Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 1 | //===--- TokenConcatenation.cpp - Token Concatenation Avoidance -----------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame^] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the TokenConcatenation class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "clang/Lex/TokenConcatenation.h" |
Jordan Rose | a08ed59 | 2013-02-08 22:30:31 +0000 | [diff] [blame] | 14 | #include "clang/Basic/CharInfo.h" |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 15 | #include "clang/Lex/Preprocessor.h" |
Abramo Bagnara | ea4f7c7 | 2010-12-22 08:23:18 +0000 | [diff] [blame] | 16 | #include "llvm/Support/ErrorHandling.h" |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 17 | using namespace clang; |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 18 | |
| 19 | |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 20 | /// IsStringPrefix - Return true if Str is a string prefix. |
| 21 | /// 'L', 'u', 'U', or 'u8'. Including raw versions. |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 22 | static bool IsStringPrefix(StringRef Str, bool CPlusPlus11) { |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 23 | |
| 24 | if (Str[0] == 'L' || |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 25 | (CPlusPlus11 && (Str[0] == 'u' || Str[0] == 'U' || Str[0] == 'R'))) { |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 26 | |
| 27 | if (Str.size() == 1) |
| 28 | return true; // "L", "u", "U", and "R" |
| 29 | |
| 30 | // Check for raw flavors. Need to make sure the first character wasn't |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 31 | // already R. Need CPlusPlus11 check for "LR". |
| 32 | if (Str[1] == 'R' && Str[0] != 'R' && Str.size() == 2 && CPlusPlus11) |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 33 | return true; // "LR", "uR", "UR" |
| 34 | |
| 35 | // Check for "u8" and "u8R" |
| 36 | if (Str[0] == 'u' && Str[1] == '8') { |
| 37 | if (Str.size() == 2) return true; // "u8" |
| 38 | if (Str.size() == 3 && Str[2] == 'R') return true; // "u8R" |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | return false; |
| 43 | } |
| 44 | |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 45 | /// IsIdentifierStringPrefix - Return true if the spelling of the token |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 46 | /// is literally 'L', 'u', 'U', or 'u8'. Including raw versions. |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 47 | bool TokenConcatenation::IsIdentifierStringPrefix(const Token &Tok) const { |
David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 48 | const LangOptions &LangOpts = PP.getLangOpts(); |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 49 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 50 | if (!Tok.needsCleaning()) { |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 51 | if (Tok.getLength() < 1 || Tok.getLength() > 3) |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 52 | return false; |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 53 | SourceManager &SM = PP.getSourceManager(); |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 54 | const char *Ptr = SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())); |
Craig Topper | 54edcca | 2011-08-11 04:06:15 +0000 | [diff] [blame] | 55 | return IsStringPrefix(StringRef(Ptr, Tok.getLength()), |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 56 | LangOpts.CPlusPlus11); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 57 | } |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 58 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 59 | if (Tok.getLength() < 256) { |
| 60 | char Buffer[256]; |
| 61 | const char *TokPtr = Buffer; |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 62 | unsigned length = PP.getSpelling(Tok, TokPtr); |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 63 | return IsStringPrefix(StringRef(TokPtr, length), LangOpts.CPlusPlus11); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 64 | } |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 65 | |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 66 | return IsStringPrefix(StringRef(PP.getSpelling(Tok)), LangOpts.CPlusPlus11); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 67 | } |
| 68 | |
Kristof Umann | b416dbf | 2018-09-27 12:40:16 +0000 | [diff] [blame] | 69 | TokenConcatenation::TokenConcatenation(const Preprocessor &pp) : PP(pp) { |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 70 | memset(TokenInfo, 0, sizeof(TokenInfo)); |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 71 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 72 | // These tokens have custom code in AvoidConcat. |
| 73 | TokenInfo[tok::identifier ] |= aci_custom; |
| 74 | TokenInfo[tok::numeric_constant] |= aci_custom_firstchar; |
| 75 | TokenInfo[tok::period ] |= aci_custom_firstchar; |
| 76 | TokenInfo[tok::amp ] |= aci_custom_firstchar; |
| 77 | TokenInfo[tok::plus ] |= aci_custom_firstchar; |
| 78 | TokenInfo[tok::minus ] |= aci_custom_firstchar; |
| 79 | TokenInfo[tok::slash ] |= aci_custom_firstchar; |
| 80 | TokenInfo[tok::less ] |= aci_custom_firstchar; |
| 81 | TokenInfo[tok::greater ] |= aci_custom_firstchar; |
| 82 | TokenInfo[tok::pipe ] |= aci_custom_firstchar; |
| 83 | TokenInfo[tok::percent ] |= aci_custom_firstchar; |
| 84 | TokenInfo[tok::colon ] |= aci_custom_firstchar; |
| 85 | TokenInfo[tok::hash ] |= aci_custom_firstchar; |
| 86 | TokenInfo[tok::arrow ] |= aci_custom_firstchar; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 87 | |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 88 | // These tokens have custom code in C++11 mode. |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 89 | if (PP.getLangOpts().CPlusPlus11) { |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 90 | TokenInfo[tok::string_literal ] |= aci_custom; |
| 91 | TokenInfo[tok::wide_string_literal ] |= aci_custom; |
| 92 | TokenInfo[tok::utf8_string_literal ] |= aci_custom; |
| 93 | TokenInfo[tok::utf16_string_literal] |= aci_custom; |
| 94 | TokenInfo[tok::utf32_string_literal] |= aci_custom; |
| 95 | TokenInfo[tok::char_constant ] |= aci_custom; |
| 96 | TokenInfo[tok::wide_char_constant ] |= aci_custom; |
| 97 | TokenInfo[tok::utf16_char_constant ] |= aci_custom; |
| 98 | TokenInfo[tok::utf32_char_constant ] |= aci_custom; |
| 99 | } |
| 100 | |
Aaron Ballman | c351fba | 2017-12-04 20:27:34 +0000 | [diff] [blame] | 101 | // These tokens have custom code in C++17 mode. |
| 102 | if (PP.getLangOpts().CPlusPlus17) |
Richard Smith | 3e3a705 | 2014-11-08 06:08:42 +0000 | [diff] [blame] | 103 | TokenInfo[tok::utf8_char_constant] |= aci_custom; |
| 104 | |
Richard Smith | edbf597 | 2017-12-01 01:07:10 +0000 | [diff] [blame] | 105 | // These tokens have custom code in C++2a mode. |
| 106 | if (PP.getLangOpts().CPlusPlus2a) |
| 107 | TokenInfo[tok::lessequal ] |= aci_custom_firstchar; |
| 108 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 109 | // These tokens change behavior if followed by an '='. |
| 110 | TokenInfo[tok::amp ] |= aci_avoid_equal; // &= |
| 111 | TokenInfo[tok::plus ] |= aci_avoid_equal; // += |
| 112 | TokenInfo[tok::minus ] |= aci_avoid_equal; // -= |
| 113 | TokenInfo[tok::slash ] |= aci_avoid_equal; // /= |
| 114 | TokenInfo[tok::less ] |= aci_avoid_equal; // <= |
| 115 | TokenInfo[tok::greater ] |= aci_avoid_equal; // >= |
| 116 | TokenInfo[tok::pipe ] |= aci_avoid_equal; // |= |
| 117 | TokenInfo[tok::percent ] |= aci_avoid_equal; // %= |
| 118 | TokenInfo[tok::star ] |= aci_avoid_equal; // *= |
| 119 | TokenInfo[tok::exclaim ] |= aci_avoid_equal; // != |
| 120 | TokenInfo[tok::lessless ] |= aci_avoid_equal; // <<= |
Chris Lattner | 80dbccd | 2010-03-26 17:10:02 +0000 | [diff] [blame] | 121 | TokenInfo[tok::greatergreater] |= aci_avoid_equal; // >>= |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 122 | TokenInfo[tok::caret ] |= aci_avoid_equal; // ^= |
| 123 | TokenInfo[tok::equal ] |= aci_avoid_equal; // == |
| 124 | } |
| 125 | |
Daniel Dunbar | dc78bd9 | 2009-03-18 03:32:24 +0000 | [diff] [blame] | 126 | /// GetFirstChar - Get the first character of the token \arg Tok, |
| 127 | /// avoiding calls to getSpelling where possible. |
Kristof Umann | b416dbf | 2018-09-27 12:40:16 +0000 | [diff] [blame] | 128 | static char GetFirstChar(const Preprocessor &PP, const Token &Tok) { |
Daniel Dunbar | dc78bd9 | 2009-03-18 03:32:24 +0000 | [diff] [blame] | 129 | if (IdentifierInfo *II = Tok.getIdentifierInfo()) { |
| 130 | // Avoid spelling identifiers, the most common form of token. |
Daniel Dunbar | 2c422dc9 | 2009-10-18 20:26:12 +0000 | [diff] [blame] | 131 | return II->getNameStart()[0]; |
Daniel Dunbar | dc78bd9 | 2009-03-18 03:32:24 +0000 | [diff] [blame] | 132 | } else if (!Tok.needsCleaning()) { |
| 133 | if (Tok.isLiteral() && Tok.getLiteralData()) { |
| 134 | return *Tok.getLiteralData(); |
| 135 | } else { |
| 136 | SourceManager &SM = PP.getSourceManager(); |
| 137 | return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())); |
| 138 | } |
| 139 | } else if (Tok.getLength() < 256) { |
| 140 | char Buffer[256]; |
| 141 | const char *TokPtr = Buffer; |
| 142 | PP.getSpelling(Tok, TokPtr); |
| 143 | return TokPtr[0]; |
| 144 | } else { |
| 145 | return PP.getSpelling(Tok)[0]; |
| 146 | } |
| 147 | } |
| 148 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 149 | /// AvoidConcat - If printing PrevTok immediately followed by Tok would cause |
| 150 | /// the two individual tokens to be lexed as a single token, return true |
| 151 | /// (which causes a space to be printed between them). This allows the output |
| 152 | /// of -E mode to be lexed to the same token stream as lexing the input |
| 153 | /// directly would. |
| 154 | /// |
| 155 | /// This code must conservatively return true if it doesn't want to be 100% |
| 156 | /// accurate. This will cause the output to include extra space characters, |
| 157 | /// but the resulting output won't have incorrect concatenations going on. |
| 158 | /// Examples include "..", which we print with a space between, because we |
| 159 | /// don't want to track enough to tell "x.." from "...". |
Chris Lattner | 0384e635 | 2010-04-14 03:57:19 +0000 | [diff] [blame] | 160 | bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok, |
| 161 | const Token &PrevTok, |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 162 | const Token &Tok) const { |
Chris Lattner | ca515cc | 2009-04-21 23:28:41 +0000 | [diff] [blame] | 163 | // First, check to see if the tokens were directly adjacent in the original |
| 164 | // source. If they were, it must be okay to stick them together: if there |
| 165 | // were an issue, the tokens would have been lexed differently. |
Argyrios Kyrtzidis | 005206a8 | 2013-01-29 20:28:24 +0000 | [diff] [blame] | 166 | SourceManager &SM = PP.getSourceManager(); |
| 167 | SourceLocation PrevSpellLoc = SM.getSpellingLoc(PrevTok.getLocation()); |
| 168 | SourceLocation SpellLoc = SM.getSpellingLoc(Tok.getLocation()); |
| 169 | if (PrevSpellLoc.getLocWithOffset(PrevTok.getLength()) == SpellLoc) |
Chris Lattner | ca515cc | 2009-04-21 23:28:41 +0000 | [diff] [blame] | 170 | return false; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 171 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 172 | tok::TokenKind PrevKind = PrevTok.getKind(); |
Ben Langmuir | 5418f40 | 2014-09-10 21:29:41 +0000 | [diff] [blame] | 173 | if (!PrevTok.isAnnotation() && PrevTok.getIdentifierInfo()) |
| 174 | PrevKind = tok::identifier; // Language keyword or named operator. |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 175 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 176 | // Look up information on when we should avoid concatenation with prevtok. |
| 177 | unsigned ConcatInfo = TokenInfo[PrevKind]; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 178 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 179 | // If prevtok never causes a problem for anything after it, return quickly. |
| 180 | if (ConcatInfo == 0) return false; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 181 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 182 | if (ConcatInfo & aci_avoid_equal) { |
| 183 | // If the next token is '=' or '==', avoid concatenation. |
Daniel Marjamaki | e59f8d7 | 2015-06-18 10:59:26 +0000 | [diff] [blame] | 184 | if (Tok.isOneOf(tok::equal, tok::equalequal)) |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 185 | return true; |
| 186 | ConcatInfo &= ~aci_avoid_equal; |
| 187 | } |
Ben Langmuir | 5418f40 | 2014-09-10 21:29:41 +0000 | [diff] [blame] | 188 | if (Tok.isAnnotation()) { |
| 189 | // Modules annotation can show up when generated automatically for includes. |
Daniel Marjamaki | e59f8d7 | 2015-06-18 10:59:26 +0000 | [diff] [blame] | 190 | assert(Tok.isOneOf(tok::annot_module_include, tok::annot_module_begin, |
| 191 | tok::annot_module_end) && |
Ben Langmuir | 5418f40 | 2014-09-10 21:29:41 +0000 | [diff] [blame] | 192 | "unexpected annotation in AvoidConcat"); |
| 193 | ConcatInfo = 0; |
| 194 | } |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 195 | |
Daniel Marjamaki | e59f8d7 | 2015-06-18 10:59:26 +0000 | [diff] [blame] | 196 | if (ConcatInfo == 0) |
| 197 | return false; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 198 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 199 | // Basic algorithm: we look at the first character of the second token, and |
| 200 | // determine whether it, if appended to the first token, would form (or |
| 201 | // would contribute) to a larger token if concatenated. |
| 202 | char FirstChar = 0; |
| 203 | if (ConcatInfo & aci_custom) { |
| 204 | // If the token does not need to know the first character, don't get it. |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 205 | } else { |
Daniel Dunbar | dc78bd9 | 2009-03-18 03:32:24 +0000 | [diff] [blame] | 206 | FirstChar = GetFirstChar(PP, Tok); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 207 | } |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 208 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 209 | switch (PrevKind) { |
Abramo Bagnara | ea4f7c7 | 2010-12-22 08:23:18 +0000 | [diff] [blame] | 210 | default: |
| 211 | llvm_unreachable("InitAvoidConcatTokenInfo built wrong"); |
Abramo Bagnara | ea4f7c7 | 2010-12-22 08:23:18 +0000 | [diff] [blame] | 212 | |
| 213 | case tok::raw_identifier: |
| 214 | llvm_unreachable("tok::raw_identifier in non-raw lexing mode!"); |
Abramo Bagnara | ea4f7c7 | 2010-12-22 08:23:18 +0000 | [diff] [blame] | 215 | |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 216 | case tok::string_literal: |
| 217 | case tok::wide_string_literal: |
| 218 | case tok::utf8_string_literal: |
| 219 | case tok::utf16_string_literal: |
| 220 | case tok::utf32_string_literal: |
| 221 | case tok::char_constant: |
| 222 | case tok::wide_char_constant: |
Richard Smith | 3e3a705 | 2014-11-08 06:08:42 +0000 | [diff] [blame] | 223 | case tok::utf8_char_constant: |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 224 | case tok::utf16_char_constant: |
| 225 | case tok::utf32_char_constant: |
Richard Smith | 2bf7fdb | 2013-01-02 11:42:31 +0000 | [diff] [blame] | 226 | if (!PP.getLangOpts().CPlusPlus11) |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 227 | return false; |
| 228 | |
| 229 | // In C++11, a string or character literal followed by an identifier is a |
| 230 | // single token. |
Ben Langmuir | 5eb7cb7 | 2014-01-30 21:50:18 +0000 | [diff] [blame] | 231 | if (Tok.getIdentifierInfo()) |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 232 | return true; |
| 233 | |
| 234 | // A ud-suffix is an identifier. If the previous token ends with one, treat |
| 235 | // it as an identifier. |
| 236 | if (!PrevTok.hasUDSuffix()) |
| 237 | return false; |
Erik Verbruggen | e4fd652 | 2016-10-26 13:06:13 +0000 | [diff] [blame] | 238 | LLVM_FALLTHROUGH; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 239 | case tok::identifier: // id+id or id+number or id+L"foo". |
Daniel Dunbar | dc78bd9 | 2009-03-18 03:32:24 +0000 | [diff] [blame] | 240 | // id+'.'... will not append. |
| 241 | if (Tok.is(tok::numeric_constant)) |
| 242 | return GetFirstChar(PP, Tok) != '.'; |
| 243 | |
Daniel Marjamaki | e59f8d7 | 2015-06-18 10:59:26 +0000 | [diff] [blame] | 244 | if (Tok.getIdentifierInfo() || |
| 245 | Tok.isOneOf(tok::wide_string_literal, tok::utf8_string_literal, |
| 246 | tok::utf16_string_literal, tok::utf32_string_literal, |
| 247 | tok::wide_char_constant, tok::utf8_char_constant, |
| 248 | tok::utf16_char_constant, tok::utf32_char_constant)) |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 249 | return true; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 250 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 251 | // If this isn't identifier + string, we're done. |
| 252 | if (Tok.isNot(tok::char_constant) && Tok.isNot(tok::string_literal)) |
| 253 | return false; |
Mike Stump | 11289f4 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 254 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 255 | // Otherwise, this is a narrow character or string. If the *identifier* |
Douglas Gregor | fb65e59 | 2011-07-27 05:40:30 +0000 | [diff] [blame] | 256 | // is a literal 'L', 'u8', 'u' or 'U', avoid pasting L "foo" -> L"foo". |
| 257 | return IsIdentifierStringPrefix(PrevTok); |
Richard Smith | d67aea2 | 2012-03-06 03:21:47 +0000 | [diff] [blame] | 258 | |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 259 | case tok::numeric_constant: |
Jordan Rose | a08ed59 | 2013-02-08 22:30:31 +0000 | [diff] [blame] | 260 | return isPreprocessingNumberBody(FirstChar) || |
| 261 | FirstChar == '+' || FirstChar == '-'; |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 262 | case tok::period: // ..., .*, .1234 |
Chris Lattner | 0384e635 | 2010-04-14 03:57:19 +0000 | [diff] [blame] | 263 | return (FirstChar == '.' && PrevPrevTok.is(tok::period)) || |
Jordan Rose | a08ed59 | 2013-02-08 22:30:31 +0000 | [diff] [blame] | 264 | isDigit(FirstChar) || |
| 265 | (PP.getLangOpts().CPlusPlus && FirstChar == '*'); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 266 | case tok::amp: // && |
| 267 | return FirstChar == '&'; |
| 268 | case tok::plus: // ++ |
| 269 | return FirstChar == '+'; |
| 270 | case tok::minus: // --, ->, ->* |
| 271 | return FirstChar == '-' || FirstChar == '>'; |
| 272 | case tok::slash: //, /*, // |
| 273 | return FirstChar == '*' || FirstChar == '/'; |
| 274 | case tok::less: // <<, <<=, <:, <% |
| 275 | return FirstChar == '<' || FirstChar == ':' || FirstChar == '%'; |
| 276 | case tok::greater: // >>, >>= |
| 277 | return FirstChar == '>'; |
| 278 | case tok::pipe: // || |
| 279 | return FirstChar == '|'; |
| 280 | case tok::percent: // %>, %: |
Eli Friedman | 98dbc1c | 2009-05-27 22:33:06 +0000 | [diff] [blame] | 281 | return FirstChar == '>' || FirstChar == ':'; |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 282 | case tok::colon: // ::, :> |
Eli Friedman | dd2ab96 | 2009-06-15 19:48:50 +0000 | [diff] [blame] | 283 | return FirstChar == '>' || |
David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 284 | (PP.getLangOpts().CPlusPlus && FirstChar == ':'); |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 285 | case tok::hash: // ##, #@, %:%: |
| 286 | return FirstChar == '#' || FirstChar == '@' || FirstChar == '%'; |
| 287 | case tok::arrow: // ->* |
David Blaikie | bbafb8a | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 288 | return PP.getLangOpts().CPlusPlus && FirstChar == '*'; |
Richard Smith | edbf597 | 2017-12-01 01:07:10 +0000 | [diff] [blame] | 289 | case tok::lessequal: // <=> (C++2a) |
| 290 | return PP.getLangOpts().CPlusPlus2a && FirstChar == '>'; |
Chris Lattner | 644d452 | 2009-02-13 00:46:04 +0000 | [diff] [blame] | 291 | } |
| 292 | } |