blob: 3217df9fc9ec6d235b21315f55b37734154c2f44 [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//
Chris Lattner80965422006-07-04 18:03:19 +000010// This file implements the Preprocessor::EvaluateDirectiveExpression method,
11// which parses and evaluates integer constant expressions for #if directives.
Chris Lattner22eb9722006-06-18 05:43:12 +000012//
13//===----------------------------------------------------------------------===//
14//
15// FIXME: implement testing for asserts.
16// FIXME: Parse integer constants correctly. Reject 123.0, etc.
17// FIXME: Track signed/unsigned correctly.
18// FIXME: Track and report integer overflow correctly.
19//
20//===----------------------------------------------------------------------===//
21
22#include "clang/Lex/Preprocessor.h"
Chris Lattnera78a97e2006-07-03 05:42:18 +000023#include "clang/Lex/MacroInfo.h"
Chris Lattner81278c62006-10-14 19:03:49 +000024#include "clang/Basic/TargetInfo.h"
Chris Lattner22eb9722006-06-18 05:43:12 +000025#include "clang/Basic/TokenKinds.h"
26#include "clang/Basic/Diagnostic.h"
27using namespace llvm;
28using namespace clang;
29
Chris Lattnere3519cc2006-07-04 18:11:39 +000030static bool EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
31 LexerToken &PeekTok, Preprocessor &PP);
Chris Lattner22eb9722006-06-18 05:43:12 +000032
Chris Lattnerb9d90f72006-07-04 18:32:03 +000033/// DefinedTracker - This struct is used while parsing expressions to keep track
34/// of whether !defined(X) has been seen.
35///
36/// With this simple scheme, we handle the basic forms:
37/// !defined(X) and !defined X
38/// but we also trivially handle (silly) stuff like:
39/// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).
40struct DefinedTracker {
41 /// Each time a Value is evaluated, it returns information about whether the
42 /// parsed value is of the form defined(X), !defined(X) or is something else.
43 enum TrackerState {
44 DefinedMacro, // defined(X)
45 NotDefinedMacro, // !defined(X)
46 Unknown // Something else.
47 } State;
48 /// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
49 /// indicates the macro that was checked.
50 IdentifierInfo *TheMacro;
51};
52
53
Chris Lattner22eb9722006-06-18 05:43:12 +000054
55/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
56/// return the computed value in Result. Return true if there was an error
Chris Lattnerb9d90f72006-07-04 18:32:03 +000057/// parsing. This function also returns information about the form of the
58/// expression in DT. See above for information on what DT means.
59static bool EvaluateValue(int &Result, LexerToken &PeekTok, DefinedTracker &DT,
60 Preprocessor &PP) {
Chris Lattner22eb9722006-06-18 05:43:12 +000061 Result = 0;
Chris Lattnerb9d90f72006-07-04 18:32:03 +000062 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +000063
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.
Chris Lattnerb9d90f72006-07-04 18:32:03 +000067 if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
Chris Lattner22eb9722006-06-18 05:43:12 +000068 // 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 Lattnere3519cc2006-07-04 18:11:39 +000072 PP.Lex(PeekTok);
Chris Lattnercb283342006-06-18 06:48:37 +000073 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +000074 }
75
76 // Handle "defined X" and "defined(X)".
Chris Lattner22eb9722006-06-18 05:43:12 +000077
Chris Lattnere3519cc2006-07-04 18:11:39 +000078 // Get the next token, don't expand it.
79 PP.LexUnexpandedToken(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000080
81 // Two options, it can either be a pp-identifier or a (.
82 bool InParens = false;
83 if (PeekTok.getKind() == tok::l_paren) {
84 // Found a paren, remember we saw it and skip it.
85 InParens = true;
Chris Lattnere3519cc2006-07-04 18:11:39 +000086 PP.LexUnexpandedToken(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +000087 }
88
89 // If we don't have a pp-identifier now, this is an error.
90 if ((II = PeekTok.getIdentifierInfo()) == 0) {
Chris Lattnere3519cc2006-07-04 18:11:39 +000091 PP.Diag(PeekTok, diag::err_pp_defined_requires_identifier);
Chris Lattner22eb9722006-06-18 05:43:12 +000092 return true;
93 }
94
95 // Otherwise, we got an identifier, is it defined to something?
96 Result = II->getMacroInfo() != 0;
Chris Lattnera78a97e2006-07-03 05:42:18 +000097
98 // If there is a macro, mark it used.
Chris Lattner81278c62006-10-14 19:03:49 +000099 if (Result) {
100 II->getMacroInfo()->setIsUsed(true);
101
102 // If this is the first use of a target-specific macro, warn about it.
103 if (II->getMacroInfo()->isTargetSpecific()) {
104 // Don't warn on second use.
105 II->getMacroInfo()->setIsTargetSpecific(false);
106 PP.getTargetInfo().DiagnoseNonPortability(PeekTok.getLocation(),
107 diag::port_target_macro_use);
108 }
109 }
Chris Lattner22eb9722006-06-18 05:43:12 +0000110
111 // Consume identifier.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000112 PP.Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000113
114 // If we are in parens, ensure we have a trailing ).
115 if (InParens) {
116 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000117 PP.Diag(PeekTok, diag::err_pp_missing_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000118 return true;
119 }
120 // Consume the ).
Chris Lattnere3519cc2006-07-04 18:11:39 +0000121 PP.Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000122 }
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000123
124 // Success, remember that we saw defined(X).
125 DT.State = DefinedTracker::DefinedMacro;
126 DT.TheMacro = II;
Chris Lattner22eb9722006-06-18 05:43:12 +0000127 return false;
128 }
129
130 switch (PeekTok.getKind()) {
131 default: // Non-value token.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000132 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000133 return true;
134 case tok::eom:
135 case tok::r_paren:
136 // If there is no expression, report and exit.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000137 PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000138 return true;
139 case tok::numeric_constant: {
140 // FIXME: faster. FIXME: track signs.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000141 std::string Spell = PP.getSpelling(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000142 // FIXME: COMPUTE integer constants CORRECTLY.
143 Result = atoi(Spell.c_str());
Chris Lattnere3519cc2006-07-04 18:11:39 +0000144 PP.Lex(PeekTok);
Chris Lattnercb283342006-06-18 06:48:37 +0000145 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +0000146 }
147 case tok::l_paren:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000148 PP.Lex(PeekTok); // Eat the (.
Chris Lattnercb283342006-06-18 06:48:37 +0000149 // Parse the value and if there are any binary operators involved, parse
150 // them.
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000151 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000152
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000153 // If this is a silly value like (X), which doesn't need parens, check for
154 // !(defined X).
155 if (PeekTok.getKind() == tok::r_paren) {
156 // Just use DT unmodified as our result.
157 } else {
158 if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, PP)) return true;
159
160 if (PeekTok.getKind() != tok::r_paren) {
161 PP.Diag(PeekTok, diag::err_pp_expected_rparen);
162 return true;
163 }
164 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +0000165 }
Chris Lattnere3519cc2006-07-04 18:11:39 +0000166 PP.Lex(PeekTok); // Eat the ).
Chris Lattner22eb9722006-06-18 05:43:12 +0000167 return false;
168
169 case tok::plus:
170 // Unary plus doesn't modify the value.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000171 PP.Lex(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000172 return EvaluateValue(Result, PeekTok, DT, PP);
Chris Lattner22eb9722006-06-18 05:43:12 +0000173 case tok::minus:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000174 PP.Lex(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000175 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000176 Result = -Result;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000177 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +0000178 return false;
179
180 case tok::tilde:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000181 PP.Lex(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000182 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000183 Result = ~Result;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000184 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +0000185 return false;
186
187 case tok::exclaim:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000188 PP.Lex(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000189 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000190 Result = !Result;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000191
192 if (DT.State == DefinedTracker::DefinedMacro)
193 DT.State = DefinedTracker::NotDefinedMacro;
194 else if (DT.State == DefinedTracker::NotDefinedMacro)
195 DT.State = DefinedTracker::DefinedMacro;
Chris Lattner22eb9722006-06-18 05:43:12 +0000196 return false;
197
198 // FIXME: Handle #assert
199 }
200}
201
202
203
204/// getPrecedence - Return the precedence of the specified binary operator
205/// token. This returns:
206/// ~0 - Invalid token.
207/// 15 - *,/,%
208/// 14 - -,+
209/// 13 - <<,>>
210/// 12 - >=, <=, >, <
211/// 11 - ==, !=
212/// 10 - <?, >? min, max (GCC extensions)
213/// 9 - &
214/// 8 - ^
215/// 7 - |
216/// 6 - &&
217/// 5 - ||
218/// 4 - ?
219/// 3 - :
220/// 0 - eom, )
221static unsigned getPrecedence(tok::TokenKind Kind) {
222 switch (Kind) {
223 default: return ~0U;
224 case tok::percent:
225 case tok::slash:
226 case tok::star: return 15;
227 case tok::plus:
228 case tok::minus: return 14;
229 case tok::lessless:
230 case tok::greatergreater: return 13;
231 case tok::lessequal:
232 case tok::less:
233 case tok::greaterequal:
234 case tok::greater: return 12;
235 case tok::exclaimequal:
236 case tok::equalequal: return 11;
237 case tok::lessquestion:
238 case tok::greaterquestion: return 10;
239 case tok::amp: return 9;
240 case tok::caret: return 8;
241 case tok::pipe: return 7;
242 case tok::ampamp: return 6;
243 case tok::pipepipe: return 5;
244 case tok::question: return 4;
245 case tok::colon: return 3;
246 case tok::comma: return 2;
247 case tok::r_paren: return 0; // Lowest priority, end of expr.
248 case tok::eom: return 0; // Lowest priority, end of macro.
249 }
250}
251
252
253/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
254/// PeekTok, and whose precedence is PeekPrec.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000255static bool EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
256 LexerToken &PeekTok, Preprocessor &PP) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000257 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
258 // If this token isn't valid, report the error.
259 if (PeekPrec == ~0U) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000260 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000261 return true;
262 }
263
264 while (1) {
265 // If this token has a lower precedence than we are allowed to parse, return
266 // it so that higher levels of the recursion can parse it.
267 if (PeekPrec < MinPrec)
268 return false;
269
270 tok::TokenKind Operator = PeekTok.getKind();
271
272 // Consume the operator, saving the operator token for error reporting.
273 LexerToken OpToken = PeekTok;
Chris Lattnere3519cc2006-07-04 18:11:39 +0000274 PP.Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000275
276 int RHS;
277 // Parse the RHS of the operator.
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000278 DefinedTracker DT;
279 if (EvaluateValue(RHS, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000280
281 // Remember the precedence of this operator and get the precedence of the
282 // operator immediately to the right of the RHS.
283 unsigned ThisPrec = PeekPrec;
284 PeekPrec = getPrecedence(PeekTok.getKind());
285
286 // If this token isn't valid, report the error.
287 if (PeekPrec == ~0U) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000288 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000289 return true;
290 }
291
292 bool isRightAssoc = Operator == tok::question;
293
294 // Get the precedence of the operator to the right of the RHS. If it binds
295 // more tightly with RHS than we do, evaluate it completely first.
296 if (ThisPrec < PeekPrec ||
297 (ThisPrec == PeekPrec && isRightAssoc)) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000298 if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok, PP))
Chris Lattner22eb9722006-06-18 05:43:12 +0000299 return true;
300 PeekPrec = getPrecedence(PeekTok.getKind());
301 }
302 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
303
304 switch (Operator) {
305 default: assert(0 && "Unknown operator token!");
306 case tok::percent:
307 if (RHS == 0) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000308 PP.Diag(OpToken, diag::err_pp_remainder_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000309 return true;
310 }
311 LHS %= RHS;
312 break;
313 case tok::slash:
314 if (RHS == 0) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000315 PP.Diag(OpToken, diag::err_pp_division_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000316 return true;
317 }
318 LHS /= RHS;
319 break;
320 case tok::star : LHS *= RHS; break;
321 case tok::lessless: LHS << RHS; break; // FIXME: shift amt overflow?
322 case tok::greatergreater: LHS >> RHS; break; // FIXME: signed vs unsigned
323 case tok::plus : LHS += RHS; break;
324 case tok::minus: LHS -= RHS; break;
325 case tok::lessequal: LHS = LHS <= RHS; break;
326 case tok::less: LHS = LHS < RHS; break;
327 case tok::greaterequal: LHS = LHS >= RHS; break;
328 case tok::greater: LHS = LHS > RHS; break;
329 case tok::exclaimequal: LHS = LHS != RHS; break;
330 case tok::equalequal: LHS = LHS == RHS; break;
331 case tok::lessquestion: // Deprecation warning emitted by the lexer.
332 LHS = std::min(LHS, RHS);
333 break;
334 case tok::greaterquestion: // Deprecation warning emitted by the lexer.
335 LHS = std::max(LHS, RHS);
336 break;
337 case tok::amp: LHS &= RHS; break;
338 case tok::caret: LHS ^= RHS; break;
339 case tok::pipe: LHS |= RHS; break;
340 case tok::ampamp: LHS = LHS && RHS; break;
341 case tok::pipepipe: LHS = LHS || RHS; break;
342 case tok::comma:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000343 PP.Diag(OpToken, diag::ext_pp_comma_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000344 LHS = RHS; // LHS = LHS,RHS -> RHS.
345 break;
346 case tok::question: {
347 // Parse the : part of the expression.
348 if (PeekTok.getKind() != tok::colon) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000349 PP.Diag(OpToken, diag::err_pp_question_without_colon);
Chris Lattner22eb9722006-06-18 05:43:12 +0000350 return true;
351 }
352 // Consume the :.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000353 PP.Lex(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000354
355 // Evaluate the value after the :.
356 int AfterColonVal = 0;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000357 DefinedTracker DT;
358 if (EvaluateValue(AfterColonVal, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000359
360 // Parse anything after the : RHS that has a higher precedence than ?.
361 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
Chris Lattnere3519cc2006-07-04 18:11:39 +0000362 PeekTok, PP))
Chris Lattner22eb9722006-06-18 05:43:12 +0000363 return true;
364
365 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
366 LHS = LHS ? RHS : AfterColonVal;
367
368 // Figure out the precedence of the token after the : part.
369 PeekPrec = getPrecedence(PeekTok.getKind());
370 break;
371 }
372 case tok::colon:
373 // Don't allow :'s to float around without being part of ?: exprs.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000374 PP.Diag(OpToken, diag::err_pp_colon_without_question);
Chris Lattner22eb9722006-06-18 05:43:12 +0000375 return true;
376 }
377 }
378
379 return false;
380}
Chris Lattnere3519cc2006-07-04 18:11:39 +0000381
382/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
383/// may occur after a #if or #elif directive. If the expression is equivalent
384/// to "!defined(X)" return X in IfNDefMacro.
385bool Preprocessor::
386EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
387 // Peek ahead one token.
388 LexerToken Tok;
389 Lex(Tok);
390
391 int ResVal = 0;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000392 DefinedTracker DT;
393 if (EvaluateValue(ResVal, Tok, DT, *this)) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000394 // Parse error, skip the rest of the macro line.
395 if (Tok.getKind() != tok::eom)
396 DiscardUntilEndOfDirective();
397 return false;
398 }
399
400 // If we are at the end of the expression after just parsing a value, there
401 // must be no (unparenthesized) binary operators involved, so we can exit
402 // directly.
403 if (Tok.getKind() == tok::eom) {
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000404 // If the expression we parsed was of the form !defined(macro), return the
405 // macro in IfNDefMacro.
406 if (DT.State == DefinedTracker::NotDefinedMacro)
407 IfNDefMacro = DT.TheMacro;
408
Chris Lattnere3519cc2006-07-04 18:11:39 +0000409 return ResVal != 0;
410 }
411
412 // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
413 // operator and the stuff after it.
414 if (EvaluateDirectiveSubExpr(ResVal, 1, Tok, *this)) {
415 // Parse error, skip the rest of the macro line.
416 if (Tok.getKind() != tok::eom)
417 DiscardUntilEndOfDirective();
418 return false;
419 }
420
421 // If we aren't at the tok::eom token, something bad happened, like an extra
422 // ')' token.
423 if (Tok.getKind() != tok::eom) {
424 Diag(Tok, diag::err_pp_expected_eol);
425 DiscardUntilEndOfDirective();
426 }
427
428 return ResVal != 0;
429}
430