 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
60.3% |
79 / 131 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
80.2% |
105 / 131 |
| |
|
Line Coverage: |
76.2% |
80 / 105 |
| |
 |
|
 |
1 : //===--- TokenConcatenation.cpp - Token Concatenation Avoidance -----------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements the TokenConcatenation class.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Lex/TokenConcatenation.h"
15 : #include "clang/Lex/Preprocessor.h"
16 : using namespace clang;
17 :
18 :
19 : /// StartsWithL - Return true if the spelling of this token starts with 'L'.
20 1: bool TokenConcatenation::StartsWithL(const Token &Tok) const {
1: branch 1 taken
0: branch 2 not taken
21 1: if (!Tok.needsCleaning()) {
22 1: SourceManager &SM = PP.getSourceManager();
23 1: return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())) == 'L';
24 : }
25 :
0: branch 1 not taken
0: branch 2 not taken
26 0: if (Tok.getLength() < 256) {
27 : char Buffer[256];
28 0: const char *TokPtr = Buffer;
29 0: PP.getSpelling(Tok, TokPtr);
30 0: return TokPtr[0] == 'L';
31 : }
32 :
33 0: return PP.getSpelling(Tok)[0] == 'L';
34 : }
35 :
36 : /// IsIdentifierL - Return true if the spelling of this token is literally
37 : /// 'L'.
38 1: bool TokenConcatenation::IsIdentifierL(const Token &Tok) const {
1: branch 1 taken
0: branch 2 not taken
39 1: if (!Tok.needsCleaning()) {
0: branch 1 not taken
1: branch 2 taken
40 1: if (Tok.getLength() != 1)
41 0: return false;
42 1: SourceManager &SM = PP.getSourceManager();
43 1: return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation())) == 'L';
44 : }
45 :
0: branch 1 not taken
0: branch 2 not taken
46 0: if (Tok.getLength() < 256) {
47 : char Buffer[256];
48 0: const char *TokPtr = Buffer;
0: branch 1 not taken
0: branch 2 not taken
49 0: if (PP.getSpelling(Tok, TokPtr) != 1)
50 0: return false;
51 0: return TokPtr[0] == 'L';
52 : }
53 :
54 0: return PP.getSpelling(Tok) == "L";
55 : }
56 :
57 204: TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
58 204: memset(TokenInfo, 0, sizeof(TokenInfo));
59 :
60 : // These tokens have custom code in AvoidConcat.
61 204: TokenInfo[tok::identifier ] |= aci_custom;
62 204: TokenInfo[tok::numeric_constant] |= aci_custom_firstchar;
63 204: TokenInfo[tok::period ] |= aci_custom_firstchar;
64 204: TokenInfo[tok::amp ] |= aci_custom_firstchar;
65 204: TokenInfo[tok::plus ] |= aci_custom_firstchar;
66 204: TokenInfo[tok::minus ] |= aci_custom_firstchar;
67 204: TokenInfo[tok::slash ] |= aci_custom_firstchar;
68 204: TokenInfo[tok::less ] |= aci_custom_firstchar;
69 204: TokenInfo[tok::greater ] |= aci_custom_firstchar;
70 204: TokenInfo[tok::pipe ] |= aci_custom_firstchar;
71 204: TokenInfo[tok::percent ] |= aci_custom_firstchar;
72 204: TokenInfo[tok::colon ] |= aci_custom_firstchar;
73 204: TokenInfo[tok::hash ] |= aci_custom_firstchar;
74 204: TokenInfo[tok::arrow ] |= aci_custom_firstchar;
75 :
76 : // These tokens change behavior if followed by an '='.
77 204: TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
78 204: TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
79 204: TokenInfo[tok::minus ] |= aci_avoid_equal; // -=
80 204: TokenInfo[tok::slash ] |= aci_avoid_equal; // /=
81 204: TokenInfo[tok::less ] |= aci_avoid_equal; // <=
82 204: TokenInfo[tok::greater ] |= aci_avoid_equal; // >=
83 204: TokenInfo[tok::pipe ] |= aci_avoid_equal; // |=
84 204: TokenInfo[tok::percent ] |= aci_avoid_equal; // %=
85 204: TokenInfo[tok::star ] |= aci_avoid_equal; // *=
86 204: TokenInfo[tok::exclaim ] |= aci_avoid_equal; // !=
87 204: TokenInfo[tok::lessless ] |= aci_avoid_equal; // <<=
88 204: TokenInfo[tok::greaterequal] |= aci_avoid_equal; // >>=
89 204: TokenInfo[tok::caret ] |= aci_avoid_equal; // ^=
90 204: TokenInfo[tok::equal ] |= aci_avoid_equal; // ==
91 204: }
92 :
93 : /// GetFirstChar - Get the first character of the token \arg Tok,
94 : /// avoiding calls to getSpelling where possible.
95 998: static char GetFirstChar(Preprocessor &PP, const Token &Tok) {
14: branch 1 taken
984: branch 2 taken
96 998: if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
97 : // Avoid spelling identifiers, the most common form of token.
98 14: return II->getNameStart()[0];
984: branch 1 taken
0: branch 2 not taken
99 984: } else if (!Tok.needsCleaning()) {
437: branch 1 taken
547: branch 2 taken
437: branch 4 taken
0: branch 5 not taken
437: branch 6 taken
547: branch 7 taken
100 984: if (Tok.isLiteral() && Tok.getLiteralData()) {
101 437: return *Tok.getLiteralData();
102 : } else {
103 547: SourceManager &SM = PP.getSourceManager();
104 547: return *SM.getCharacterData(SM.getSpellingLoc(Tok.getLocation()));
105 : }
0: branch 1 not taken
0: branch 2 not taken
106 0: } else if (Tok.getLength() < 256) {
107 : char Buffer[256];
108 0: const char *TokPtr = Buffer;
109 0: PP.getSpelling(Tok, TokPtr);
110 0: return TokPtr[0];
111 : } else {
112 0: return PP.getSpelling(Tok)[0];
113 : }
114 : }
115 :
116 : /// AvoidConcat - If printing PrevTok immediately followed by Tok would cause
117 : /// the two individual tokens to be lexed as a single token, return true
118 : /// (which causes a space to be printed between them). This allows the output
119 : /// of -E mode to be lexed to the same token stream as lexing the input
120 : /// directly would.
121 : ///
122 : /// This code must conservatively return true if it doesn't want to be 100%
123 : /// accurate. This will cause the output to include extra space characters,
124 : /// but the resulting output won't have incorrect concatenations going on.
125 : /// Examples include "..", which we print with a space between, because we
126 : /// don't want to track enough to tell "x.." from "...".
127 : bool TokenConcatenation::AvoidConcat(const Token &PrevTok,
128 4621: const Token &Tok) const {
129 : // First, check to see if the tokens were directly adjacent in the original
130 : // source. If they were, it must be okay to stick them together: if there
131 : // were an issue, the tokens would have been lexed differently.
2599: branch 2 taken
2022: branch 3 taken
2580: branch 6 taken
19: branch 7 taken
2528: branch 13 taken
52: branch 14 taken
2528: branch 15 taken
2093: branch 16 taken
132 4621: if (PrevTok.getLocation().isFileID() && Tok.getLocation().isFileID() &&
133 : PrevTok.getLocation().getFileLocWithOffset(PrevTok.getLength()) ==
134 : Tok.getLocation())
135 2528: return false;
136 :
137 2093: tok::TokenKind PrevKind = PrevTok.getKind();
324: branch 1 taken
1769: branch 2 taken
138 2093: if (PrevTok.getIdentifierInfo()) // Language keyword or named operator.
139 324: PrevKind = tok::identifier;
140 :
141 : // Look up information on when we should avoid concatenation with prevtok.
142 2093: unsigned ConcatInfo = TokenInfo[PrevKind];
143 :
144 : // If prevtok never causes a problem for anything after it, return quickly.
746: branch 0 taken
1347: branch 1 taken
145 2093: if (ConcatInfo == 0) return false;
146 :
469: branch 0 taken
878: branch 1 taken
147 1347: if (ConcatInfo & aci_avoid_equal) {
148 : // If the next token is '=' or '==', avoid concatenation.
467: branch 1 taken
2: branch 2 taken
0: branch 4 not taken
467: branch 5 taken
2: branch 6 taken
467: branch 7 taken
149 469: if (Tok.is(tok::equal) || Tok.is(tok::equalequal))
150 2: return true;
151 467: ConcatInfo &= ~aci_avoid_equal;
152 : }
153 :
33: branch 0 taken
1312: branch 1 taken
154 1345: if (ConcatInfo == 0) return false;
155 :
156 : // Basic algorithm: we look at the first character of the second token, and
157 : // determine whether it, if appended to the first token, would form (or
158 : // would contribute) to a larger token if concatenated.
159 1312: char FirstChar = 0;
988: branch 0 taken
324: branch 1 taken
160 1312: if (ConcatInfo & aci_custom) {
161 : // If the token does not need to know the first character, don't get it.
162 : } else {
163 988: FirstChar = GetFirstChar(PP, Tok);
164 : }
165 :
0: branch 0 not taken
324: branch 1 taken
536: branch 2 taken
6: branch 3 taken
0: branch 4 not taken
7: branch 5 taken
425: branch 6 taken
0: branch 7 not taken
0: branch 8 not taken
1: branch 9 taken
0: branch 10 not taken
1: branch 11 taken
9: branch 12 taken
3: branch 13 taken
0: branch 14 not taken
166 1312: switch (PrevKind) {
167 0: default: assert(0 && "InitAvoidConcatTokenInfo built wrong");
168 : case tok::identifier: // id+id or id+number or id+L"foo".
169 : // id+'.'... will not append.
10: branch 1 taken
314: branch 2 taken
170 324: if (Tok.is(tok::numeric_constant))
171 10: return GetFirstChar(PP, Tok) != '.';
172 :
314: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
314: branch 5 taken
0: branch 6 not taken
314: branch 7 taken
173 314: if (Tok.getIdentifierInfo() || Tok.is(tok::wide_string_literal) /* ||
174 : Tok.is(tok::wide_char_literal)*/)
175 0: return true;
176 :
177 : // If this isn't identifier + string, we're done.
314: branch 1 taken
0: branch 2 not taken
313: branch 4 taken
1: branch 5 taken
313: branch 6 taken
1: branch 7 taken
178 314: if (Tok.isNot(tok::char_constant) && Tok.isNot(tok::string_literal))
179 313: return false;
180 :
181 : // FIXME: need a wide_char_constant!
182 :
183 : // If the string was a wide string L"foo" or wide char L'f', it would
184 : // concat with the previous identifier into fooL"bar". Avoid this.
0: branch 1 not taken
1: branch 2 taken
185 1: if (StartsWithL(Tok))
186 0: return true;
187 :
188 : // Otherwise, this is a narrow character or string. If the *identifier*
189 : // is a literal 'L', avoid pasting L "foo" -> L"foo".
190 1: return IsIdentifierL(PrevTok);
191 : case tok::numeric_constant:
192 : return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
536: branch 1 taken
0: branch 2 not taken
536: branch 4 taken
0: branch 5 not taken
532: branch 6 taken
4: branch 7 taken
322: branch 8 taken
210: branch 9 taken
0: branch 10 not taken
322: branch 11 taken
193 536: FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
194 : case tok::period: // ..., .*, .1234
195 : return FirstChar == '.' || isdigit(FirstChar) ||
3: branch 0 taken
3: branch 1 taken
3: branch 2 taken
0: branch 3 not taken
0: branch 5 not taken
3: branch 6 taken
3: branch 7 taken
3: branch 8 taken
196 6: (PP.getLangOptions().CPlusPlus && FirstChar == '*');
197 : case tok::amp: // &&
198 0: return FirstChar == '&';
199 : case tok::plus: // ++
200 7: return FirstChar == '+';
201 : case tok::minus: // --, ->, ->*
424: branch 0 taken
1: branch 1 taken
0: branch 2 not taken
424: branch 3 taken
202 425: return FirstChar == '-' || FirstChar == '>';
203 : case tok::slash: //, /*, //
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
204 0: return FirstChar == '*' || FirstChar == '/';
205 : case tok::less: // <<, <<=, <:, <%
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
206 0: return FirstChar == '<' || FirstChar == ':' || FirstChar == '%';
207 : case tok::greater: // >>, >>=
208 1: return FirstChar == '>';
209 : case tok::pipe: // ||
210 0: return FirstChar == '|';
211 : case tok::percent: // %>, %:
1: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
1: branch 3 taken
212 1: return FirstChar == '>' || FirstChar == ':';
213 : case tok::colon: // ::, :>
214 : return FirstChar == '>' ||
9: branch 0 taken
0: branch 1 not taken
0: branch 3 not taken
9: branch 4 taken
9: branch 5 taken
9: branch 6 taken
215 9: (PP.getLangOptions().CPlusPlus && FirstChar == ':');
216 : case tok::hash: // ##, #@, %:%:
3: branch 0 taken
0: branch 1 not taken
3: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
3: branch 5 taken
217 3: return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
218 : case tok::arrow: // ->*
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
219 0: return PP.getLangOptions().CPlusPlus && FirstChar == '*';
220 : }
221 : }
Generated: 2010-02-10 01:31 by zcov