blob: 2b4afa900e5dd3b4f3a3d6b5e7047864d5bdc3d4 [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"
Chris Lattnera78a97e2006-07-03 05:42:18 +000022#include "clang/Lex/MacroInfo.h"
Chris Lattner22eb9722006-06-18 05:43:12 +000023#include "clang/Basic/TokenKinds.h"
24#include "clang/Basic/Diagnostic.h"
25using namespace llvm;
26using namespace clang;
27
28/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
29/// may occur after a #if or #elif directive. Sets Result to the result of
30/// the expression. Returns false normally, true if lexing must be aborted.
31///
32/// MinPrec is the minimum precedence that this range of the expression is
33/// allowed to include.
Chris Lattner7966aaf2006-06-18 06:50:36 +000034bool Preprocessor::EvaluateDirectiveExpression() {
Chris Lattner22eb9722006-06-18 05:43:12 +000035 // Peek ahead one token.
36 LexerToken Tok;
Chris Lattnercb283342006-06-18 06:48:37 +000037 Lex(Tok);
Chris Lattner22eb9722006-06-18 05:43:12 +000038
Chris Lattner22eb9722006-06-18 05:43:12 +000039 int ResVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000040 if (EvaluateValue(ResVal, Tok) ||
41 EvaluateDirectiveSubExpr(ResVal, 1, Tok)) {
Chris Lattner22eb9722006-06-18 05:43:12 +000042 // Skip the rest of the macro line.
Chris Lattnercb283342006-06-18 06:48:37 +000043 if (Tok.getKind() != tok::eom)
44 DiscardUntilEndOfDirective();
Chris Lattner7966aaf2006-06-18 06:50:36 +000045 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000046 }
47
48 // If we aren't at the tok::eom token, something bad happened, like an extra
49 // ')' token.
50 if (Tok.getKind() != tok::eom) {
Chris Lattnercb283342006-06-18 06:48:37 +000051 Diag(Tok, diag::err_pp_expected_eol);
52 DiscardUntilEndOfDirective();
Chris Lattner22eb9722006-06-18 05:43:12 +000053 }
54
Chris Lattner7966aaf2006-06-18 06:50:36 +000055 return ResVal != 0;
Chris Lattner22eb9722006-06-18 05:43:12 +000056}
57
58/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
59/// return the computed value in Result. Return true if there was an error
Chris Lattnercb283342006-06-18 06:48:37 +000060/// parsing.
61bool Preprocessor::EvaluateValue(int &Result, LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +000062 Result = 0;
63
64 // If this token's spelling is a pp-identifier, check to see if it is
65 // 'defined' or if it is a macro. Note that we check here because many
66 // keywords are pp-identifiers, so we can't check the kind.
67 if (const IdentifierTokenInfo *II = PeekTok.getIdentifierInfo()) {
68 // If this identifier isn't 'defined' and it wasn't macro expanded, it turns
69 // into a simple 0.
70 if (strcmp(II->getName(), "defined")) {
71 Result = 0;
Chris Lattnercb283342006-06-18 06:48:37 +000072 Lex(PeekTok);
73 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000074 }
75
76 // Handle "defined X" and "defined(X)".
77 assert(!DisableMacroExpansion &&
78 "How could macro exp already be disabled?");
79 // Turn off macro expansion.
80 DisableMacroExpansion = true;
81
82 // Get the next token.
Chris Lattnercb283342006-06-18 06:48:37 +000083 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000084
85 // Two options, it can either be a pp-identifier or a (.
86 bool InParens = false;
87 if (PeekTok.getKind() == tok::l_paren) {
88 // Found a paren, remember we saw it and skip it.
89 InParens = true;
Chris Lattnercb283342006-06-18 06:48:37 +000090 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000091 }
92
93 // If we don't have a pp-identifier now, this is an error.
94 if ((II = PeekTok.getIdentifierInfo()) == 0) {
95 DisableMacroExpansion = false;
Chris Lattnercb283342006-06-18 06:48:37 +000096 Diag(PeekTok, diag::err_pp_defined_requires_identifier);
Chris Lattner22eb9722006-06-18 05:43:12 +000097 return true;
98 }
99
100 // Otherwise, we got an identifier, is it defined to something?
101 Result = II->getMacroInfo() != 0;
Chris Lattnera78a97e2006-07-03 05:42:18 +0000102
103 // If there is a macro, mark it used.
104 if (Result) II->getMacroInfo()->setIsUsed(true);
Chris Lattner22eb9722006-06-18 05:43:12 +0000105
106 // Consume identifier.
Chris Lattnercb283342006-06-18 06:48:37 +0000107 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000108
109 // If we are in parens, ensure we have a trailing ).
110 if (InParens) {
111 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000112 Diag(PeekTok, diag::err_pp_missing_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000113 return true;
114 }
115 // Consume the ).
Chris Lattnercb283342006-06-18 06:48:37 +0000116 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000117 }
118
119 DisableMacroExpansion = false;
120 return false;
121 }
122
123 switch (PeekTok.getKind()) {
124 default: // Non-value token.
Chris Lattnercb283342006-06-18 06:48:37 +0000125 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000126 return true;
127 case tok::eom:
128 case tok::r_paren:
129 // If there is no expression, report and exit.
Chris Lattnercb283342006-06-18 06:48:37 +0000130 Diag(PeekTok, diag::err_pp_expected_value_in_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000131 return true;
132 case tok::numeric_constant: {
133 // FIXME: faster. FIXME: track signs.
Chris Lattnerd01e2912006-06-18 16:22:51 +0000134 std::string Spell = getSpelling(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000135 // FIXME: COMPUTE integer constants CORRECTLY.
136 Result = atoi(Spell.c_str());
Chris Lattnercb283342006-06-18 06:48:37 +0000137 Lex(PeekTok);
138 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +0000139 }
140 case tok::l_paren:
Chris Lattnercb283342006-06-18 06:48:37 +0000141 Lex(PeekTok); // Eat the (.
142 // Parse the value and if there are any binary operators involved, parse
143 // them.
144 if (EvaluateValue(Result, PeekTok) ||
145 EvaluateDirectiveSubExpr(Result, 1, PeekTok))
146 return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000147
148 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnercb283342006-06-18 06:48:37 +0000149 Diag(PeekTok, diag::err_pp_expected_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000150 return true;
151 }
Chris Lattnercb283342006-06-18 06:48:37 +0000152 Lex(PeekTok); // Eat the ).
Chris Lattner22eb9722006-06-18 05:43:12 +0000153 return false;
154
155 case tok::plus:
156 // Unary plus doesn't modify the value.
Chris Lattnercb283342006-06-18 06:48:37 +0000157 Lex(PeekTok);
158 return EvaluateValue(Result, PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000159 case tok::minus:
Chris Lattnercb283342006-06-18 06:48:37 +0000160 Lex(PeekTok);
161 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000162 Result = -Result;
163 return false;
164
165 case tok::tilde:
Chris Lattnercb283342006-06-18 06:48:37 +0000166 Lex(PeekTok);
167 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000168 Result = ~Result;
169 return false;
170
171 case tok::exclaim:
Chris Lattnercb283342006-06-18 06:48:37 +0000172 Lex(PeekTok);
173 if (EvaluateValue(Result, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000174 Result = !Result;
175 return false;
176
177 // FIXME: Handle #assert
178 }
179}
180
181
182
183/// getPrecedence - Return the precedence of the specified binary operator
184/// token. This returns:
185/// ~0 - Invalid token.
186/// 15 - *,/,%
187/// 14 - -,+
188/// 13 - <<,>>
189/// 12 - >=, <=, >, <
190/// 11 - ==, !=
191/// 10 - <?, >? min, max (GCC extensions)
192/// 9 - &
193/// 8 - ^
194/// 7 - |
195/// 6 - &&
196/// 5 - ||
197/// 4 - ?
198/// 3 - :
199/// 0 - eom, )
200static unsigned getPrecedence(tok::TokenKind Kind) {
201 switch (Kind) {
202 default: return ~0U;
203 case tok::percent:
204 case tok::slash:
205 case tok::star: return 15;
206 case tok::plus:
207 case tok::minus: return 14;
208 case tok::lessless:
209 case tok::greatergreater: return 13;
210 case tok::lessequal:
211 case tok::less:
212 case tok::greaterequal:
213 case tok::greater: return 12;
214 case tok::exclaimequal:
215 case tok::equalequal: return 11;
216 case tok::lessquestion:
217 case tok::greaterquestion: return 10;
218 case tok::amp: return 9;
219 case tok::caret: return 8;
220 case tok::pipe: return 7;
221 case tok::ampamp: return 6;
222 case tok::pipepipe: return 5;
223 case tok::question: return 4;
224 case tok::colon: return 3;
225 case tok::comma: return 2;
226 case tok::r_paren: return 0; // Lowest priority, end of expr.
227 case tok::eom: return 0; // Lowest priority, end of macro.
228 }
229}
230
231
232/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
233/// PeekTok, and whose precedence is PeekPrec.
234bool Preprocessor::EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
Chris Lattnercb283342006-06-18 06:48:37 +0000235 LexerToken &PeekTok) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000236 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
237 // If this token isn't valid, report the error.
238 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000239 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000240 return true;
241 }
242
243 while (1) {
244 // If this token has a lower precedence than we are allowed to parse, return
245 // it so that higher levels of the recursion can parse it.
246 if (PeekPrec < MinPrec)
247 return false;
248
249 tok::TokenKind Operator = PeekTok.getKind();
250
251 // Consume the operator, saving the operator token for error reporting.
252 LexerToken OpToken = PeekTok;
Chris Lattnercb283342006-06-18 06:48:37 +0000253 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000254
255 int RHS;
256 // Parse the RHS of the operator.
Chris Lattnercb283342006-06-18 06:48:37 +0000257 if (EvaluateValue(RHS, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000258
259 // Remember the precedence of this operator and get the precedence of the
260 // operator immediately to the right of the RHS.
261 unsigned ThisPrec = PeekPrec;
262 PeekPrec = getPrecedence(PeekTok.getKind());
263
264 // If this token isn't valid, report the error.
265 if (PeekPrec == ~0U) {
Chris Lattnercb283342006-06-18 06:48:37 +0000266 Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000267 return true;
268 }
269
270 bool isRightAssoc = Operator == tok::question;
271
272 // Get the precedence of the operator to the right of the RHS. If it binds
273 // more tightly with RHS than we do, evaluate it completely first.
274 if (ThisPrec < PeekPrec ||
275 (ThisPrec == PeekPrec && isRightAssoc)) {
Chris Lattnercb283342006-06-18 06:48:37 +0000276 if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000277 return true;
278 PeekPrec = getPrecedence(PeekTok.getKind());
279 }
280 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
281
282 switch (Operator) {
283 default: assert(0 && "Unknown operator token!");
284 case tok::percent:
285 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000286 Diag(OpToken, diag::err_pp_remainder_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000287 return true;
288 }
289 LHS %= RHS;
290 break;
291 case tok::slash:
292 if (RHS == 0) {
Chris Lattnercb283342006-06-18 06:48:37 +0000293 Diag(OpToken, diag::err_pp_division_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000294 return true;
295 }
296 LHS /= RHS;
297 break;
298 case tok::star : LHS *= RHS; break;
299 case tok::lessless: LHS << RHS; break; // FIXME: shift amt overflow?
300 case tok::greatergreater: LHS >> RHS; break; // FIXME: signed vs unsigned
301 case tok::plus : LHS += RHS; break;
302 case tok::minus: LHS -= RHS; break;
303 case tok::lessequal: LHS = LHS <= RHS; break;
304 case tok::less: LHS = LHS < RHS; break;
305 case tok::greaterequal: LHS = LHS >= RHS; break;
306 case tok::greater: LHS = LHS > RHS; break;
307 case tok::exclaimequal: LHS = LHS != RHS; break;
308 case tok::equalequal: LHS = LHS == RHS; break;
309 case tok::lessquestion: // Deprecation warning emitted by the lexer.
310 LHS = std::min(LHS, RHS);
311 break;
312 case tok::greaterquestion: // Deprecation warning emitted by the lexer.
313 LHS = std::max(LHS, RHS);
314 break;
315 case tok::amp: LHS &= RHS; break;
316 case tok::caret: LHS ^= RHS; break;
317 case tok::pipe: LHS |= RHS; break;
318 case tok::ampamp: LHS = LHS && RHS; break;
319 case tok::pipepipe: LHS = LHS || RHS; break;
320 case tok::comma:
Chris Lattnercb283342006-06-18 06:48:37 +0000321 Diag(OpToken, diag::ext_pp_comma_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000322 LHS = RHS; // LHS = LHS,RHS -> RHS.
323 break;
324 case tok::question: {
325 // Parse the : part of the expression.
326 if (PeekTok.getKind() != tok::colon) {
Chris Lattnercb283342006-06-18 06:48:37 +0000327 Diag(OpToken, diag::err_pp_question_without_colon);
Chris Lattner22eb9722006-06-18 05:43:12 +0000328 return true;
329 }
330 // Consume the :.
Chris Lattnercb283342006-06-18 06:48:37 +0000331 Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000332
333 // Evaluate the value after the :.
334 int AfterColonVal = 0;
Chris Lattnercb283342006-06-18 06:48:37 +0000335 if (EvaluateValue(AfterColonVal, PeekTok)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000336
337 // Parse anything after the : RHS that has a higher precedence than ?.
338 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
Chris Lattnercb283342006-06-18 06:48:37 +0000339 PeekTok))
Chris Lattner22eb9722006-06-18 05:43:12 +0000340 return true;
341
342 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
343 LHS = LHS ? RHS : AfterColonVal;
344
345 // Figure out the precedence of the token after the : part.
346 PeekPrec = getPrecedence(PeekTok.getKind());
347 break;
348 }
349 case tok::colon:
350 // Don't allow :'s to float around without being part of ?: exprs.
Chris Lattnercb283342006-06-18 06:48:37 +0000351 Diag(OpToken, diag::err_pp_colon_without_question);
Chris Lattner22eb9722006-06-18 05:43:12 +0000352 return true;
353 }
354 }
355
356 return false;
357}