annotate clang/lib/Lex/PPExpressions.cpp @ 176:de4ac79aef9d

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 17:13:11 +0900
parents 1d019706d866
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // This file implements the Preprocessor::EvaluateDirectiveExpression method,
anatofuz
parents:
diff changeset
10 // which parses and evaluates integer constant expressions for #if directives.
anatofuz
parents:
diff changeset
11 //
anatofuz
parents:
diff changeset
12 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
13 //
anatofuz
parents:
diff changeset
14 // FIXME: implement testing for #assert's.
anatofuz
parents:
diff changeset
15 //
anatofuz
parents:
diff changeset
16 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
17
anatofuz
parents:
diff changeset
18 #include "clang/Lex/Preprocessor.h"
anatofuz
parents:
diff changeset
19 #include "clang/Basic/IdentifierTable.h"
anatofuz
parents:
diff changeset
20 #include "clang/Basic/SourceLocation.h"
anatofuz
parents:
diff changeset
21 #include "clang/Basic/SourceManager.h"
anatofuz
parents:
diff changeset
22 #include "clang/Basic/TargetInfo.h"
anatofuz
parents:
diff changeset
23 #include "clang/Basic/TokenKinds.h"
anatofuz
parents:
diff changeset
24 #include "clang/Lex/CodeCompletionHandler.h"
anatofuz
parents:
diff changeset
25 #include "clang/Lex/LexDiagnostic.h"
anatofuz
parents:
diff changeset
26 #include "clang/Lex/LiteralSupport.h"
anatofuz
parents:
diff changeset
27 #include "clang/Lex/MacroInfo.h"
anatofuz
parents:
diff changeset
28 #include "clang/Lex/PPCallbacks.h"
anatofuz
parents:
diff changeset
29 #include "clang/Lex/Token.h"
anatofuz
parents:
diff changeset
30 #include "llvm/ADT/APSInt.h"
anatofuz
parents:
diff changeset
31 #include "llvm/ADT/SmallString.h"
anatofuz
parents:
diff changeset
32 #include "llvm/ADT/StringRef.h"
anatofuz
parents:
diff changeset
33 #include "llvm/Support/ErrorHandling.h"
anatofuz
parents:
diff changeset
34 #include "llvm/Support/SaveAndRestore.h"
anatofuz
parents:
diff changeset
35 #include <cassert>
anatofuz
parents:
diff changeset
36
anatofuz
parents:
diff changeset
37 using namespace clang;
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 namespace {
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 /// PPValue - Represents the value of a subexpression of a preprocessor
anatofuz
parents:
diff changeset
42 /// conditional and the source range covered by it.
anatofuz
parents:
diff changeset
43 class PPValue {
anatofuz
parents:
diff changeset
44 SourceRange Range;
anatofuz
parents:
diff changeset
45 IdentifierInfo *II;
anatofuz
parents:
diff changeset
46
anatofuz
parents:
diff changeset
47 public:
anatofuz
parents:
diff changeset
48 llvm::APSInt Val;
anatofuz
parents:
diff changeset
49
anatofuz
parents:
diff changeset
50 // Default ctor - Construct an 'invalid' PPValue.
anatofuz
parents:
diff changeset
51 PPValue(unsigned BitWidth) : Val(BitWidth) {}
anatofuz
parents:
diff changeset
52
anatofuz
parents:
diff changeset
53 // If this value was produced by directly evaluating an identifier, produce
anatofuz
parents:
diff changeset
54 // that identifier.
anatofuz
parents:
diff changeset
55 IdentifierInfo *getIdentifier() const { return II; }
anatofuz
parents:
diff changeset
56 void setIdentifier(IdentifierInfo *II) { this->II = II; }
anatofuz
parents:
diff changeset
57
anatofuz
parents:
diff changeset
58 unsigned getBitWidth() const { return Val.getBitWidth(); }
anatofuz
parents:
diff changeset
59 bool isUnsigned() const { return Val.isUnsigned(); }
anatofuz
parents:
diff changeset
60
anatofuz
parents:
diff changeset
61 SourceRange getRange() const { return Range; }
anatofuz
parents:
diff changeset
62
anatofuz
parents:
diff changeset
63 void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
anatofuz
parents:
diff changeset
64 void setRange(SourceLocation B, SourceLocation E) {
anatofuz
parents:
diff changeset
65 Range.setBegin(B); Range.setEnd(E);
anatofuz
parents:
diff changeset
66 }
anatofuz
parents:
diff changeset
67 void setBegin(SourceLocation L) { Range.setBegin(L); }
anatofuz
parents:
diff changeset
68 void setEnd(SourceLocation L) { Range.setEnd(L); }
anatofuz
parents:
diff changeset
69 };
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 } // end anonymous namespace
anatofuz
parents:
diff changeset
72
anatofuz
parents:
diff changeset
73 static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
anatofuz
parents:
diff changeset
74 Token &PeekTok, bool ValueLive,
anatofuz
parents:
diff changeset
75 bool &IncludedUndefinedIds,
anatofuz
parents:
diff changeset
76 Preprocessor &PP);
anatofuz
parents:
diff changeset
77
anatofuz
parents:
diff changeset
78 /// DefinedTracker - This struct is used while parsing expressions to keep track
anatofuz
parents:
diff changeset
79 /// of whether !defined(X) has been seen.
anatofuz
parents:
diff changeset
80 ///
anatofuz
parents:
diff changeset
81 /// With this simple scheme, we handle the basic forms:
anatofuz
parents:
diff changeset
82 /// !defined(X) and !defined X
anatofuz
parents:
diff changeset
83 /// but we also trivially handle (silly) stuff like:
anatofuz
parents:
diff changeset
84 /// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).
anatofuz
parents:
diff changeset
85 struct DefinedTracker {
anatofuz
parents:
diff changeset
86 /// Each time a Value is evaluated, it returns information about whether the
anatofuz
parents:
diff changeset
87 /// parsed value is of the form defined(X), !defined(X) or is something else.
anatofuz
parents:
diff changeset
88 enum TrackerState {
anatofuz
parents:
diff changeset
89 DefinedMacro, // defined(X)
anatofuz
parents:
diff changeset
90 NotDefinedMacro, // !defined(X)
anatofuz
parents:
diff changeset
91 Unknown // Something else.
anatofuz
parents:
diff changeset
92 } State;
anatofuz
parents:
diff changeset
93 /// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
anatofuz
parents:
diff changeset
94 /// indicates the macro that was checked.
anatofuz
parents:
diff changeset
95 IdentifierInfo *TheMacro;
anatofuz
parents:
diff changeset
96 bool IncludedUndefinedIds = false;
anatofuz
parents:
diff changeset
97 };
anatofuz
parents:
diff changeset
98
anatofuz
parents:
diff changeset
99 /// EvaluateDefined - Process a 'defined(sym)' expression.
anatofuz
parents:
diff changeset
100 static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
anatofuz
parents:
diff changeset
101 bool ValueLive, Preprocessor &PP) {
anatofuz
parents:
diff changeset
102 SourceLocation beginLoc(PeekTok.getLocation());
anatofuz
parents:
diff changeset
103 Result.setBegin(beginLoc);
anatofuz
parents:
diff changeset
104
anatofuz
parents:
diff changeset
105 // Get the next token, don't expand it.
anatofuz
parents:
diff changeset
106 PP.LexUnexpandedNonComment(PeekTok);
anatofuz
parents:
diff changeset
107
anatofuz
parents:
diff changeset
108 // Two options, it can either be a pp-identifier or a (.
anatofuz
parents:
diff changeset
109 SourceLocation LParenLoc;
anatofuz
parents:
diff changeset
110 if (PeekTok.is(tok::l_paren)) {
anatofuz
parents:
diff changeset
111 // Found a paren, remember we saw it and skip it.
anatofuz
parents:
diff changeset
112 LParenLoc = PeekTok.getLocation();
anatofuz
parents:
diff changeset
113 PP.LexUnexpandedNonComment(PeekTok);
anatofuz
parents:
diff changeset
114 }
anatofuz
parents:
diff changeset
115
anatofuz
parents:
diff changeset
116 if (PeekTok.is(tok::code_completion)) {
anatofuz
parents:
diff changeset
117 if (PP.getCodeCompletionHandler())
anatofuz
parents:
diff changeset
118 PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
anatofuz
parents:
diff changeset
119 PP.setCodeCompletionReached();
anatofuz
parents:
diff changeset
120 PP.LexUnexpandedNonComment(PeekTok);
anatofuz
parents:
diff changeset
121 }
anatofuz
parents:
diff changeset
122
anatofuz
parents:
diff changeset
123 // If we don't have a pp-identifier now, this is an error.
anatofuz
parents:
diff changeset
124 if (PP.CheckMacroName(PeekTok, MU_Other))
anatofuz
parents:
diff changeset
125 return true;
anatofuz
parents:
diff changeset
126
anatofuz
parents:
diff changeset
127 // Otherwise, we got an identifier, is it defined to something?
anatofuz
parents:
diff changeset
128 IdentifierInfo *II = PeekTok.getIdentifierInfo();
anatofuz
parents:
diff changeset
129 MacroDefinition Macro = PP.getMacroDefinition(II);
anatofuz
parents:
diff changeset
130 Result.Val = !!Macro;
anatofuz
parents:
diff changeset
131 Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
anatofuz
parents:
diff changeset
132 DT.IncludedUndefinedIds = !Macro;
anatofuz
parents:
diff changeset
133
anatofuz
parents:
diff changeset
134 // If there is a macro, mark it used.
anatofuz
parents:
diff changeset
135 if (Result.Val != 0 && ValueLive)
anatofuz
parents:
diff changeset
136 PP.markMacroAsUsed(Macro.getMacroInfo());
anatofuz
parents:
diff changeset
137
anatofuz
parents:
diff changeset
138 // Save macro token for callback.
anatofuz
parents:
diff changeset
139 Token macroToken(PeekTok);
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 // If we are in parens, ensure we have a trailing ).
anatofuz
parents:
diff changeset
142 if (LParenLoc.isValid()) {
anatofuz
parents:
diff changeset
143 // Consume identifier.
anatofuz
parents:
diff changeset
144 Result.setEnd(PeekTok.getLocation());
anatofuz
parents:
diff changeset
145 PP.LexUnexpandedNonComment(PeekTok);
anatofuz
parents:
diff changeset
146
anatofuz
parents:
diff changeset
147 if (PeekTok.isNot(tok::r_paren)) {
anatofuz
parents:
diff changeset
148 PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after)
anatofuz
parents:
diff changeset
149 << "'defined'" << tok::r_paren;
anatofuz
parents:
diff changeset
150 PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
anatofuz
parents:
diff changeset
151 return true;
anatofuz
parents:
diff changeset
152 }
anatofuz
parents:
diff changeset
153 // Consume the ).
anatofuz
parents:
diff changeset
154 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
155 Result.setEnd(PeekTok.getLocation());
anatofuz
parents:
diff changeset
156 } else {
anatofuz
parents:
diff changeset
157 // Consume identifier.
anatofuz
parents:
diff changeset
158 Result.setEnd(PeekTok.getLocation());
anatofuz
parents:
diff changeset
159 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
160 }
anatofuz
parents:
diff changeset
161
anatofuz
parents:
diff changeset
162 // [cpp.cond]p4:
anatofuz
parents:
diff changeset
163 // Prior to evaluation, macro invocations in the list of preprocessing
anatofuz
parents:
diff changeset
164 // tokens that will become the controlling constant expression are replaced
anatofuz
parents:
diff changeset
165 // (except for those macro names modified by the 'defined' unary operator),
anatofuz
parents:
diff changeset
166 // just as in normal text. If the token 'defined' is generated as a result
anatofuz
parents:
diff changeset
167 // of this replacement process or use of the 'defined' unary operator does
anatofuz
parents:
diff changeset
168 // not match one of the two specified forms prior to macro replacement, the
anatofuz
parents:
diff changeset
169 // behavior is undefined.
anatofuz
parents:
diff changeset
170 // This isn't an idle threat, consider this program:
anatofuz
parents:
diff changeset
171 // #define FOO
anatofuz
parents:
diff changeset
172 // #define BAR defined(FOO)
anatofuz
parents:
diff changeset
173 // #if BAR
anatofuz
parents:
diff changeset
174 // ...
anatofuz
parents:
diff changeset
175 // #else
anatofuz
parents:
diff changeset
176 // ...
anatofuz
parents:
diff changeset
177 // #endif
anatofuz
parents:
diff changeset
178 // clang and gcc will pick the #if branch while Visual Studio will take the
anatofuz
parents:
diff changeset
179 // #else branch. Emit a warning about this undefined behavior.
anatofuz
parents:
diff changeset
180 if (beginLoc.isMacroID()) {
anatofuz
parents:
diff changeset
181 bool IsFunctionTypeMacro =
anatofuz
parents:
diff changeset
182 PP.getSourceManager()
anatofuz
parents:
diff changeset
183 .getSLocEntry(PP.getSourceManager().getFileID(beginLoc))
anatofuz
parents:
diff changeset
184 .getExpansion()
anatofuz
parents:
diff changeset
185 .isFunctionMacroExpansion();
anatofuz
parents:
diff changeset
186 // For object-type macros, it's easy to replace
anatofuz
parents:
diff changeset
187 // #define FOO defined(BAR)
anatofuz
parents:
diff changeset
188 // with
anatofuz
parents:
diff changeset
189 // #if defined(BAR)
anatofuz
parents:
diff changeset
190 // #define FOO 1
anatofuz
parents:
diff changeset
191 // #else
anatofuz
parents:
diff changeset
192 // #define FOO 0
anatofuz
parents:
diff changeset
193 // #endif
anatofuz
parents:
diff changeset
194 // and doing so makes sense since compilers handle this differently in
anatofuz
parents:
diff changeset
195 // practice (see example further up). But for function-type macros,
anatofuz
parents:
diff changeset
196 // there is no good way to write
anatofuz
parents:
diff changeset
197 // # define FOO(x) (defined(M_ ## x) && M_ ## x)
anatofuz
parents:
diff changeset
198 // in a different way, and compilers seem to agree on how to behave here.
anatofuz
parents:
diff changeset
199 // So warn by default on object-type macros, but only warn in -pedantic
anatofuz
parents:
diff changeset
200 // mode on function-type macros.
anatofuz
parents:
diff changeset
201 if (IsFunctionTypeMacro)
anatofuz
parents:
diff changeset
202 PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro);
anatofuz
parents:
diff changeset
203 else
anatofuz
parents:
diff changeset
204 PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro);
anatofuz
parents:
diff changeset
205 }
anatofuz
parents:
diff changeset
206
anatofuz
parents:
diff changeset
207 // Invoke the 'defined' callback.
anatofuz
parents:
diff changeset
208 if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
anatofuz
parents:
diff changeset
209 Callbacks->Defined(macroToken, Macro,
anatofuz
parents:
diff changeset
210 SourceRange(beginLoc, PeekTok.getLocation()));
anatofuz
parents:
diff changeset
211 }
anatofuz
parents:
diff changeset
212
anatofuz
parents:
diff changeset
213 // Success, remember that we saw defined(X).
anatofuz
parents:
diff changeset
214 DT.State = DefinedTracker::DefinedMacro;
anatofuz
parents:
diff changeset
215 DT.TheMacro = II;
anatofuz
parents:
diff changeset
216 return false;
anatofuz
parents:
diff changeset
217 }
anatofuz
parents:
diff changeset
218
anatofuz
parents:
diff changeset
219 /// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
anatofuz
parents:
diff changeset
220 /// return the computed value in Result. Return true if there was an error
anatofuz
parents:
diff changeset
221 /// parsing. This function also returns information about the form of the
anatofuz
parents:
diff changeset
222 /// expression in DT. See above for information on what DT means.
anatofuz
parents:
diff changeset
223 ///
anatofuz
parents:
diff changeset
224 /// If ValueLive is false, then this value is being evaluated in a context where
anatofuz
parents:
diff changeset
225 /// the result is not used. As such, avoid diagnostics that relate to
anatofuz
parents:
diff changeset
226 /// evaluation.
anatofuz
parents:
diff changeset
227 static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
anatofuz
parents:
diff changeset
228 bool ValueLive, Preprocessor &PP) {
anatofuz
parents:
diff changeset
229 DT.State = DefinedTracker::Unknown;
anatofuz
parents:
diff changeset
230
anatofuz
parents:
diff changeset
231 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
232
anatofuz
parents:
diff changeset
233 if (PeekTok.is(tok::code_completion)) {
anatofuz
parents:
diff changeset
234 if (PP.getCodeCompletionHandler())
anatofuz
parents:
diff changeset
235 PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
anatofuz
parents:
diff changeset
236 PP.setCodeCompletionReached();
anatofuz
parents:
diff changeset
237 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
238 }
anatofuz
parents:
diff changeset
239
anatofuz
parents:
diff changeset
240 switch (PeekTok.getKind()) {
anatofuz
parents:
diff changeset
241 default:
anatofuz
parents:
diff changeset
242 // If this token's spelling is a pp-identifier, check to see if it is
anatofuz
parents:
diff changeset
243 // 'defined' or if it is a macro. Note that we check here because many
anatofuz
parents:
diff changeset
244 // keywords are pp-identifiers, so we can't check the kind.
anatofuz
parents:
diff changeset
245 if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
anatofuz
parents:
diff changeset
246 // Handle "defined X" and "defined(X)".
anatofuz
parents:
diff changeset
247 if (II->isStr("defined"))
anatofuz
parents:
diff changeset
248 return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP);
anatofuz
parents:
diff changeset
249
anatofuz
parents:
diff changeset
250 if (!II->isCPlusPlusOperatorKeyword()) {
anatofuz
parents:
diff changeset
251 // If this identifier isn't 'defined' or one of the special
anatofuz
parents:
diff changeset
252 // preprocessor keywords and it wasn't macro expanded, it turns
anatofuz
parents:
diff changeset
253 // into a simple 0
anatofuz
parents:
diff changeset
254 if (ValueLive)
anatofuz
parents:
diff changeset
255 PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
anatofuz
parents:
diff changeset
256 Result.Val = 0;
anatofuz
parents:
diff changeset
257 Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
anatofuz
parents:
diff changeset
258 Result.setIdentifier(II);
anatofuz
parents:
diff changeset
259 Result.setRange(PeekTok.getLocation());
anatofuz
parents:
diff changeset
260 DT.IncludedUndefinedIds = true;
anatofuz
parents:
diff changeset
261 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
262 return false;
anatofuz
parents:
diff changeset
263 }
anatofuz
parents:
diff changeset
264 }
anatofuz
parents:
diff changeset
265 PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
anatofuz
parents:
diff changeset
266 return true;
anatofuz
parents:
diff changeset
267 case tok::eod:
anatofuz
parents:
diff changeset
268 case tok::r_paren:
anatofuz
parents:
diff changeset
269 // If there is no expression, report and exit.
anatofuz
parents:
diff changeset
270 PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
anatofuz
parents:
diff changeset
271 return true;
anatofuz
parents:
diff changeset
272 case tok::numeric_constant: {
anatofuz
parents:
diff changeset
273 SmallString<64> IntegerBuffer;
anatofuz
parents:
diff changeset
274 bool NumberInvalid = false;
anatofuz
parents:
diff changeset
275 StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
anatofuz
parents:
diff changeset
276 &NumberInvalid);
anatofuz
parents:
diff changeset
277 if (NumberInvalid)
anatofuz
parents:
diff changeset
278 return true; // a diagnostic was already reported
anatofuz
parents:
diff changeset
279
anatofuz
parents:
diff changeset
280 NumericLiteralParser Literal(Spelling, PeekTok.getLocation(), PP);
anatofuz
parents:
diff changeset
281 if (Literal.hadError)
anatofuz
parents:
diff changeset
282 return true; // a diagnostic was already reported.
anatofuz
parents:
diff changeset
283
anatofuz
parents:
diff changeset
284 if (Literal.isFloatingLiteral() || Literal.isImaginary) {
anatofuz
parents:
diff changeset
285 PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);
anatofuz
parents:
diff changeset
286 return true;
anatofuz
parents:
diff changeset
287 }
anatofuz
parents:
diff changeset
288 assert(Literal.isIntegerLiteral() && "Unknown ppnumber");
anatofuz
parents:
diff changeset
289
anatofuz
parents:
diff changeset
290 // Complain about, and drop, any ud-suffix.
anatofuz
parents:
diff changeset
291 if (Literal.hasUDSuffix())
anatofuz
parents:
diff changeset
292 PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*integer*/1;
anatofuz
parents:
diff changeset
293
anatofuz
parents:
diff changeset
294 // 'long long' is a C99 or C++11 feature.
anatofuz
parents:
diff changeset
295 if (!PP.getLangOpts().C99 && Literal.isLongLong) {
anatofuz
parents:
diff changeset
296 if (PP.getLangOpts().CPlusPlus)
anatofuz
parents:
diff changeset
297 PP.Diag(PeekTok,
anatofuz
parents:
diff changeset
298 PP.getLangOpts().CPlusPlus11 ?
anatofuz
parents:
diff changeset
299 diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
anatofuz
parents:
diff changeset
300 else
anatofuz
parents:
diff changeset
301 PP.Diag(PeekTok, diag::ext_c99_longlong);
anatofuz
parents:
diff changeset
302 }
anatofuz
parents:
diff changeset
303
anatofuz
parents:
diff changeset
304 // Parse the integer literal into Result.
anatofuz
parents:
diff changeset
305 if (Literal.GetIntegerValue(Result.Val)) {
anatofuz
parents:
diff changeset
306 // Overflow parsing integer literal.
anatofuz
parents:
diff changeset
307 if (ValueLive)
anatofuz
parents:
diff changeset
308 PP.Diag(PeekTok, diag::err_integer_literal_too_large)
anatofuz
parents:
diff changeset
309 << /* Unsigned */ 1;
anatofuz
parents:
diff changeset
310 Result.Val.setIsUnsigned(true);
anatofuz
parents:
diff changeset
311 } else {
anatofuz
parents:
diff changeset
312 // Set the signedness of the result to match whether there was a U suffix
anatofuz
parents:
diff changeset
313 // or not.
anatofuz
parents:
diff changeset
314 Result.Val.setIsUnsigned(Literal.isUnsigned);
anatofuz
parents:
diff changeset
315
anatofuz
parents:
diff changeset
316 // Detect overflow based on whether the value is signed. If signed
anatofuz
parents:
diff changeset
317 // and if the value is too large, emit a warning "integer constant is so
anatofuz
parents:
diff changeset
318 // large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
anatofuz
parents:
diff changeset
319 // is 64-bits.
anatofuz
parents:
diff changeset
320 if (!Literal.isUnsigned && Result.Val.isNegative()) {
anatofuz
parents:
diff changeset
321 // Octal, hexadecimal, and binary literals are implicitly unsigned if
anatofuz
parents:
diff changeset
322 // the value does not fit into a signed integer type.
anatofuz
parents:
diff changeset
323 if (ValueLive && Literal.getRadix() == 10)
anatofuz
parents:
diff changeset
324 PP.Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);
anatofuz
parents:
diff changeset
325 Result.Val.setIsUnsigned(true);
anatofuz
parents:
diff changeset
326 }
anatofuz
parents:
diff changeset
327 }
anatofuz
parents:
diff changeset
328
anatofuz
parents:
diff changeset
329 // Consume the token.
anatofuz
parents:
diff changeset
330 Result.setRange(PeekTok.getLocation());
anatofuz
parents:
diff changeset
331 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
332 return false;
anatofuz
parents:
diff changeset
333 }
anatofuz
parents:
diff changeset
334 case tok::char_constant: // 'x'
anatofuz
parents:
diff changeset
335 case tok::wide_char_constant: // L'x'
anatofuz
parents:
diff changeset
336 case tok::utf8_char_constant: // u8'x'
anatofuz
parents:
diff changeset
337 case tok::utf16_char_constant: // u'x'
anatofuz
parents:
diff changeset
338 case tok::utf32_char_constant: { // U'x'
anatofuz
parents:
diff changeset
339 // Complain about, and drop, any ud-suffix.
anatofuz
parents:
diff changeset
340 if (PeekTok.hasUDSuffix())
anatofuz
parents:
diff changeset
341 PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*character*/0;
anatofuz
parents:
diff changeset
342
anatofuz
parents:
diff changeset
343 SmallString<32> CharBuffer;
anatofuz
parents:
diff changeset
344 bool CharInvalid = false;
anatofuz
parents:
diff changeset
345 StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
anatofuz
parents:
diff changeset
346 if (CharInvalid)
anatofuz
parents:
diff changeset
347 return true;
anatofuz
parents:
diff changeset
348
anatofuz
parents:
diff changeset
349 CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
anatofuz
parents:
diff changeset
350 PeekTok.getLocation(), PP, PeekTok.getKind());
anatofuz
parents:
diff changeset
351 if (Literal.hadError())
anatofuz
parents:
diff changeset
352 return true; // A diagnostic was already emitted.
anatofuz
parents:
diff changeset
353
anatofuz
parents:
diff changeset
354 // Character literals are always int or wchar_t, expand to intmax_t.
anatofuz
parents:
diff changeset
355 const TargetInfo &TI = PP.getTargetInfo();
anatofuz
parents:
diff changeset
356 unsigned NumBits;
anatofuz
parents:
diff changeset
357 if (Literal.isMultiChar())
anatofuz
parents:
diff changeset
358 NumBits = TI.getIntWidth();
anatofuz
parents:
diff changeset
359 else if (Literal.isWide())
anatofuz
parents:
diff changeset
360 NumBits = TI.getWCharWidth();
anatofuz
parents:
diff changeset
361 else if (Literal.isUTF16())
anatofuz
parents:
diff changeset
362 NumBits = TI.getChar16Width();
anatofuz
parents:
diff changeset
363 else if (Literal.isUTF32())
anatofuz
parents:
diff changeset
364 NumBits = TI.getChar32Width();
anatofuz
parents:
diff changeset
365 else // char or char8_t
anatofuz
parents:
diff changeset
366 NumBits = TI.getCharWidth();
anatofuz
parents:
diff changeset
367
anatofuz
parents:
diff changeset
368 // Set the width.
anatofuz
parents:
diff changeset
369 llvm::APSInt Val(NumBits);
anatofuz
parents:
diff changeset
370 // Set the value.
anatofuz
parents:
diff changeset
371 Val = Literal.getValue();
anatofuz
parents:
diff changeset
372 // Set the signedness. UTF-16 and UTF-32 are always unsigned
anatofuz
parents:
diff changeset
373 if (Literal.isWide())
anatofuz
parents:
diff changeset
374 Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType()));
anatofuz
parents:
diff changeset
375 else if (!Literal.isUTF16() && !Literal.isUTF32())
anatofuz
parents:
diff changeset
376 Val.setIsUnsigned(!PP.getLangOpts().CharIsSigned);
anatofuz
parents:
diff changeset
377
anatofuz
parents:
diff changeset
378 if (Result.Val.getBitWidth() > Val.getBitWidth()) {
anatofuz
parents:
diff changeset
379 Result.Val = Val.extend(Result.Val.getBitWidth());
anatofuz
parents:
diff changeset
380 } else {
anatofuz
parents:
diff changeset
381 assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
anatofuz
parents:
diff changeset
382 "intmax_t smaller than char/wchar_t?");
anatofuz
parents:
diff changeset
383 Result.Val = Val;
anatofuz
parents:
diff changeset
384 }
anatofuz
parents:
diff changeset
385
anatofuz
parents:
diff changeset
386 // Consume the token.
anatofuz
parents:
diff changeset
387 Result.setRange(PeekTok.getLocation());
anatofuz
parents:
diff changeset
388 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
389 return false;
anatofuz
parents:
diff changeset
390 }
anatofuz
parents:
diff changeset
391 case tok::l_paren: {
anatofuz
parents:
diff changeset
392 SourceLocation Start = PeekTok.getLocation();
anatofuz
parents:
diff changeset
393 PP.LexNonComment(PeekTok); // Eat the (.
anatofuz
parents:
diff changeset
394 // Parse the value and if there are any binary operators involved, parse
anatofuz
parents:
diff changeset
395 // them.
anatofuz
parents:
diff changeset
396 if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
anatofuz
parents:
diff changeset
397
anatofuz
parents:
diff changeset
398 // If this is a silly value like (X), which doesn't need parens, check for
anatofuz
parents:
diff changeset
399 // !(defined X).
anatofuz
parents:
diff changeset
400 if (PeekTok.is(tok::r_paren)) {
anatofuz
parents:
diff changeset
401 // Just use DT unmodified as our result.
anatofuz
parents:
diff changeset
402 } else {
anatofuz
parents:
diff changeset
403 // Otherwise, we have something like (x+y), and we consumed '(x'.
anatofuz
parents:
diff changeset
404 if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive,
anatofuz
parents:
diff changeset
405 DT.IncludedUndefinedIds, PP))
anatofuz
parents:
diff changeset
406 return true;
anatofuz
parents:
diff changeset
407
anatofuz
parents:
diff changeset
408 if (PeekTok.isNot(tok::r_paren)) {
anatofuz
parents:
diff changeset
409 PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
anatofuz
parents:
diff changeset
410 << Result.getRange();
anatofuz
parents:
diff changeset
411 PP.Diag(Start, diag::note_matching) << tok::l_paren;
anatofuz
parents:
diff changeset
412 return true;
anatofuz
parents:
diff changeset
413 }
anatofuz
parents:
diff changeset
414 DT.State = DefinedTracker::Unknown;
anatofuz
parents:
diff changeset
415 }
anatofuz
parents:
diff changeset
416 Result.setRange(Start, PeekTok.getLocation());
anatofuz
parents:
diff changeset
417 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
418 PP.LexNonComment(PeekTok); // Eat the ).
anatofuz
parents:
diff changeset
419 return false;
anatofuz
parents:
diff changeset
420 }
anatofuz
parents:
diff changeset
421 case tok::plus: {
anatofuz
parents:
diff changeset
422 SourceLocation Start = PeekTok.getLocation();
anatofuz
parents:
diff changeset
423 // Unary plus doesn't modify the value.
anatofuz
parents:
diff changeset
424 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
425 if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
anatofuz
parents:
diff changeset
426 Result.setBegin(Start);
anatofuz
parents:
diff changeset
427 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
428 return false;
anatofuz
parents:
diff changeset
429 }
anatofuz
parents:
diff changeset
430 case tok::minus: {
anatofuz
parents:
diff changeset
431 SourceLocation Loc = PeekTok.getLocation();
anatofuz
parents:
diff changeset
432 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
433 if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
anatofuz
parents:
diff changeset
434 Result.setBegin(Loc);
anatofuz
parents:
diff changeset
435 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
436
anatofuz
parents:
diff changeset
437 // C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
anatofuz
parents:
diff changeset
438 Result.Val = -Result.Val;
anatofuz
parents:
diff changeset
439
anatofuz
parents:
diff changeset
440 // -MININT is the only thing that overflows. Unsigned never overflows.
anatofuz
parents:
diff changeset
441 bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();
anatofuz
parents:
diff changeset
442
anatofuz
parents:
diff changeset
443 // If this operator is live and overflowed, report the issue.
anatofuz
parents:
diff changeset
444 if (Overflow && ValueLive)
anatofuz
parents:
diff changeset
445 PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange();
anatofuz
parents:
diff changeset
446
anatofuz
parents:
diff changeset
447 DT.State = DefinedTracker::Unknown;
anatofuz
parents:
diff changeset
448 return false;
anatofuz
parents:
diff changeset
449 }
anatofuz
parents:
diff changeset
450
anatofuz
parents:
diff changeset
451 case tok::tilde: {
anatofuz
parents:
diff changeset
452 SourceLocation Start = PeekTok.getLocation();
anatofuz
parents:
diff changeset
453 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
454 if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
anatofuz
parents:
diff changeset
455 Result.setBegin(Start);
anatofuz
parents:
diff changeset
456 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
457
anatofuz
parents:
diff changeset
458 // C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
anatofuz
parents:
diff changeset
459 Result.Val = ~Result.Val;
anatofuz
parents:
diff changeset
460 DT.State = DefinedTracker::Unknown;
anatofuz
parents:
diff changeset
461 return false;
anatofuz
parents:
diff changeset
462 }
anatofuz
parents:
diff changeset
463
anatofuz
parents:
diff changeset
464 case tok::exclaim: {
anatofuz
parents:
diff changeset
465 SourceLocation Start = PeekTok.getLocation();
anatofuz
parents:
diff changeset
466 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
467 if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
anatofuz
parents:
diff changeset
468 Result.setBegin(Start);
anatofuz
parents:
diff changeset
469 Result.Val = !Result.Val;
anatofuz
parents:
diff changeset
470 // C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
anatofuz
parents:
diff changeset
471 Result.Val.setIsUnsigned(false);
anatofuz
parents:
diff changeset
472 Result.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
473
anatofuz
parents:
diff changeset
474 if (DT.State == DefinedTracker::DefinedMacro)
anatofuz
parents:
diff changeset
475 DT.State = DefinedTracker::NotDefinedMacro;
anatofuz
parents:
diff changeset
476 else if (DT.State == DefinedTracker::NotDefinedMacro)
anatofuz
parents:
diff changeset
477 DT.State = DefinedTracker::DefinedMacro;
anatofuz
parents:
diff changeset
478 return false;
anatofuz
parents:
diff changeset
479 }
anatofuz
parents:
diff changeset
480 case tok::kw_true:
anatofuz
parents:
diff changeset
481 case tok::kw_false:
anatofuz
parents:
diff changeset
482 Result.Val = PeekTok.getKind() == tok::kw_true;
anatofuz
parents:
diff changeset
483 Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
anatofuz
parents:
diff changeset
484 Result.setIdentifier(PeekTok.getIdentifierInfo());
anatofuz
parents:
diff changeset
485 Result.setRange(PeekTok.getLocation());
anatofuz
parents:
diff changeset
486 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
487 return false;
anatofuz
parents:
diff changeset
488
anatofuz
parents:
diff changeset
489 // FIXME: Handle #assert
anatofuz
parents:
diff changeset
490 }
anatofuz
parents:
diff changeset
491 }
anatofuz
parents:
diff changeset
492
anatofuz
parents:
diff changeset
493 /// getPrecedence - Return the precedence of the specified binary operator
anatofuz
parents:
diff changeset
494 /// token. This returns:
anatofuz
parents:
diff changeset
495 /// ~0 - Invalid token.
anatofuz
parents:
diff changeset
496 /// 14 -> 3 - various operators.
anatofuz
parents:
diff changeset
497 /// 0 - 'eod' or ')'
anatofuz
parents:
diff changeset
498 static unsigned getPrecedence(tok::TokenKind Kind) {
anatofuz
parents:
diff changeset
499 switch (Kind) {
anatofuz
parents:
diff changeset
500 default: return ~0U;
anatofuz
parents:
diff changeset
501 case tok::percent:
anatofuz
parents:
diff changeset
502 case tok::slash:
anatofuz
parents:
diff changeset
503 case tok::star: return 14;
anatofuz
parents:
diff changeset
504 case tok::plus:
anatofuz
parents:
diff changeset
505 case tok::minus: return 13;
anatofuz
parents:
diff changeset
506 case tok::lessless:
anatofuz
parents:
diff changeset
507 case tok::greatergreater: return 12;
anatofuz
parents:
diff changeset
508 case tok::lessequal:
anatofuz
parents:
diff changeset
509 case tok::less:
anatofuz
parents:
diff changeset
510 case tok::greaterequal:
anatofuz
parents:
diff changeset
511 case tok::greater: return 11;
anatofuz
parents:
diff changeset
512 case tok::exclaimequal:
anatofuz
parents:
diff changeset
513 case tok::equalequal: return 10;
anatofuz
parents:
diff changeset
514 case tok::amp: return 9;
anatofuz
parents:
diff changeset
515 case tok::caret: return 8;
anatofuz
parents:
diff changeset
516 case tok::pipe: return 7;
anatofuz
parents:
diff changeset
517 case tok::ampamp: return 6;
anatofuz
parents:
diff changeset
518 case tok::pipepipe: return 5;
anatofuz
parents:
diff changeset
519 case tok::question: return 4;
anatofuz
parents:
diff changeset
520 case tok::comma: return 3;
anatofuz
parents:
diff changeset
521 case tok::colon: return 2;
anatofuz
parents:
diff changeset
522 case tok::r_paren: return 0;// Lowest priority, end of expr.
anatofuz
parents:
diff changeset
523 case tok::eod: return 0;// Lowest priority, end of directive.
anatofuz
parents:
diff changeset
524 }
anatofuz
parents:
diff changeset
525 }
anatofuz
parents:
diff changeset
526
anatofuz
parents:
diff changeset
527 static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,
anatofuz
parents:
diff changeset
528 Token &Tok) {
anatofuz
parents:
diff changeset
529 if (Tok.is(tok::l_paren) && LHS.getIdentifier())
anatofuz
parents:
diff changeset
530 PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
anatofuz
parents:
diff changeset
531 << LHS.getIdentifier();
anatofuz
parents:
diff changeset
532 else
anatofuz
parents:
diff changeset
533 PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
anatofuz
parents:
diff changeset
534 << LHS.getRange();
anatofuz
parents:
diff changeset
535 }
anatofuz
parents:
diff changeset
536
anatofuz
parents:
diff changeset
537 /// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
anatofuz
parents:
diff changeset
538 /// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS.
anatofuz
parents:
diff changeset
539 ///
anatofuz
parents:
diff changeset
540 /// If ValueLive is false, then this value is being evaluated in a context where
anatofuz
parents:
diff changeset
541 /// the result is not used. As such, avoid diagnostics that relate to
anatofuz
parents:
diff changeset
542 /// evaluation, such as division by zero warnings.
anatofuz
parents:
diff changeset
543 static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
anatofuz
parents:
diff changeset
544 Token &PeekTok, bool ValueLive,
anatofuz
parents:
diff changeset
545 bool &IncludedUndefinedIds,
anatofuz
parents:
diff changeset
546 Preprocessor &PP) {
anatofuz
parents:
diff changeset
547 unsigned PeekPrec = getPrecedence(PeekTok.getKind());
anatofuz
parents:
diff changeset
548 // If this token isn't valid, report the error.
anatofuz
parents:
diff changeset
549 if (PeekPrec == ~0U) {
anatofuz
parents:
diff changeset
550 diagnoseUnexpectedOperator(PP, LHS, PeekTok);
anatofuz
parents:
diff changeset
551 return true;
anatofuz
parents:
diff changeset
552 }
anatofuz
parents:
diff changeset
553
anatofuz
parents:
diff changeset
554 while (true) {
anatofuz
parents:
diff changeset
555 // If this token has a lower precedence than we are allowed to parse, return
anatofuz
parents:
diff changeset
556 // it so that higher levels of the recursion can parse it.
anatofuz
parents:
diff changeset
557 if (PeekPrec < MinPrec)
anatofuz
parents:
diff changeset
558 return false;
anatofuz
parents:
diff changeset
559
anatofuz
parents:
diff changeset
560 tok::TokenKind Operator = PeekTok.getKind();
anatofuz
parents:
diff changeset
561
anatofuz
parents:
diff changeset
562 // If this is a short-circuiting operator, see if the RHS of the operator is
anatofuz
parents:
diff changeset
563 // dead. Note that this cannot just clobber ValueLive. Consider
anatofuz
parents:
diff changeset
564 // "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In
anatofuz
parents:
diff changeset
565 // this example, the RHS of the && being dead does not make the rest of the
anatofuz
parents:
diff changeset
566 // expr dead.
anatofuz
parents:
diff changeset
567 bool RHSIsLive;
anatofuz
parents:
diff changeset
568 if (Operator == tok::ampamp && LHS.Val == 0)
anatofuz
parents:
diff changeset
569 RHSIsLive = false; // RHS of "0 && x" is dead.
anatofuz
parents:
diff changeset
570 else if (Operator == tok::pipepipe && LHS.Val != 0)
anatofuz
parents:
diff changeset
571 RHSIsLive = false; // RHS of "1 || x" is dead.
anatofuz
parents:
diff changeset
572 else if (Operator == tok::question && LHS.Val == 0)
anatofuz
parents:
diff changeset
573 RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.
anatofuz
parents:
diff changeset
574 else
anatofuz
parents:
diff changeset
575 RHSIsLive = ValueLive;
anatofuz
parents:
diff changeset
576
anatofuz
parents:
diff changeset
577 // Consume the operator, remembering the operator's location for reporting.
anatofuz
parents:
diff changeset
578 SourceLocation OpLoc = PeekTok.getLocation();
anatofuz
parents:
diff changeset
579 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
580
anatofuz
parents:
diff changeset
581 PPValue RHS(LHS.getBitWidth());
anatofuz
parents:
diff changeset
582 // Parse the RHS of the operator.
anatofuz
parents:
diff changeset
583 DefinedTracker DT;
anatofuz
parents:
diff changeset
584 if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
anatofuz
parents:
diff changeset
585 IncludedUndefinedIds = DT.IncludedUndefinedIds;
anatofuz
parents:
diff changeset
586
anatofuz
parents:
diff changeset
587 // Remember the precedence of this operator and get the precedence of the
anatofuz
parents:
diff changeset
588 // operator immediately to the right of the RHS.
anatofuz
parents:
diff changeset
589 unsigned ThisPrec = PeekPrec;
anatofuz
parents:
diff changeset
590 PeekPrec = getPrecedence(PeekTok.getKind());
anatofuz
parents:
diff changeset
591
anatofuz
parents:
diff changeset
592 // If this token isn't valid, report the error.
anatofuz
parents:
diff changeset
593 if (PeekPrec == ~0U) {
anatofuz
parents:
diff changeset
594 diagnoseUnexpectedOperator(PP, RHS, PeekTok);
anatofuz
parents:
diff changeset
595 return true;
anatofuz
parents:
diff changeset
596 }
anatofuz
parents:
diff changeset
597
anatofuz
parents:
diff changeset
598 // Decide whether to include the next binop in this subexpression. For
anatofuz
parents:
diff changeset
599 // example, when parsing x+y*z and looking at '*', we want to recursively
anatofuz
parents:
diff changeset
600 // handle y*z as a single subexpression. We do this because the precedence
anatofuz
parents:
diff changeset
601 // of * is higher than that of +. The only strange case we have to handle
anatofuz
parents:
diff changeset
602 // here is for the ?: operator, where the precedence is actually lower than
anatofuz
parents:
diff changeset
603 // the LHS of the '?'. The grammar rule is:
anatofuz
parents:
diff changeset
604 //
anatofuz
parents:
diff changeset
605 // conditional-expression ::=
anatofuz
parents:
diff changeset
606 // logical-OR-expression ? expression : conditional-expression
anatofuz
parents:
diff changeset
607 // where 'expression' is actually comma-expression.
anatofuz
parents:
diff changeset
608 unsigned RHSPrec;
anatofuz
parents:
diff changeset
609 if (Operator == tok::question)
anatofuz
parents:
diff changeset
610 // The RHS of "?" should be maximally consumed as an expression.
anatofuz
parents:
diff changeset
611 RHSPrec = getPrecedence(tok::comma);
anatofuz
parents:
diff changeset
612 else // All others should munch while higher precedence.
anatofuz
parents:
diff changeset
613 RHSPrec = ThisPrec+1;
anatofuz
parents:
diff changeset
614
anatofuz
parents:
diff changeset
615 if (PeekPrec >= RHSPrec) {
anatofuz
parents:
diff changeset
616 if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive,
anatofuz
parents:
diff changeset
617 IncludedUndefinedIds, PP))
anatofuz
parents:
diff changeset
618 return true;
anatofuz
parents:
diff changeset
619 PeekPrec = getPrecedence(PeekTok.getKind());
anatofuz
parents:
diff changeset
620 }
anatofuz
parents:
diff changeset
621 assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
anatofuz
parents:
diff changeset
622
anatofuz
parents:
diff changeset
623 // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
anatofuz
parents:
diff changeset
624 // either operand is unsigned.
anatofuz
parents:
diff changeset
625 llvm::APSInt Res(LHS.getBitWidth());
anatofuz
parents:
diff changeset
626 switch (Operator) {
anatofuz
parents:
diff changeset
627 case tok::question: // No UAC for x and y in "x ? y : z".
anatofuz
parents:
diff changeset
628 case tok::lessless: // Shift amount doesn't UAC with shift value.
anatofuz
parents:
diff changeset
629 case tok::greatergreater: // Shift amount doesn't UAC with shift value.
anatofuz
parents:
diff changeset
630 case tok::comma: // Comma operands are not subject to UACs.
anatofuz
parents:
diff changeset
631 case tok::pipepipe: // Logical || does not do UACs.
anatofuz
parents:
diff changeset
632 case tok::ampamp: // Logical && does not do UACs.
anatofuz
parents:
diff changeset
633 break; // No UAC
anatofuz
parents:
diff changeset
634 default:
anatofuz
parents:
diff changeset
635 Res.setIsUnsigned(LHS.isUnsigned()|RHS.isUnsigned());
anatofuz
parents:
diff changeset
636 // If this just promoted something from signed to unsigned, and if the
anatofuz
parents:
diff changeset
637 // value was negative, warn about it.
anatofuz
parents:
diff changeset
638 if (ValueLive && Res.isUnsigned()) {
anatofuz
parents:
diff changeset
639 if (!LHS.isUnsigned() && LHS.Val.isNegative())
anatofuz
parents:
diff changeset
640 PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
anatofuz
parents:
diff changeset
641 << LHS.Val.toString(10, true) + " to " +
anatofuz
parents:
diff changeset
642 LHS.Val.toString(10, false)
anatofuz
parents:
diff changeset
643 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
644 if (!RHS.isUnsigned() && RHS.Val.isNegative())
anatofuz
parents:
diff changeset
645 PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
anatofuz
parents:
diff changeset
646 << RHS.Val.toString(10, true) + " to " +
anatofuz
parents:
diff changeset
647 RHS.Val.toString(10, false)
anatofuz
parents:
diff changeset
648 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
649 }
anatofuz
parents:
diff changeset
650 LHS.Val.setIsUnsigned(Res.isUnsigned());
anatofuz
parents:
diff changeset
651 RHS.Val.setIsUnsigned(Res.isUnsigned());
anatofuz
parents:
diff changeset
652 }
anatofuz
parents:
diff changeset
653
anatofuz
parents:
diff changeset
654 bool Overflow = false;
anatofuz
parents:
diff changeset
655 switch (Operator) {
anatofuz
parents:
diff changeset
656 default: llvm_unreachable("Unknown operator token!");
anatofuz
parents:
diff changeset
657 case tok::percent:
anatofuz
parents:
diff changeset
658 if (RHS.Val != 0)
anatofuz
parents:
diff changeset
659 Res = LHS.Val % RHS.Val;
anatofuz
parents:
diff changeset
660 else if (ValueLive) {
anatofuz
parents:
diff changeset
661 PP.Diag(OpLoc, diag::err_pp_remainder_by_zero)
anatofuz
parents:
diff changeset
662 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
663 return true;
anatofuz
parents:
diff changeset
664 }
anatofuz
parents:
diff changeset
665 break;
anatofuz
parents:
diff changeset
666 case tok::slash:
anatofuz
parents:
diff changeset
667 if (RHS.Val != 0) {
anatofuz
parents:
diff changeset
668 if (LHS.Val.isSigned())
anatofuz
parents:
diff changeset
669 Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false);
anatofuz
parents:
diff changeset
670 else
anatofuz
parents:
diff changeset
671 Res = LHS.Val / RHS.Val;
anatofuz
parents:
diff changeset
672 } else if (ValueLive) {
anatofuz
parents:
diff changeset
673 PP.Diag(OpLoc, diag::err_pp_division_by_zero)
anatofuz
parents:
diff changeset
674 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
675 return true;
anatofuz
parents:
diff changeset
676 }
anatofuz
parents:
diff changeset
677 break;
anatofuz
parents:
diff changeset
678
anatofuz
parents:
diff changeset
679 case tok::star:
anatofuz
parents:
diff changeset
680 if (Res.isSigned())
anatofuz
parents:
diff changeset
681 Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false);
anatofuz
parents:
diff changeset
682 else
anatofuz
parents:
diff changeset
683 Res = LHS.Val * RHS.Val;
anatofuz
parents:
diff changeset
684 break;
anatofuz
parents:
diff changeset
685 case tok::lessless: {
anatofuz
parents:
diff changeset
686 // Determine whether overflow is about to happen.
anatofuz
parents:
diff changeset
687 if (LHS.isUnsigned())
anatofuz
parents:
diff changeset
688 Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
anatofuz
parents:
diff changeset
689 else
anatofuz
parents:
diff changeset
690 Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow), false);
anatofuz
parents:
diff changeset
691 break;
anatofuz
parents:
diff changeset
692 }
anatofuz
parents:
diff changeset
693 case tok::greatergreater: {
anatofuz
parents:
diff changeset
694 // Determine whether overflow is about to happen.
anatofuz
parents:
diff changeset
695 unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
anatofuz
parents:
diff changeset
696 if (ShAmt >= LHS.getBitWidth()) {
anatofuz
parents:
diff changeset
697 Overflow = true;
anatofuz
parents:
diff changeset
698 ShAmt = LHS.getBitWidth()-1;
anatofuz
parents:
diff changeset
699 }
anatofuz
parents:
diff changeset
700 Res = LHS.Val >> ShAmt;
anatofuz
parents:
diff changeset
701 break;
anatofuz
parents:
diff changeset
702 }
anatofuz
parents:
diff changeset
703 case tok::plus:
anatofuz
parents:
diff changeset
704 if (LHS.isUnsigned())
anatofuz
parents:
diff changeset
705 Res = LHS.Val + RHS.Val;
anatofuz
parents:
diff changeset
706 else
anatofuz
parents:
diff changeset
707 Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false);
anatofuz
parents:
diff changeset
708 break;
anatofuz
parents:
diff changeset
709 case tok::minus:
anatofuz
parents:
diff changeset
710 if (LHS.isUnsigned())
anatofuz
parents:
diff changeset
711 Res = LHS.Val - RHS.Val;
anatofuz
parents:
diff changeset
712 else
anatofuz
parents:
diff changeset
713 Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false);
anatofuz
parents:
diff changeset
714 break;
anatofuz
parents:
diff changeset
715 case tok::lessequal:
anatofuz
parents:
diff changeset
716 Res = LHS.Val <= RHS.Val;
anatofuz
parents:
diff changeset
717 Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
anatofuz
parents:
diff changeset
718 break;
anatofuz
parents:
diff changeset
719 case tok::less:
anatofuz
parents:
diff changeset
720 Res = LHS.Val < RHS.Val;
anatofuz
parents:
diff changeset
721 Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
anatofuz
parents:
diff changeset
722 break;
anatofuz
parents:
diff changeset
723 case tok::greaterequal:
anatofuz
parents:
diff changeset
724 Res = LHS.Val >= RHS.Val;
anatofuz
parents:
diff changeset
725 Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
anatofuz
parents:
diff changeset
726 break;
anatofuz
parents:
diff changeset
727 case tok::greater:
anatofuz
parents:
diff changeset
728 Res = LHS.Val > RHS.Val;
anatofuz
parents:
diff changeset
729 Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
anatofuz
parents:
diff changeset
730 break;
anatofuz
parents:
diff changeset
731 case tok::exclaimequal:
anatofuz
parents:
diff changeset
732 Res = LHS.Val != RHS.Val;
anatofuz
parents:
diff changeset
733 Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
anatofuz
parents:
diff changeset
734 break;
anatofuz
parents:
diff changeset
735 case tok::equalequal:
anatofuz
parents:
diff changeset
736 Res = LHS.Val == RHS.Val;
anatofuz
parents:
diff changeset
737 Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
anatofuz
parents:
diff changeset
738 break;
anatofuz
parents:
diff changeset
739 case tok::amp:
anatofuz
parents:
diff changeset
740 Res = LHS.Val & RHS.Val;
anatofuz
parents:
diff changeset
741 break;
anatofuz
parents:
diff changeset
742 case tok::caret:
anatofuz
parents:
diff changeset
743 Res = LHS.Val ^ RHS.Val;
anatofuz
parents:
diff changeset
744 break;
anatofuz
parents:
diff changeset
745 case tok::pipe:
anatofuz
parents:
diff changeset
746 Res = LHS.Val | RHS.Val;
anatofuz
parents:
diff changeset
747 break;
anatofuz
parents:
diff changeset
748 case tok::ampamp:
anatofuz
parents:
diff changeset
749 Res = (LHS.Val != 0 && RHS.Val != 0);
anatofuz
parents:
diff changeset
750 Res.setIsUnsigned(false); // C99 6.5.13p3, result is always int (signed)
anatofuz
parents:
diff changeset
751 break;
anatofuz
parents:
diff changeset
752 case tok::pipepipe:
anatofuz
parents:
diff changeset
753 Res = (LHS.Val != 0 || RHS.Val != 0);
anatofuz
parents:
diff changeset
754 Res.setIsUnsigned(false); // C99 6.5.14p3, result is always int (signed)
anatofuz
parents:
diff changeset
755 break;
anatofuz
parents:
diff changeset
756 case tok::comma:
anatofuz
parents:
diff changeset
757 // Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99
anatofuz
parents:
diff changeset
758 // if not being evaluated.
anatofuz
parents:
diff changeset
759 if (!PP.getLangOpts().C99 || ValueLive)
anatofuz
parents:
diff changeset
760 PP.Diag(OpLoc, diag::ext_pp_comma_expr)
anatofuz
parents:
diff changeset
761 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
762 Res = RHS.Val; // LHS = LHS,RHS -> RHS.
anatofuz
parents:
diff changeset
763 break;
anatofuz
parents:
diff changeset
764 case tok::question: {
anatofuz
parents:
diff changeset
765 // Parse the : part of the expression.
anatofuz
parents:
diff changeset
766 if (PeekTok.isNot(tok::colon)) {
anatofuz
parents:
diff changeset
767 PP.Diag(PeekTok.getLocation(), diag::err_expected)
anatofuz
parents:
diff changeset
768 << tok::colon << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
769 PP.Diag(OpLoc, diag::note_matching) << tok::question;
anatofuz
parents:
diff changeset
770 return true;
anatofuz
parents:
diff changeset
771 }
anatofuz
parents:
diff changeset
772 // Consume the :.
anatofuz
parents:
diff changeset
773 PP.LexNonComment(PeekTok);
anatofuz
parents:
diff changeset
774
anatofuz
parents:
diff changeset
775 // Evaluate the value after the :.
anatofuz
parents:
diff changeset
776 bool AfterColonLive = ValueLive && LHS.Val == 0;
anatofuz
parents:
diff changeset
777 PPValue AfterColonVal(LHS.getBitWidth());
anatofuz
parents:
diff changeset
778 DefinedTracker DT;
anatofuz
parents:
diff changeset
779 if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
anatofuz
parents:
diff changeset
780 return true;
anatofuz
parents:
diff changeset
781
anatofuz
parents:
diff changeset
782 // Parse anything after the : with the same precedence as ?. We allow
anatofuz
parents:
diff changeset
783 // things of equal precedence because ?: is right associative.
anatofuz
parents:
diff changeset
784 if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,
anatofuz
parents:
diff changeset
785 PeekTok, AfterColonLive,
anatofuz
parents:
diff changeset
786 IncludedUndefinedIds, PP))
anatofuz
parents:
diff changeset
787 return true;
anatofuz
parents:
diff changeset
788
anatofuz
parents:
diff changeset
789 // Now that we have the condition, the LHS and the RHS of the :, evaluate.
anatofuz
parents:
diff changeset
790 Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
anatofuz
parents:
diff changeset
791 RHS.setEnd(AfterColonVal.getRange().getEnd());
anatofuz
parents:
diff changeset
792
anatofuz
parents:
diff changeset
793 // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
anatofuz
parents:
diff changeset
794 // either operand is unsigned.
anatofuz
parents:
diff changeset
795 Res.setIsUnsigned(RHS.isUnsigned() | AfterColonVal.isUnsigned());
anatofuz
parents:
diff changeset
796
anatofuz
parents:
diff changeset
797 // Figure out the precedence of the token after the : part.
anatofuz
parents:
diff changeset
798 PeekPrec = getPrecedence(PeekTok.getKind());
anatofuz
parents:
diff changeset
799 break;
anatofuz
parents:
diff changeset
800 }
anatofuz
parents:
diff changeset
801 case tok::colon:
anatofuz
parents:
diff changeset
802 // Don't allow :'s to float around without being part of ?: exprs.
anatofuz
parents:
diff changeset
803 PP.Diag(OpLoc, diag::err_pp_colon_without_question)
anatofuz
parents:
diff changeset
804 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
805 return true;
anatofuz
parents:
diff changeset
806 }
anatofuz
parents:
diff changeset
807
anatofuz
parents:
diff changeset
808 // If this operator is live and overflowed, report the issue.
anatofuz
parents:
diff changeset
809 if (Overflow && ValueLive)
anatofuz
parents:
diff changeset
810 PP.Diag(OpLoc, diag::warn_pp_expr_overflow)
anatofuz
parents:
diff changeset
811 << LHS.getRange() << RHS.getRange();
anatofuz
parents:
diff changeset
812
anatofuz
parents:
diff changeset
813 // Put the result back into 'LHS' for our next iteration.
anatofuz
parents:
diff changeset
814 LHS.Val = Res;
anatofuz
parents:
diff changeset
815 LHS.setEnd(RHS.getRange().getEnd());
anatofuz
parents:
diff changeset
816 RHS.setIdentifier(nullptr);
anatofuz
parents:
diff changeset
817 }
anatofuz
parents:
diff changeset
818 }
anatofuz
parents:
diff changeset
819
anatofuz
parents:
diff changeset
820 /// EvaluateDirectiveExpression - Evaluate an integer constant expression that
anatofuz
parents:
diff changeset
821 /// may occur after a #if or #elif directive. If the expression is equivalent
anatofuz
parents:
diff changeset
822 /// to "!defined(X)" return X in IfNDefMacro.
anatofuz
parents:
diff changeset
823 Preprocessor::DirectiveEvalResult
anatofuz
parents:
diff changeset
824 Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) {
anatofuz
parents:
diff changeset
825 SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true);
anatofuz
parents:
diff changeset
826 // Save the current state of 'DisableMacroExpansion' and reset it to false. If
anatofuz
parents:
diff changeset
827 // 'DisableMacroExpansion' is true, then we must be in a macro argument list
anatofuz
parents:
diff changeset
828 // in which case a directive is undefined behavior. We want macros to be able
anatofuz
parents:
diff changeset
829 // to recursively expand in order to get more gcc-list behavior, so we force
anatofuz
parents:
diff changeset
830 // DisableMacroExpansion to false and restore it when we're done parsing the
anatofuz
parents:
diff changeset
831 // expression.
anatofuz
parents:
diff changeset
832 bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
anatofuz
parents:
diff changeset
833 DisableMacroExpansion = false;
anatofuz
parents:
diff changeset
834
anatofuz
parents:
diff changeset
835 // Peek ahead one token.
anatofuz
parents:
diff changeset
836 Token Tok;
anatofuz
parents:
diff changeset
837 LexNonComment(Tok);
anatofuz
parents:
diff changeset
838
anatofuz
parents:
diff changeset
839 // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
anatofuz
parents:
diff changeset
840 unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
anatofuz
parents:
diff changeset
841
anatofuz
parents:
diff changeset
842 PPValue ResVal(BitWidth);
anatofuz
parents:
diff changeset
843 DefinedTracker DT;
anatofuz
parents:
diff changeset
844 SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation());
anatofuz
parents:
diff changeset
845 if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
anatofuz
parents:
diff changeset
846 // Parse error, skip the rest of the macro line.
anatofuz
parents:
diff changeset
847 SourceRange ConditionRange = ExprStartLoc;
anatofuz
parents:
diff changeset
848 if (Tok.isNot(tok::eod))
anatofuz
parents:
diff changeset
849 ConditionRange = DiscardUntilEndOfDirective();
anatofuz
parents:
diff changeset
850
anatofuz
parents:
diff changeset
851 // Restore 'DisableMacroExpansion'.
anatofuz
parents:
diff changeset
852 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
anatofuz
parents:
diff changeset
853
anatofuz
parents:
diff changeset
854 // We cannot trust the source range from the value because there was a
anatofuz
parents:
diff changeset
855 // parse error. Track the range manually -- the end of the directive is the
anatofuz
parents:
diff changeset
856 // end of the condition range.
anatofuz
parents:
diff changeset
857 return {false,
anatofuz
parents:
diff changeset
858 DT.IncludedUndefinedIds,
anatofuz
parents:
diff changeset
859 {ExprStartLoc, ConditionRange.getEnd()}};
anatofuz
parents:
diff changeset
860 }
anatofuz
parents:
diff changeset
861
anatofuz
parents:
diff changeset
862 // If we are at the end of the expression after just parsing a value, there
anatofuz
parents:
diff changeset
863 // must be no (unparenthesized) binary operators involved, so we can exit
anatofuz
parents:
diff changeset
864 // directly.
anatofuz
parents:
diff changeset
865 if (Tok.is(tok::eod)) {
anatofuz
parents:
diff changeset
866 // If the expression we parsed was of the form !defined(macro), return the
anatofuz
parents:
diff changeset
867 // macro in IfNDefMacro.
anatofuz
parents:
diff changeset
868 if (DT.State == DefinedTracker::NotDefinedMacro)
anatofuz
parents:
diff changeset
869 IfNDefMacro = DT.TheMacro;
anatofuz
parents:
diff changeset
870
anatofuz
parents:
diff changeset
871 // Restore 'DisableMacroExpansion'.
anatofuz
parents:
diff changeset
872 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
anatofuz
parents:
diff changeset
873 return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()};
anatofuz
parents:
diff changeset
874 }
anatofuz
parents:
diff changeset
875
anatofuz
parents:
diff changeset
876 // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
anatofuz
parents:
diff changeset
877 // operator and the stuff after it.
anatofuz
parents:
diff changeset
878 if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),
anatofuz
parents:
diff changeset
879 Tok, true, DT.IncludedUndefinedIds, *this)) {
anatofuz
parents:
diff changeset
880 // Parse error, skip the rest of the macro line.
anatofuz
parents:
diff changeset
881 if (Tok.isNot(tok::eod))
anatofuz
parents:
diff changeset
882 DiscardUntilEndOfDirective();
anatofuz
parents:
diff changeset
883
anatofuz
parents:
diff changeset
884 // Restore 'DisableMacroExpansion'.
anatofuz
parents:
diff changeset
885 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
anatofuz
parents:
diff changeset
886 return {false, DT.IncludedUndefinedIds, ResVal.getRange()};
anatofuz
parents:
diff changeset
887 }
anatofuz
parents:
diff changeset
888
anatofuz
parents:
diff changeset
889 // If we aren't at the tok::eod token, something bad happened, like an extra
anatofuz
parents:
diff changeset
890 // ')' token.
anatofuz
parents:
diff changeset
891 if (Tok.isNot(tok::eod)) {
anatofuz
parents:
diff changeset
892 Diag(Tok, diag::err_pp_expected_eol);
anatofuz
parents:
diff changeset
893 DiscardUntilEndOfDirective();
anatofuz
parents:
diff changeset
894 }
anatofuz
parents:
diff changeset
895
anatofuz
parents:
diff changeset
896 // Restore 'DisableMacroExpansion'.
anatofuz
parents:
diff changeset
897 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
anatofuz
parents:
diff changeset
898 return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()};
anatofuz
parents:
diff changeset
899 }