blob: 237b1f4b22ffc30dc3e83993856791678e8bf7d0 [file] [log] [blame]
Chris Lattner22eb9722006-06-18 05:43:12 +00001//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Preprocessor::EvaluateDirectiveExpression method.
11//
12//===----------------------------------------------------------------------===//
13//
14// FIXME: implement testing for asserts.
15// FIXME: Parse integer constants correctly. Reject 123.0, etc.
16// FIXME: Track signed/unsigned correctly.
17// FIXME: Track and report integer overflow correctly.
18//
19//===----------------------------------------------------------------------===//
20
21#include "clang/Lex/Preprocessor.h"
22#include "clang/Basic/TokenKinds.h"
23#include "clang/Basic/Diagnostic.h"
24using namespace llvm;
25using namespace clang;
26
27/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
28/// may occur after a #if or #elif directive. Sets Result to the result of
29/// the expression. Returns false normally, true if lexing must be aborted.
30///
31/// MinPrec is the minimum precedence that this range of the expression is
32/// allowed to include.
Chris Lattnercb283342006-06-18 06:48:37 +000033void Preprocessor::EvaluateDirectiveExpression(bool &Result) {
Chris Lattner22eb9722006-06-18 05:43:12 +000034 // Peek ahead one token.
35 LexerToken Tok;
Chris Lattnercb283342006-06-18 06:48:37 +000036 Lex(Tok);
Chris Lattner22eb9722006-06-18 05:43:12 +000037
38 // In error cases, bail out with false value.
39 Result = false;
40
Chris Lattner22eb9722006-06-18 05:43:12 +000041 int ResVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000042 if (EvaluateValue(ResVal, Tok) ||
43 EvaluateDirectiveSubExpr(ResVal, 1, Tok)) {
Chris Lattner22eb9722006-06-18 05:43:12 +000044 // Skip the rest of the macro line.
Chris Lattnercb283342006-06-18 06:48:37 +000045 if (Tok.getKind() != tok::eom)
46 DiscardUntilEndOfDirective();
47 return;
Chris Lattner22eb9722006-06-18 05:43:12 +000048 }
49
50 // If we aren't at the tok::eom token, something bad happened, like an extra
51 // ')' token.
52 if (Tok.getKind() != tok::eom) {
Chris Lattnercb283342006-06-18 06:48:37 +000053 Diag(Tok, diag::err_pp_expected_eol);
54 DiscardUntilEndOfDirective();
Chris Lattner22eb9722006-06-18 05:43:12 +000055 }
56
57 Result = ResVal != 0;
Chris Lattner22eb9722006-06-18 05:43:12 +000058}
59
60/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
61/// return the computed value in Result. Return true if there was an error
Chris Lattnercb283342006-06-18 06:48:37 +000062/// parsing.
63bool Preprocessor::EvaluateValue(int &Result, LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +000064 Result = 0;
65
66 // If this token's spelling is a pp-identifier, check to see if it is
67 // 'defined' or if it is a macro. Note that we check here because many
68 // keywords are pp-identifiers, so we can't check the kind.
69 if (const IdentifierTokenInfo *II = PeekTok.getIdentifierInfo()) {
70 // If this identifier isn't 'defined' and it wasn't macro expanded, it turns
71 // into a simple 0.
72 if (strcmp(II->getName(), "defined")) {
73 Result = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000074 Lex(PeekTok);
75 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000076 }
77
78 // Handle "defined X" and "defined(X)".
79 assert(!DisableMacroExpansion &&
80 "How could macro exp already be disabled?");
81 // Turn off macro expansion.
82 DisableMacroExpansion = true;
83
84 // Get the next token.
Chris Lattnercb283342006-06-18 06:48:37 +000085 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000086
87 // Two options, it can either be a pp-identifier or a (.
88 bool InParens = false;
89 if (PeekTok.getKind() == tok::l_paren) {
90 // Found a paren, remember we saw it and skip it.
91 InParens = true;
Chris Lattnercb283342006-06-18 06:48:37 +000092 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000093 }
94
95 // If we don't have a pp-identifier now, this is an error.
96 if ((II = PeekTok.getIdentifierInfo()) == 0) {
97 DisableMacroExpansion = false;
Chris Lattnercb283342006-06-18 06:48:37 +000098 Diag(PeekTok, diag::err_pp_defined_requires_identifier);
Chris Lattner22eb9722006-06-18 05:43:12 +000099 return true;
100 }
101
102 // Otherwise, we got an identifier, is it defined to something?
103 Result = II->getMacroInfo() != 0;
104
105 // Consume identifier.
Chris Lattnercb283342006-06-18 06:48:37 +0000106 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000107
108 // If we are in parens, ensure we have a trailing ).
109 if (InParens) {
110 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000111 Diag(PeekTok, diag::err_pp_missing_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000112 return true;
113 }
114 // Consume the ).
Chris Lattnercb283342006-06-18 06:48:37 +0000115 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000116 }
117
118 DisableMacroExpansion = false;
119 return false;
120 }
121
122 switch (PeekTok.getKind()) {
123 default: // Non-value token.
Chris Lattnercb283342006-06-18 06:48:37 +0000124 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000125 return true;
126 case tok::eom:
127 case tok::r_paren:
128 // If there is no expression, report and exit.
Chris Lattnercb283342006-06-18 06:48:37 +0000129 Diag(PeekTok, diag::err_pp_expected_value_in_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000130 return true;
131 case tok::numeric_constant: {
132 // FIXME: faster. FIXME: track signs.
133 std::string Spell = Lexer::getSpelling(PeekTok, getLangOptions());
134 // FIXME: COMPUTE integer constants CORRECTLY.
135 Result = atoi(Spell.c_str());
Chris Lattnercb283342006-06-18 06:48:37 +0000136 Lex(PeekTok);
137 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +0000138 }
139 case tok::l_paren:
Chris Lattnercb283342006-06-18 06:48:37 +0000140 Lex(PeekTok); // Eat the (.
141 // Parse the value and if there are any binary operators involved, parse
142 // them.
143 if (EvaluateValue(Result, PeekTok) ||
144 EvaluateDirectiveSubExpr(Result, 1, PeekTok))
145 return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000146
147 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000148 Diag(PeekTok, diag::err_pp_expected_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000149 return true;
150 }
Chris Lattnercb283342006-06-18 06:48:37 +0000151 Lex(PeekTok); // Eat the ).
Chris Lattner22eb9722006-06-18 05:43:12 +0000152 return false;
153
154 case tok::plus:
155 // Unary plus doesn't modify the value.
Chris Lattnercb283342006-06-18 06:48:37 +0000156 Lex(PeekTok);
157 return EvaluateValue(Result, PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000158 case tok::minus:
Chris Lattnercb283342006-06-18 06:48:37 +0000159 Lex(PeekTok);
160 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000161 Result = -Result;
162 return false;
163
164 case tok::tilde:
Chris Lattnercb283342006-06-18 06:48:37 +0000165 Lex(PeekTok);
166 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000167 Result = ~Result;
168 return false;
169
170 case tok::exclaim:
Chris Lattnercb283342006-06-18 06:48:37 +0000171 Lex(PeekTok);
172 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000173 Result = !Result;
174 return false;
175
176 // FIXME: Handle #assert
177 }
178}
179
180
181
182/// getPrecedence - Return the precedence of the specified binary operator
183/// token. This returns:
184/// ~0 - Invalid token.
185/// 15 - *,/,%
186/// 14 - -,+
187/// 13 - <<,>>
188/// 12 - >=, <=, >, <
189/// 11 - ==, !=
190/// 10 - <?, >? min, max (GCC extensions)
191/// 9 - &
192/// 8 - ^
193/// 7 - |
194/// 6 - &&
195/// 5 - ||
196/// 4 - ?
197/// 3 - :
198/// 0 - eom, )
199static unsigned getPrecedence(tok::TokenKind Kind) {
200 switch (Kind) {
201 default: return ~0U;
202 case tok::percent:
203 case tok::slash:
204 case tok::star: return 15;
205 case tok::plus:
206 case tok::minus: return 14;
207 case tok::lessless:
208 case tok::greatergreater: return 13;
209 case tok::lessequal:
210 case tok::less:
211 case tok::greaterequal:
212 case tok::greater: return 12;
213 case tok::exclaimequal:
214 case tok::equalequal: return 11;
215 case tok::lessquestion:
216 case tok::greaterquestion: return 10;
217 case tok::amp: return 9;
218 case tok::caret: return 8;
219 case tok::pipe: return 7;
220 case tok::ampamp: return 6;
221 case tok::pipepipe: return 5;
222 case tok::question: return 4;
223 case tok::colon: return 3;
224 case tok::comma: return 2;
225 case tok::r_paren: return 0; // Lowest priority, end of expr.
226 case tok::eom: return 0; // Lowest priority, end of macro.
227 }
228}
229
230
231/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
232/// PeekTok, and whose precedence is PeekPrec.
233bool Preprocessor::EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
Chris Lattnercb283342006-06-18 06:48:37 +0000234 LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000235 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
236 // If this token isn't valid, report the error.
237 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000238 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000239 return true;
240 }
241
242 while (1) {
243 // If this token has a lower precedence than we are allowed to parse, return
244 // it so that higher levels of the recursion can parse it.
245 if (PeekPrec < MinPrec)
246 return false;
247
248 tok::TokenKind Operator = PeekTok.getKind();
249
250 // Consume the operator, saving the operator token for error reporting.
251 LexerToken OpToken = PeekTok;
Chris Lattnercb283342006-06-18 06:48:37 +0000252 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000253
254 int RHS;
255 // Parse the RHS of the operator.
Chris Lattnercb283342006-06-18 06:48:37 +0000256 if (EvaluateValue(RHS, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000257
258 // Remember the precedence of this operator and get the precedence of the
259 // operator immediately to the right of the RHS.
260 unsigned ThisPrec = PeekPrec;
261 PeekPrec = getPrecedence(PeekTok.getKind());
262
263 // If this token isn't valid, report the error.
264 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000265 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000266 return true;
267 }
268
269 bool isRightAssoc = Operator == tok::question;
270
271 // Get the precedence of the operator to the right of the RHS. If it binds
272 // more tightly with RHS than we do, evaluate it completely first.
273 if (ThisPrec < PeekPrec ||
274 (ThisPrec == PeekPrec && isRightAssoc)) {
Chris Lattnercb283342006-06-18 06:48:37 +0000275 if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000276 return true;
277 PeekPrec = getPrecedence(PeekTok.getKind());
278 }
279 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
280
281 switch (Operator) {
282 default: assert(0 && "Unknown operator token!");
283 case tok::percent:
284 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000285 Diag(OpToken, diag::err_pp_remainder_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000286 return true;
287 }
288 LHS %= RHS;
289 break;
290 case tok::slash:
291 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000292 Diag(OpToken, diag::err_pp_division_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000293 return true;
294 }
295 LHS /= RHS;
296 break;
297 case tok::star : LHS *= RHS; break;
298 case tok::lessless: LHS << RHS; break; // FIXME: shift amt overflow?
299 case tok::greatergreater: LHS >> RHS; break; // FIXME: signed vs unsigned
300 case tok::plus : LHS += RHS; break;
301 case tok::minus: LHS -= RHS; break;
302 case tok::lessequal: LHS = LHS <= RHS; break;
303 case tok::less: LHS = LHS < RHS; break;
304 case tok::greaterequal: LHS = LHS >= RHS; break;
305 case tok::greater: LHS = LHS > RHS; break;
306 case tok::exclaimequal: LHS = LHS != RHS; break;
307 case tok::equalequal: LHS = LHS == RHS; break;
308 case tok::lessquestion: // Deprecation warning emitted by the lexer.
309 LHS = std::min(LHS, RHS);
310 break;
311 case tok::greaterquestion: // Deprecation warning emitted by the lexer.
312 LHS = std::max(LHS, RHS);
313 break;
314 case tok::amp: LHS &= RHS; break;
315 case tok::caret: LHS ^= RHS; break;
316 case tok::pipe: LHS |= RHS; break;
317 case tok::ampamp: LHS = LHS && RHS; break;
318 case tok::pipepipe: LHS = LHS || RHS; break;
319 case tok::comma:
Chris Lattnercb283342006-06-18 06:48:37 +0000320 Diag(OpToken, diag::ext_pp_comma_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000321 LHS = RHS; // LHS = LHS,RHS -> RHS.
322 break;
323 case tok::question: {
324 // Parse the : part of the expression.
325 if (PeekTok.getKind() != tok::colon) {
Chris Lattnercb283342006-06-18 06:48:37 +0000326 Diag(OpToken, diag::err_pp_question_without_colon);
Chris Lattner22eb9722006-06-18 05:43:12 +0000327 return true;
328 }
329 // Consume the :.
Chris Lattnercb283342006-06-18 06:48:37 +0000330 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000331
332 // Evaluate the value after the :.
333 int AfterColonVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +0000334 if (EvaluateValue(AfterColonVal, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000335
336 // Parse anything after the : RHS that has a higher precedence than ?.
337 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
Chris Lattnercb283342006-06-18 06:48:37 +0000338 PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000339 return true;
340
341 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
342 LHS = LHS ? RHS : AfterColonVal;
343
344 // Figure out the precedence of the token after the : part.
345 PeekPrec = getPrecedence(PeekTok.getKind());
346 break;
347 }
348 case tok::colon:
349 // Don't allow :'s to float around without being part of ?: exprs.
Chris Lattnercb283342006-06-18 06:48:37 +0000350 Diag(OpToken, diag::err_pp_colon_without_question);
Chris Lattner22eb9722006-06-18 05:43:12 +0000351 return true;
352 }
353 }
354
355 return false;
356}