blob: 34cd73fb8b9a8aa21c93deb9688d47aaf38c5382 [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.
Chris Lattner2bb8a952006-11-21 22:24:17 +000070 if (II->getPPKeywordID() != tok::pp_defined) {
Chris Lattner22eb9722006-06-18 05:43:12 +000071 Result = 0;
Chris Lattnerbcb416b2006-10-27 05:43:50 +000072 PP.LexNonComment(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 }
Chris Lattner063400e2006-10-14 19:54:15 +0000109 } else {
110 // Use of a target-specific macro for some other target? If so, warn.
111 if (II->isOtherTargetMacro()) {
112 II->setIsOtherTargetMacro(false); // Don't warn on second use.
113 PP.getTargetInfo().DiagnoseNonPortability(PeekTok.getLocation(),
114 diag::port_target_macro_use);
115 }
Chris Lattner81278c62006-10-14 19:03:49 +0000116 }
Chris Lattner22eb9722006-06-18 05:43:12 +0000117
118 // Consume identifier.
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000119 PP.LexNonComment(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000120
121 // If we are in parens, ensure we have a trailing ).
122 if (InParens) {
123 if (PeekTok.getKind() != tok::r_paren) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000124 PP.Diag(PeekTok, diag::err_pp_missing_rparen);
Chris Lattner22eb9722006-06-18 05:43:12 +0000125 return true;
126 }
127 // Consume the ).
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000128 PP.LexNonComment(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000129 }
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000130
131 // Success, remember that we saw defined(X).
132 DT.State = DefinedTracker::DefinedMacro;
133 DT.TheMacro = II;
Chris Lattner22eb9722006-06-18 05:43:12 +0000134 return false;
135 }
136
137 switch (PeekTok.getKind()) {
138 default: // Non-value token.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000139 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000140 return true;
141 case tok::eom:
142 case tok::r_paren:
143 // If there is no expression, report and exit.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000144 PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000145 return true;
146 case tok::numeric_constant: {
147 // FIXME: faster. FIXME: track signs.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000148 std::string Spell = PP.getSpelling(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000149 // FIXME: COMPUTE integer constants CORRECTLY.
150 Result = atoi(Spell.c_str());
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000151 PP.LexNonComment(PeekTok);
Chris Lattnercb283342006-06-18 06:48:37 +0000152 return false;
Chris Lattner22eb9722006-06-18 05:43:12 +0000153 }
154 case tok::l_paren:
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000155 PP.LexNonComment(PeekTok); // Eat the (.
Chris Lattnercb283342006-06-18 06:48:37 +0000156 // Parse the value and if there are any binary operators involved, parse
157 // them.
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000158 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000159
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000160 // If this is a silly value like (X), which doesn't need parens, check for
161 // !(defined X).
162 if (PeekTok.getKind() == tok::r_paren) {
163 // Just use DT unmodified as our result.
164 } else {
165 if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, PP)) return true;
166
167 if (PeekTok.getKind() != tok::r_paren) {
168 PP.Diag(PeekTok, diag::err_pp_expected_rparen);
169 return true;
170 }
171 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +0000172 }
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000173 PP.LexNonComment(PeekTok); // Eat the ).
Chris Lattner22eb9722006-06-18 05:43:12 +0000174 return false;
175
176 case tok::plus:
177 // Unary plus doesn't modify the value.
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000178 PP.LexNonComment(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000179 return EvaluateValue(Result, PeekTok, DT, PP);
Chris Lattner22eb9722006-06-18 05:43:12 +0000180 case tok::minus:
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000181 PP.LexNonComment(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::tilde:
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000188 PP.LexNonComment(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 DT.State = DefinedTracker::Unknown;
Chris Lattner22eb9722006-06-18 05:43:12 +0000192 return false;
193
194 case tok::exclaim:
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000195 PP.LexNonComment(PeekTok);
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000196 if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000197 Result = !Result;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000198
199 if (DT.State == DefinedTracker::DefinedMacro)
200 DT.State = DefinedTracker::NotDefinedMacro;
201 else if (DT.State == DefinedTracker::NotDefinedMacro)
202 DT.State = DefinedTracker::DefinedMacro;
Chris Lattner22eb9722006-06-18 05:43:12 +0000203 return false;
204
205 // FIXME: Handle #assert
206 }
207}
208
209
210
211/// getPrecedence - Return the precedence of the specified binary operator
212/// token. This returns:
213/// ~0 - Invalid token.
Chris Lattner9916c5c2006-10-27 05:24:37 +0000214/// 14 - *,/,%
215/// 13 - -,+
216/// 12 - <<,>>
217/// 11 - >=, <=, >, <
218/// 10 - ==, !=
Chris Lattner22eb9722006-06-18 05:43:12 +0000219/// 9 - &
220/// 8 - ^
221/// 7 - |
222/// 6 - &&
223/// 5 - ||
224/// 4 - ?
225/// 3 - :
226/// 0 - eom, )
227static unsigned getPrecedence(tok::TokenKind Kind) {
228 switch (Kind) {
229 default: return ~0U;
230 case tok::percent:
231 case tok::slash:
Chris Lattner9916c5c2006-10-27 05:24:37 +0000232 case tok::star: return 14;
Chris Lattner22eb9722006-06-18 05:43:12 +0000233 case tok::plus:
Chris Lattner9916c5c2006-10-27 05:24:37 +0000234 case tok::minus: return 13;
Chris Lattner22eb9722006-06-18 05:43:12 +0000235 case tok::lessless:
Chris Lattner9916c5c2006-10-27 05:24:37 +0000236 case tok::greatergreater: return 12;
Chris Lattner22eb9722006-06-18 05:43:12 +0000237 case tok::lessequal:
238 case tok::less:
239 case tok::greaterequal:
Chris Lattner9916c5c2006-10-27 05:24:37 +0000240 case tok::greater: return 11;
Chris Lattner22eb9722006-06-18 05:43:12 +0000241 case tok::exclaimequal:
Chris Lattner9916c5c2006-10-27 05:24:37 +0000242 case tok::equalequal: return 10;
Chris Lattner22eb9722006-06-18 05:43:12 +0000243 case tok::amp: return 9;
244 case tok::caret: return 8;
245 case tok::pipe: return 7;
246 case tok::ampamp: return 6;
247 case tok::pipepipe: return 5;
248 case tok::question: return 4;
249 case tok::colon: return 3;
250 case tok::comma: return 2;
251 case tok::r_paren: return 0; // Lowest priority, end of expr.
252 case tok::eom: return 0; // Lowest priority, end of macro.
253 }
254}
255
256
257/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
258/// PeekTok, and whose precedence is PeekPrec.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000259static bool EvaluateDirectiveSubExpr(int &LHS, unsigned MinPrec,
260 LexerToken &PeekTok, Preprocessor &PP) {
Chris Lattner22eb9722006-06-18 05:43:12 +0000261 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
262 // If this token isn't valid, report the error.
263 if (PeekPrec == ~0U) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000264 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000265 return true;
266 }
267
268 while (1) {
269 // If this token has a lower precedence than we are allowed to parse, return
270 // it so that higher levels of the recursion can parse it.
271 if (PeekPrec < MinPrec)
272 return false;
273
274 tok::TokenKind Operator = PeekTok.getKind();
275
276 // Consume the operator, saving the operator token for error reporting.
277 LexerToken OpToken = PeekTok;
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000278 PP.LexNonComment(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000279
280 int RHS;
281 // Parse the RHS of the operator.
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000282 DefinedTracker DT;
283 if (EvaluateValue(RHS, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000284
285 // Remember the precedence of this operator and get the precedence of the
286 // operator immediately to the right of the RHS.
287 unsigned ThisPrec = PeekPrec;
288 PeekPrec = getPrecedence(PeekTok.getKind());
289
290 // If this token isn't valid, report the error.
291 if (PeekPrec == ~0U) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000292 PP.Diag(PeekTok, diag::err_pp_expr_bad_token);
Chris Lattner22eb9722006-06-18 05:43:12 +0000293 return true;
294 }
295
296 bool isRightAssoc = Operator == tok::question;
297
298 // Get the precedence of the operator to the right of the RHS. If it binds
299 // more tightly with RHS than we do, evaluate it completely first.
300 if (ThisPrec < PeekPrec ||
301 (ThisPrec == PeekPrec && isRightAssoc)) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000302 if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok, PP))
Chris Lattner22eb9722006-06-18 05:43:12 +0000303 return true;
304 PeekPrec = getPrecedence(PeekTok.getKind());
305 }
306 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
307
308 switch (Operator) {
309 default: assert(0 && "Unknown operator token!");
310 case tok::percent:
311 if (RHS == 0) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000312 PP.Diag(OpToken, diag::err_pp_remainder_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000313 return true;
314 }
315 LHS %= RHS;
316 break;
317 case tok::slash:
318 if (RHS == 0) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000319 PP.Diag(OpToken, diag::err_pp_division_by_zero);
Chris Lattner22eb9722006-06-18 05:43:12 +0000320 return true;
321 }
322 LHS /= RHS;
323 break;
324 case tok::star : LHS *= RHS; break;
Chris Lattnerc95c8f22006-11-05 07:59:22 +0000325 case tok::lessless: LHS <<= RHS; break; // FIXME: shift amt overflow?
326 case tok::greatergreater: LHS >>= RHS; break; // FIXME: signed vs unsigned
Chris Lattner22eb9722006-06-18 05:43:12 +0000327 case tok::plus : LHS += RHS; break;
328 case tok::minus: LHS -= RHS; break;
329 case tok::lessequal: LHS = LHS <= RHS; break;
330 case tok::less: LHS = LHS < RHS; break;
331 case tok::greaterequal: LHS = LHS >= RHS; break;
332 case tok::greater: LHS = LHS > RHS; break;
333 case tok::exclaimequal: LHS = LHS != RHS; break;
334 case tok::equalequal: LHS = LHS == RHS; break;
Chris Lattner22eb9722006-06-18 05:43:12 +0000335 case tok::amp: LHS &= RHS; break;
336 case tok::caret: LHS ^= RHS; break;
337 case tok::pipe: LHS |= RHS; break;
338 case tok::ampamp: LHS = LHS && RHS; break;
339 case tok::pipepipe: LHS = LHS || RHS; break;
340 case tok::comma:
Chris Lattnere3519cc2006-07-04 18:11:39 +0000341 PP.Diag(OpToken, diag::ext_pp_comma_expr);
Chris Lattner22eb9722006-06-18 05:43:12 +0000342 LHS = RHS; // LHS = LHS,RHS -> RHS.
343 break;
344 case tok::question: {
345 // Parse the : part of the expression.
346 if (PeekTok.getKind() != tok::colon) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000347 PP.Diag(OpToken, diag::err_pp_question_without_colon);
Chris Lattner22eb9722006-06-18 05:43:12 +0000348 return true;
349 }
350 // Consume the :.
Chris Lattnerbcb416b2006-10-27 05:43:50 +0000351 PP.LexNonComment(PeekTok);
Chris Lattner22eb9722006-06-18 05:43:12 +0000352
353 // Evaluate the value after the :.
354 int AfterColonVal = 0;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000355 DefinedTracker DT;
356 if (EvaluateValue(AfterColonVal, PeekTok, DT, PP)) return true;
Chris Lattner22eb9722006-06-18 05:43:12 +0000357
358 // Parse anything after the : RHS that has a higher precedence than ?.
359 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
Chris Lattnere3519cc2006-07-04 18:11:39 +0000360 PeekTok, PP))
Chris Lattner22eb9722006-06-18 05:43:12 +0000361 return true;
362
363 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
364 LHS = LHS ? RHS : AfterColonVal;
365
366 // Figure out the precedence of the token after the : part.
367 PeekPrec = getPrecedence(PeekTok.getKind());
368 break;
369 }
370 case tok::colon:
371 // Don't allow :'s to float around without being part of ?: exprs.
Chris Lattnere3519cc2006-07-04 18:11:39 +0000372 PP.Diag(OpToken, diag::err_pp_colon_without_question);
Chris Lattner22eb9722006-06-18 05:43:12 +0000373 return true;
374 }
375 }
376
377 return false;
378}
Chris Lattnere3519cc2006-07-04 18:11:39 +0000379
380/// EvaluateDirectiveExpression - Evaluate an integer constant expression that
381/// may occur after a #if or #elif directive. If the expression is equivalent
382/// to "!defined(X)" return X in IfNDefMacro.
383bool Preprocessor::
384EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
385 // Peek ahead one token.
386 LexerToken Tok;
387 Lex(Tok);
388
389 int ResVal = 0;
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000390 DefinedTracker DT;
391 if (EvaluateValue(ResVal, Tok, DT, *this)) {
Chris Lattnere3519cc2006-07-04 18:11:39 +0000392 // Parse error, skip the rest of the macro line.
393 if (Tok.getKind() != tok::eom)
394 DiscardUntilEndOfDirective();
395 return false;
396 }
397
398 // If we are at the end of the expression after just parsing a value, there
399 // must be no (unparenthesized) binary operators involved, so we can exit
400 // directly.
401 if (Tok.getKind() == tok::eom) {
Chris Lattnerb9d90f72006-07-04 18:32:03 +0000402 // If the expression we parsed was of the form !defined(macro), return the
403 // macro in IfNDefMacro.
404 if (DT.State == DefinedTracker::NotDefinedMacro)
405 IfNDefMacro = DT.TheMacro;
406
Chris Lattnere3519cc2006-07-04 18:11:39 +0000407 return ResVal != 0;
408 }
409
410 // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
411 // operator and the stuff after it.
412 if (EvaluateDirectiveSubExpr(ResVal, 1, Tok, *this)) {
413 // Parse error, skip the rest of the macro line.
414 if (Tok.getKind() != tok::eom)
415 DiscardUntilEndOfDirective();
416 return false;
417 }
418
419 // If we aren't at the tok::eom token, something bad happened, like an extra
420 // ')' token.
421 if (Tok.getKind() != tok::eom) {
422 Diag(Tok, diag::err_pp_expected_eol);
423 DiscardUntilEndOfDirective();
424 }
425
426 return ResVal != 0;
427}
428