blob: 3eeb3d90f935982b46d1782072fab8b9fd6d8d57 [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 Lattner7966aaf2006-06-18 06:50:36 +000033bool Preprocessor::EvaluateDirectiveExpression() {
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
Chris Lattner22eb9722006-06-18 05:43:12 +000038 int ResVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000039 if (EvaluateValue(ResVal, Tok) ||
40 EvaluateDirectiveSubExpr(ResVal, 1, Tok)) {
Chris Lattner22eb9722006-06-18 05:43:12 +000041 // Skip the rest of the macro line.
Chris Lattnercb283342006-06-18 06:48:37 +000042 if (Tok.getKind() != tok::eom)
43 DiscardUntilEndOfDirective();
Chris Lattner7966aaf2006-06-18 06:50:36 +000044 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000045 }
46
47 // If we aren't at the tok::eom token, something bad happened, like an extra
48 // ')' token.
49 if (Tok.getKind() != tok::eom) {
Chris Lattnercb283342006-06-18 06:48:37 +000050 Diag(Tok, diag::err_pp_expected_eol);
51 DiscardUntilEndOfDirective();
Chris Lattner22eb9722006-06-18 05:43:12 +000052 }
53
Chris Lattner7966aaf2006-06-18 06:50:36 +000054 return ResVal != 0;
Chris Lattner22eb9722006-06-18 05:43:12 +000055}
56
57/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
58/// return the computed value in Result. Return true if there was an error
Chris Lattnercb283342006-06-18 06:48:37 +000059/// parsing.
60bool Preprocessor::EvaluateValue(int &Result, LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +000061 Result = 0;
62
63 // If this token's spelling is a pp-identifier, check to see if it is
64 // 'defined' or if it is a macro. Note that we check here because many
65 // keywords are pp-identifiers, so we can't check the kind.
66 if (const IdentifierTokenInfo *II = PeekTok.getIdentifierInfo()) {
67 // If this identifier isn't 'defined' and it wasn't macro expanded, it turns
68 // into a simple 0.
69 if (strcmp(II->getName(), "defined")) {
70 Result = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000071 Lex(PeekTok);
72 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000073 }
74
75 // Handle "defined X" and "defined(X)".
76 assert(!DisableMacroExpansion &&
77 "How could macro exp already be disabled?");
78 // Turn off macro expansion.
79 DisableMacroExpansion = true;
80
81 // Get the next token.
Chris Lattnercb283342006-06-18 06:48:37 +000082 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000083
84 // Two options, it can either be a pp-identifier or a (.
85 bool InParens = false;
86 if (PeekTok.getKind() == tok::l_paren) {
87 // Found a paren, remember we saw it and skip it.
88 InParens = true;
Chris Lattnercb283342006-06-18 06:48:37 +000089 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000090 }
91
92 // If we don't have a pp-identifier now, this is an error.
93 if ((II = PeekTok.getIdentifierInfo()) == 0) {
94 DisableMacroExpansion = false;
Chris Lattnercb283342006-06-18 06:48:37 +000095 Diag(PeekTok, diag::err_pp_defined_requires_identifier);
Chris Lattner22eb9722006-06-18 05:43:12 +000096 return true;
97 }
98
99 // Otherwise, we got an identifier, is it defined to something?
100 Result = II->getMacroInfo() != 0;
101
102 // Consume identifier.
Chris Lattnercb283342006-06-18 06:48:37 +0000103 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000104
105 // If we are in parens, ensure we have a trailing ).
106 if (InParens) {
107 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000108 Diag(PeekTok, diag::err_pp_missing_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000109 return true;
110 }
111 // Consume the ).
Chris Lattnercb283342006-06-18 06:48:37 +0000112 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000113 }
114
115 DisableMacroExpansion = false;
116 return false;
117 }
118
119 switch (PeekTok.getKind()) {
120 default: // Non-value token.
Chris Lattnercb283342006-06-18 06:48:37 +0000121 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000122 return true;
123 case tok::eom:
124 case tok::r_paren:
125 // If there is no expression, report and exit.
Chris Lattnercb283342006-06-18 06:48:37 +0000126 Diag(PeekTok, diag::err_pp_expected_value_in_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000127 return true;
128 case tok::numeric_constant: {
129 // FIXME: faster. FIXME: track signs.
130 std::string Spell = Lexer::getSpelling(PeekTok, getLangOptions());
131 // FIXME: COMPUTE integer constants CORRECTLY.
132 Result = atoi(Spell.c_str());
Chris Lattnercb283342006-06-18 06:48:37 +0000133 Lex(PeekTok);
134 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +0000135 }
136 case tok::l_paren:
Chris Lattnercb283342006-06-18 06:48:37 +0000137 Lex(PeekTok); // Eat the (.
138 // Parse the value and if there are any binary operators involved, parse
139 // them.
140 if (EvaluateValue(Result, PeekTok) ||
141 EvaluateDirectiveSubExpr(Result, 1, PeekTok))
142 return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000143
144 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000145 Diag(PeekTok, diag::err_pp_expected_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000146 return true;
147 }
Chris Lattnercb283342006-06-18 06:48:37 +0000148 Lex(PeekTok); // Eat the ).
Chris Lattner22eb9722006-06-18 05:43:12 +0000149 return false;
150
151 case tok::plus:
152 // Unary plus doesn't modify the value.
Chris Lattnercb283342006-06-18 06:48:37 +0000153 Lex(PeekTok);
154 return EvaluateValue(Result, PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000155 case tok::minus:
Chris Lattnercb283342006-06-18 06:48:37 +0000156 Lex(PeekTok);
157 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000158 Result = -Result;
159 return false;
160
161 case tok::tilde:
Chris Lattnercb283342006-06-18 06:48:37 +0000162 Lex(PeekTok);
163 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000164 Result = ~Result;
165 return false;
166
167 case tok::exclaim:
Chris Lattnercb283342006-06-18 06:48:37 +0000168 Lex(PeekTok);
169 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000170 Result = !Result;
171 return false;
172
173 // FIXME: Handle #assert
174 }
175}
176
177
178
179/// getPrecedence - Return the precedence of the specified binary operator
180/// token. This returns:
181/// ~0 - Invalid token.
182/// 15 - *,/,%
183/// 14 - -,+
184/// 13 - <<,>>
185/// 12 - >=, <=, >, <
186/// 11 - ==, !=
187/// 10 - <?, >? min, max (GCC extensions)
188/// 9 - &
189/// 8 - ^
190/// 7 - |
191/// 6 - &&
192/// 5 - ||
193/// 4 - ?
194/// 3 - :
195/// 0 - eom, )
196static unsigned getPrecedence(tok::TokenKind Kind) {
197 switch (Kind) {
198 default: return ~0U;
199 case tok::percent:
200 case tok::slash:
201 case tok::star: return 15;
202 case tok::plus:
203 case tok::minus: return 14;
204 case tok::lessless:
205 case tok::greatergreater: return 13;
206 case tok::lessequal:
207 case tok::less:
208 case tok::greaterequal:
209 case tok::greater: return 12;
210 case tok::exclaimequal:
211 case tok::equalequal: return 11;
212 case tok::lessquestion:
213 case tok::greaterquestion: return 10;
214 case tok::amp: return 9;
215 case tok::caret: return 8;
216 case tok::pipe: return 7;
217 case tok::ampamp: return 6;
218 case tok::pipepipe: return 5;
219 case tok::question: return 4;
220 case tok::colon: return 3;
221 case tok::comma: return 2;
222 case tok::r_paren: return 0; // Lowest priority, end of expr.
223 case tok::eom: return 0; // Lowest priority, end of macro.
224 }
225}
226
227
228/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
229/// PeekTok, and whose precedence is PeekPrec.
230bool Preprocessor::EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
Chris Lattnercb283342006-06-18 06:48:37 +0000231 LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000232 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
233 // If this token isn't valid, report the error.
234 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000235 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000236 return true;
237 }
238
239 while (1) {
240 // If this token has a lower precedence than we are allowed to parse, return
241 // it so that higher levels of the recursion can parse it.
242 if (PeekPrec < MinPrec)
243 return false;
244
245 tok::TokenKind Operator = PeekTok.getKind();
246
247 // Consume the operator, saving the operator token for error reporting.
248 LexerToken OpToken = PeekTok;
Chris Lattnercb283342006-06-18 06:48:37 +0000249 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000250
251 int RHS;
252 // Parse the RHS of the operator.
Chris Lattnercb283342006-06-18 06:48:37 +0000253 if (EvaluateValue(RHS, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000254
255 // Remember the precedence of this operator and get the precedence of the
256 // operator immediately to the right of the RHS.
257 unsigned ThisPrec = PeekPrec;
258 PeekPrec = getPrecedence(PeekTok.getKind());
259
260 // If this token isn't valid, report the error.
261 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000262 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000263 return true;
264 }
265
266 bool isRightAssoc = Operator == tok::question;
267
268 // Get the precedence of the operator to the right of the RHS. If it binds
269 // more tightly with RHS than we do, evaluate it completely first.
270 if (ThisPrec < PeekPrec ||
271 (ThisPrec == PeekPrec && isRightAssoc)) {
Chris Lattnercb283342006-06-18 06:48:37 +0000272 if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000273 return true;
274 PeekPrec = getPrecedence(PeekTok.getKind());
275 }
276 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
277
278 switch (Operator) {
279 default: assert(0 && "Unknown operator token!");
280 case tok::percent:
281 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000282 Diag(OpToken, diag::err_pp_remainder_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000283 return true;
284 }
285 LHS %= RHS;
286 break;
287 case tok::slash:
288 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000289 Diag(OpToken, diag::err_pp_division_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000290 return true;
291 }
292 LHS /= RHS;
293 break;
294 case tok::star : LHS *= RHS; break;
295 case tok::lessless: LHS << RHS; break; // FIXME: shift amt overflow?
296 case tok::greatergreater: LHS >> RHS; break; // FIXME: signed vs unsigned
297 case tok::plus : LHS += RHS; break;
298 case tok::minus: LHS -= RHS; break;
299 case tok::lessequal: LHS = LHS <= RHS; break;
300 case tok::less: LHS = LHS < RHS; break;
301 case tok::greaterequal: LHS = LHS >= RHS; break;
302 case tok::greater: LHS = LHS > RHS; break;
303 case tok::exclaimequal: LHS = LHS != RHS; break;
304 case tok::equalequal: LHS = LHS == RHS; break;
305 case tok::lessquestion: // Deprecation warning emitted by the lexer.
306 LHS = std::min(LHS, RHS);
307 break;
308 case tok::greaterquestion: // Deprecation warning emitted by the lexer.
309 LHS = std::max(LHS, RHS);
310 break;
311 case tok::amp: LHS &= RHS; break;
312 case tok::caret: LHS ^= RHS; break;
313 case tok::pipe: LHS |= RHS; break;
314 case tok::ampamp: LHS = LHS && RHS; break;
315 case tok::pipepipe: LHS = LHS || RHS; break;
316 case tok::comma:
Chris Lattnercb283342006-06-18 06:48:37 +0000317 Diag(OpToken, diag::ext_pp_comma_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000318 LHS = RHS; // LHS = LHS,RHS -> RHS.
319 break;
320 case tok::question: {
321 // Parse the : part of the expression.
322 if (PeekTok.getKind() != tok::colon) {
Chris Lattnercb283342006-06-18 06:48:37 +0000323 Diag(OpToken, diag::err_pp_question_without_colon);
Chris Lattner22eb9722006-06-18 05:43:12 +0000324 return true;
325 }
326 // Consume the :.
Chris Lattnercb283342006-06-18 06:48:37 +0000327 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000328
329 // Evaluate the value after the :.
330 int AfterColonVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +0000331 if (EvaluateValue(AfterColonVal, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000332
333 // Parse anything after the : RHS that has a higher precedence than ?.
334 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
Chris Lattnercb283342006-06-18 06:48:37 +0000335 PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000336 return true;
337
338 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
339 LHS = LHS ? RHS : AfterColonVal;
340
341 // Figure out the precedence of the token after the : part.
342 PeekPrec = getPrecedence(PeekTok.getKind());
343 break;
344 }
345 case tok::colon:
346 // Don't allow :'s to float around without being part of ?: exprs.
Chris Lattnercb283342006-06-18 06:48:37 +0000347 Diag(OpToken, diag::err_pp_colon_without_question);
Chris Lattner22eb9722006-06-18 05:43:12 +0000348 return true;
349 }
350 }
351
352 return false;
353}