1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | #include "clang/Lex/Preprocessor.h" |
19 | #include "clang/Basic/IdentifierTable.h" |
20 | #include "clang/Basic/SourceLocation.h" |
21 | #include "clang/Basic/SourceManager.h" |
22 | #include "clang/Basic/TargetInfo.h" |
23 | #include "clang/Basic/TokenKinds.h" |
24 | #include "clang/Lex/CodeCompletionHandler.h" |
25 | #include "clang/Lex/LexDiagnostic.h" |
26 | #include "clang/Lex/LiteralSupport.h" |
27 | #include "clang/Lex/MacroInfo.h" |
28 | #include "clang/Lex/PPCallbacks.h" |
29 | #include "clang/Lex/Token.h" |
30 | #include "llvm/ADT/APSInt.h" |
31 | #include "llvm/ADT/SmallString.h" |
32 | #include "llvm/ADT/StringRef.h" |
33 | #include "llvm/Support/ErrorHandling.h" |
34 | #include "llvm/Support/SaveAndRestore.h" |
35 | #include <cassert> |
36 | |
37 | using namespace clang; |
38 | |
39 | namespace { |
40 | |
41 | |
42 | |
43 | class PPValue { |
44 | SourceRange Range; |
45 | IdentifierInfo *II; |
46 | |
47 | public: |
48 | llvm::APSInt Val; |
49 | |
50 | |
51 | PPValue(unsigned BitWidth) : Val(BitWidth) {} |
52 | |
53 | |
54 | |
55 | IdentifierInfo *getIdentifier() const { return II; } |
56 | void setIdentifier(IdentifierInfo *II) { this->II = II; } |
57 | |
58 | unsigned getBitWidth() const { return Val.getBitWidth(); } |
59 | bool isUnsigned() const { return Val.isUnsigned(); } |
60 | |
61 | SourceRange getRange() const { return Range; } |
62 | |
63 | void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); } |
64 | void setRange(SourceLocation B, SourceLocation E) { |
65 | Range.setBegin(B); Range.setEnd(E); |
66 | } |
67 | void setBegin(SourceLocation L) { Range.setBegin(L); } |
68 | void setEnd(SourceLocation L) { Range.setEnd(L); } |
69 | }; |
70 | |
71 | } |
72 | |
73 | static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, |
74 | Token &PeekTok, bool ValueLive, |
75 | bool &IncludedUndefinedIds, |
76 | Preprocessor &PP); |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | struct DefinedTracker { |
86 | |
87 | |
88 | enum TrackerState { |
89 | DefinedMacro, |
90 | NotDefinedMacro, |
91 | Unknown |
92 | } State; |
93 | |
94 | |
95 | IdentifierInfo *TheMacro; |
96 | bool IncludedUndefinedIds = false; |
97 | }; |
98 | |
99 | |
100 | static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, |
101 | bool ValueLive, Preprocessor &PP) { |
102 | SourceLocation beginLoc(PeekTok.getLocation()); |
103 | Result.setBegin(beginLoc); |
104 | |
105 | |
106 | PP.LexUnexpandedNonComment(PeekTok); |
107 | |
108 | |
109 | SourceLocation LParenLoc; |
110 | if (PeekTok.is(tok::l_paren)) { |
111 | |
112 | LParenLoc = PeekTok.getLocation(); |
113 | PP.LexUnexpandedNonComment(PeekTok); |
114 | } |
115 | |
116 | if (PeekTok.is(tok::code_completion)) { |
117 | if (PP.getCodeCompletionHandler()) |
118 | PP.getCodeCompletionHandler()->CodeCompleteMacroName(false); |
119 | PP.setCodeCompletionReached(); |
120 | PP.LexUnexpandedNonComment(PeekTok); |
121 | } |
122 | |
123 | |
124 | if (PP.CheckMacroName(PeekTok, MU_Other)) |
125 | return true; |
126 | |
127 | |
128 | IdentifierInfo *II = PeekTok.getIdentifierInfo(); |
129 | MacroDefinition Macro = PP.getMacroDefinition(II); |
130 | Result.Val = !!Macro; |
131 | Result.Val.setIsUnsigned(false); |
132 | DT.IncludedUndefinedIds = !Macro; |
133 | |
134 | |
135 | if (Result.Val != 0 && ValueLive) |
136 | PP.markMacroAsUsed(Macro.getMacroInfo()); |
137 | |
138 | |
139 | Token macroToken(PeekTok); |
140 | |
141 | |
142 | if (LParenLoc.isValid()) { |
143 | |
144 | Result.setEnd(PeekTok.getLocation()); |
145 | PP.LexUnexpandedNonComment(PeekTok); |
146 | |
147 | if (PeekTok.isNot(tok::r_paren)) { |
148 | PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after) |
149 | << "'defined'" << tok::r_paren; |
150 | PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren; |
151 | return true; |
152 | } |
153 | |
154 | PP.LexNonComment(PeekTok); |
155 | Result.setEnd(PeekTok.getLocation()); |
156 | } else { |
157 | |
158 | Result.setEnd(PeekTok.getLocation()); |
159 | PP.LexNonComment(PeekTok); |
160 | } |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | if (beginLoc.isMacroID()) { |
181 | bool IsFunctionTypeMacro = |
182 | PP.getSourceManager() |
183 | .getSLocEntry(PP.getSourceManager().getFileID(beginLoc)) |
184 | .getExpansion() |
185 | .isFunctionMacroExpansion(); |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | if (IsFunctionTypeMacro) |
202 | PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro); |
203 | else |
204 | PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro); |
205 | } |
206 | |
207 | |
208 | if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { |
209 | Callbacks->Defined(macroToken, Macro, |
210 | SourceRange(beginLoc, PeekTok.getLocation())); |
211 | } |
212 | |
213 | |
214 | DT.State = DefinedTracker::DefinedMacro; |
215 | DT.TheMacro = II; |
216 | return false; |
217 | } |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, |
228 | bool ValueLive, Preprocessor &PP) { |
229 | DT.State = DefinedTracker::Unknown; |
230 | |
231 | Result.setIdentifier(nullptr); |
232 | |
233 | if (PeekTok.is(tok::code_completion)) { |
234 | if (PP.getCodeCompletionHandler()) |
235 | PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression(); |
236 | PP.setCodeCompletionReached(); |
237 | PP.LexNonComment(PeekTok); |
238 | } |
239 | |
240 | switch (PeekTok.getKind()) { |
241 | default: |
242 | |
243 | |
244 | |
245 | if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) { |
246 | |
247 | if (II->isStr("defined")) |
248 | return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP); |
249 | |
250 | if (!II->isCPlusPlusOperatorKeyword()) { |
251 | |
252 | |
253 | |
254 | if (ValueLive) |
255 | PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II; |
256 | Result.Val = 0; |
257 | Result.Val.setIsUnsigned(false); |
258 | Result.setIdentifier(II); |
259 | Result.setRange(PeekTok.getLocation()); |
260 | DT.IncludedUndefinedIds = true; |
261 | PP.LexNonComment(PeekTok); |
262 | return false; |
263 | } |
264 | } |
265 | PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr); |
266 | return true; |
267 | case tok::eod: |
268 | case tok::r_paren: |
269 | |
270 | PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr); |
271 | return true; |
272 | case tok::numeric_constant: { |
273 | SmallString<64> IntegerBuffer; |
274 | bool NumberInvalid = false; |
275 | StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer, |
276 | &NumberInvalid); |
277 | if (NumberInvalid) |
278 | return true; |
279 | |
280 | NumericLiteralParser Literal(Spelling, PeekTok.getLocation(), PP); |
281 | if (Literal.hadError) |
282 | return true; |
283 | |
284 | if (Literal.isFloatingLiteral() || Literal.isImaginary) { |
285 | PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal); |
286 | return true; |
287 | } |
288 | (0) . __assert_fail ("Literal.isIntegerLiteral() && \"Unknown ppnumber\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPExpressions.cpp", 288, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Literal.isIntegerLiteral() && "Unknown ppnumber"); |
289 | |
290 | |
291 | if (Literal.hasUDSuffix()) |
292 | PP.Diag(PeekTok, diag::err_pp_invalid_udl) << ; |
293 | |
294 | |
295 | if (!PP.getLangOpts().C99 && Literal.isLongLong) { |
296 | if (PP.getLangOpts().CPlusPlus) |
297 | PP.Diag(PeekTok, |
298 | PP.getLangOpts().CPlusPlus11 ? |
299 | diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); |
300 | else |
301 | PP.Diag(PeekTok, diag::ext_c99_longlong); |
302 | } |
303 | |
304 | |
305 | if (Literal.GetIntegerValue(Result.Val)) { |
306 | |
307 | if (ValueLive) |
308 | PP.Diag(PeekTok, diag::err_integer_literal_too_large) |
309 | << 1; |
310 | Result.Val.setIsUnsigned(true); |
311 | } else { |
312 | |
313 | |
314 | Result.Val.setIsUnsigned(Literal.isUnsigned); |
315 | |
316 | |
317 | |
318 | |
319 | |
320 | if (!Literal.isUnsigned && Result.Val.isNegative()) { |
321 | |
322 | |
323 | if (ValueLive && Literal.getRadix() == 10) |
324 | PP.Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed); |
325 | Result.Val.setIsUnsigned(true); |
326 | } |
327 | } |
328 | |
329 | |
330 | Result.setRange(PeekTok.getLocation()); |
331 | PP.LexNonComment(PeekTok); |
332 | return false; |
333 | } |
334 | case tok::char_constant: |
335 | case tok::wide_char_constant: |
336 | case tok::utf8_char_constant: |
337 | case tok::utf16_char_constant: |
338 | case tok::utf32_char_constant: { |
339 | |
340 | if (PeekTok.hasUDSuffix()) |
341 | PP.Diag(PeekTok, diag::err_pp_invalid_udl) << ; |
342 | |
343 | SmallString<32> CharBuffer; |
344 | bool CharInvalid = false; |
345 | StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid); |
346 | if (CharInvalid) |
347 | return true; |
348 | |
349 | CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), |
350 | PeekTok.getLocation(), PP, PeekTok.getKind()); |
351 | if (Literal.hadError()) |
352 | return true; |
353 | |
354 | |
355 | const TargetInfo &TI = PP.getTargetInfo(); |
356 | unsigned NumBits; |
357 | if (Literal.isMultiChar()) |
358 | NumBits = TI.getIntWidth(); |
359 | else if (Literal.isWide()) |
360 | NumBits = TI.getWCharWidth(); |
361 | else if (Literal.isUTF16()) |
362 | NumBits = TI.getChar16Width(); |
363 | else if (Literal.isUTF32()) |
364 | NumBits = TI.getChar32Width(); |
365 | else |
366 | NumBits = TI.getCharWidth(); |
367 | |
368 | |
369 | llvm::APSInt Val(NumBits); |
370 | |
371 | Val = Literal.getValue(); |
372 | |
373 | if (Literal.isWide()) |
374 | Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType())); |
375 | else if (!Literal.isUTF16() && !Literal.isUTF32()) |
376 | Val.setIsUnsigned(!PP.getLangOpts().CharIsSigned); |
377 | |
378 | if (Result.Val.getBitWidth() > Val.getBitWidth()) { |
379 | Result.Val = Val.extend(Result.Val.getBitWidth()); |
380 | } else { |
381 | (0) . __assert_fail ("Result.Val.getBitWidth() == Val.getBitWidth() && \"intmax_t smaller than char/wchar_t?\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPExpressions.cpp", 382, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Result.Val.getBitWidth() == Val.getBitWidth() && |
382 | (0) . __assert_fail ("Result.Val.getBitWidth() == Val.getBitWidth() && \"intmax_t smaller than char/wchar_t?\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPExpressions.cpp", 382, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "intmax_t smaller than char/wchar_t?"); |
383 | Result.Val = Val; |
384 | } |
385 | |
386 | |
387 | Result.setRange(PeekTok.getLocation()); |
388 | PP.LexNonComment(PeekTok); |
389 | return false; |
390 | } |
391 | case tok::l_paren: { |
392 | SourceLocation Start = PeekTok.getLocation(); |
393 | PP.LexNonComment(PeekTok); |
394 | |
395 | |
396 | if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; |
397 | |
398 | |
399 | |
400 | if (PeekTok.is(tok::r_paren)) { |
401 | |
402 | } else { |
403 | |
404 | if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, |
405 | DT.IncludedUndefinedIds, PP)) |
406 | return true; |
407 | |
408 | if (PeekTok.isNot(tok::r_paren)) { |
409 | PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen) |
410 | << Result.getRange(); |
411 | PP.Diag(Start, diag::note_matching) << tok::l_paren; |
412 | return true; |
413 | } |
414 | DT.State = DefinedTracker::Unknown; |
415 | } |
416 | Result.setRange(Start, PeekTok.getLocation()); |
417 | Result.setIdentifier(nullptr); |
418 | PP.LexNonComment(PeekTok); |
419 | return false; |
420 | } |
421 | case tok::plus: { |
422 | SourceLocation Start = PeekTok.getLocation(); |
423 | |
424 | PP.LexNonComment(PeekTok); |
425 | if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; |
426 | Result.setBegin(Start); |
427 | Result.setIdentifier(nullptr); |
428 | return false; |
429 | } |
430 | case tok::minus: { |
431 | SourceLocation Loc = PeekTok.getLocation(); |
432 | PP.LexNonComment(PeekTok); |
433 | if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; |
434 | Result.setBegin(Loc); |
435 | Result.setIdentifier(nullptr); |
436 | |
437 | |
438 | Result.Val = -Result.Val; |
439 | |
440 | |
441 | bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue(); |
442 | |
443 | |
444 | if (Overflow && ValueLive) |
445 | PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange(); |
446 | |
447 | DT.State = DefinedTracker::Unknown; |
448 | return false; |
449 | } |
450 | |
451 | case tok::tilde: { |
452 | SourceLocation Start = PeekTok.getLocation(); |
453 | PP.LexNonComment(PeekTok); |
454 | if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; |
455 | Result.setBegin(Start); |
456 | Result.setIdentifier(nullptr); |
457 | |
458 | |
459 | Result.Val = ~Result.Val; |
460 | DT.State = DefinedTracker::Unknown; |
461 | return false; |
462 | } |
463 | |
464 | case tok::exclaim: { |
465 | SourceLocation Start = PeekTok.getLocation(); |
466 | PP.LexNonComment(PeekTok); |
467 | if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true; |
468 | Result.setBegin(Start); |
469 | Result.Val = !Result.Val; |
470 | |
471 | Result.Val.setIsUnsigned(false); |
472 | Result.setIdentifier(nullptr); |
473 | |
474 | if (DT.State == DefinedTracker::DefinedMacro) |
475 | DT.State = DefinedTracker::NotDefinedMacro; |
476 | else if (DT.State == DefinedTracker::NotDefinedMacro) |
477 | DT.State = DefinedTracker::DefinedMacro; |
478 | return false; |
479 | } |
480 | case tok::kw_true: |
481 | case tok::kw_false: |
482 | Result.Val = PeekTok.getKind() == tok::kw_true; |
483 | Result.Val.setIsUnsigned(false); |
484 | Result.setIdentifier(PeekTok.getIdentifierInfo()); |
485 | Result.setRange(PeekTok.getLocation()); |
486 | PP.LexNonComment(PeekTok); |
487 | return false; |
488 | |
489 | |
490 | } |
491 | } |
492 | |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | static unsigned getPrecedence(tok::TokenKind Kind) { |
499 | switch (Kind) { |
500 | default: return ~0U; |
501 | case tok::percent: |
502 | case tok::slash: |
503 | case tok::star: return 14; |
504 | case tok::plus: |
505 | case tok::minus: return 13; |
506 | case tok::lessless: |
507 | case tok::greatergreater: return 12; |
508 | case tok::lessequal: |
509 | case tok::less: |
510 | case tok::greaterequal: |
511 | case tok::greater: return 11; |
512 | case tok::exclaimequal: |
513 | case tok::equalequal: return 10; |
514 | case tok::amp: return 9; |
515 | case tok::caret: return 8; |
516 | case tok::pipe: return 7; |
517 | case tok::ampamp: return 6; |
518 | case tok::pipepipe: return 5; |
519 | case tok::question: return 4; |
520 | case tok::comma: return 3; |
521 | case tok::colon: return 2; |
522 | case tok::r_paren: return 0; |
523 | case tok::eod: return 0; |
524 | } |
525 | } |
526 | |
527 | static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS, |
528 | Token &Tok) { |
529 | if (Tok.is(tok::l_paren) && LHS.getIdentifier()) |
530 | PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen) |
531 | << LHS.getIdentifier(); |
532 | else |
533 | PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop) |
534 | << LHS.getRange(); |
535 | } |
536 | |
537 | |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, |
544 | Token &PeekTok, bool ValueLive, |
545 | bool &IncludedUndefinedIds, |
546 | Preprocessor &PP) { |
547 | unsigned PeekPrec = getPrecedence(PeekTok.getKind()); |
548 | |
549 | if (PeekPrec == ~0U) { |
550 | diagnoseUnexpectedOperator(PP, LHS, PeekTok); |
551 | return true; |
552 | } |
553 | |
554 | while (true) { |
555 | |
556 | |
557 | if (PeekPrec < MinPrec) |
558 | return false; |
559 | |
560 | tok::TokenKind Operator = PeekTok.getKind(); |
561 | |
562 | |
563 | |
564 | |
565 | |
566 | |
567 | bool RHSIsLive; |
568 | if (Operator == tok::ampamp && LHS.Val == 0) |
569 | RHSIsLive = false; |
570 | else if (Operator == tok::pipepipe && LHS.Val != 0) |
571 | RHSIsLive = false; |
572 | else if (Operator == tok::question && LHS.Val == 0) |
573 | RHSIsLive = false; |
574 | else |
575 | RHSIsLive = ValueLive; |
576 | |
577 | |
578 | SourceLocation OpLoc = PeekTok.getLocation(); |
579 | PP.LexNonComment(PeekTok); |
580 | |
581 | PPValue RHS(LHS.getBitWidth()); |
582 | |
583 | DefinedTracker DT; |
584 | if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true; |
585 | IncludedUndefinedIds = DT.IncludedUndefinedIds; |
586 | |
587 | |
588 | |
589 | unsigned ThisPrec = PeekPrec; |
590 | PeekPrec = getPrecedence(PeekTok.getKind()); |
591 | |
592 | |
593 | if (PeekPrec == ~0U) { |
594 | diagnoseUnexpectedOperator(PP, RHS, PeekTok); |
595 | return true; |
596 | } |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | unsigned RHSPrec; |
609 | if (Operator == tok::question) |
610 | |
611 | RHSPrec = getPrecedence(tok::comma); |
612 | else |
613 | RHSPrec = ThisPrec+1; |
614 | |
615 | if (PeekPrec >= RHSPrec) { |
616 | if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive, |
617 | IncludedUndefinedIds, PP)) |
618 | return true; |
619 | PeekPrec = getPrecedence(PeekTok.getKind()); |
620 | } |
621 | (0) . __assert_fail ("PeekPrec <= ThisPrec && \"Recursion didn't work!\"", "/home/seafit/code_projects/clang_source/clang/lib/Lex/PPExpressions.cpp", 621, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PeekPrec <= ThisPrec && "Recursion didn't work!"); |
622 | |
623 | |
624 | |
625 | llvm::APSInt Res(LHS.getBitWidth()); |
626 | switch (Operator) { |
627 | case tok::question: |
628 | case tok::lessless: |
629 | case tok::greatergreater: |
630 | case tok::comma: |
631 | case tok::pipepipe: |
632 | case tok::ampamp: |
633 | break; |
634 | default: |
635 | Res.setIsUnsigned(LHS.isUnsigned()|RHS.isUnsigned()); |
636 | |
637 | |
638 | if (ValueLive && Res.isUnsigned()) { |
639 | if (!LHS.isUnsigned() && LHS.Val.isNegative()) |
640 | PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0 |
641 | << LHS.Val.toString(10, true) + " to " + |
642 | LHS.Val.toString(10, false) |
643 | << LHS.getRange() << RHS.getRange(); |
644 | if (!RHS.isUnsigned() && RHS.Val.isNegative()) |
645 | PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1 |
646 | << RHS.Val.toString(10, true) + " to " + |
647 | RHS.Val.toString(10, false) |
648 | << LHS.getRange() << RHS.getRange(); |
649 | } |
650 | LHS.Val.setIsUnsigned(Res.isUnsigned()); |
651 | RHS.Val.setIsUnsigned(Res.isUnsigned()); |
652 | } |
653 | |
654 | bool Overflow = false; |
655 | switch (Operator) { |
656 | default: llvm_unreachable("Unknown operator token!"); |
657 | case tok::percent: |
658 | if (RHS.Val != 0) |
659 | Res = LHS.Val % RHS.Val; |
660 | else if (ValueLive) { |
661 | PP.Diag(OpLoc, diag::err_pp_remainder_by_zero) |
662 | << LHS.getRange() << RHS.getRange(); |
663 | return true; |
664 | } |
665 | break; |
666 | case tok::slash: |
667 | if (RHS.Val != 0) { |
668 | if (LHS.Val.isSigned()) |
669 | Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false); |
670 | else |
671 | Res = LHS.Val / RHS.Val; |
672 | } else if (ValueLive) { |
673 | PP.Diag(OpLoc, diag::err_pp_division_by_zero) |
674 | << LHS.getRange() << RHS.getRange(); |
675 | return true; |
676 | } |
677 | break; |
678 | |
679 | case tok::star: |
680 | if (Res.isSigned()) |
681 | Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false); |
682 | else |
683 | Res = LHS.Val * RHS.Val; |
684 | break; |
685 | case tok::lessless: { |
686 | |
687 | if (LHS.isUnsigned()) |
688 | Res = LHS.Val.ushl_ov(RHS.Val, Overflow); |
689 | else |
690 | Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow), false); |
691 | break; |
692 | } |
693 | case tok::greatergreater: { |
694 | |
695 | unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue()); |
696 | if (ShAmt >= LHS.getBitWidth()) { |
697 | Overflow = true; |
698 | ShAmt = LHS.getBitWidth()-1; |
699 | } |
700 | Res = LHS.Val >> ShAmt; |
701 | break; |
702 | } |
703 | case tok::plus: |
704 | if (LHS.isUnsigned()) |
705 | Res = LHS.Val + RHS.Val; |
706 | else |
707 | Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false); |
708 | break; |
709 | case tok::minus: |
710 | if (LHS.isUnsigned()) |
711 | Res = LHS.Val - RHS.Val; |
712 | else |
713 | Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false); |
714 | break; |
715 | case tok::lessequal: |
716 | Res = LHS.Val <= RHS.Val; |
717 | Res.setIsUnsigned(false); |
718 | break; |
719 | case tok::less: |
720 | Res = LHS.Val < RHS.Val; |
721 | Res.setIsUnsigned(false); |
722 | break; |
723 | case tok::greaterequal: |
724 | Res = LHS.Val >= RHS.Val; |
725 | Res.setIsUnsigned(false); |
726 | break; |
727 | case tok::greater: |
728 | Res = LHS.Val > RHS.Val; |
729 | Res.setIsUnsigned(false); |
730 | break; |
731 | case tok::exclaimequal: |
732 | Res = LHS.Val != RHS.Val; |
733 | Res.setIsUnsigned(false); |
734 | break; |
735 | case tok::equalequal: |
736 | Res = LHS.Val == RHS.Val; |
737 | Res.setIsUnsigned(false); |
738 | break; |
739 | case tok::amp: |
740 | Res = LHS.Val & RHS.Val; |
741 | break; |
742 | case tok::caret: |
743 | Res = LHS.Val ^ RHS.Val; |
744 | break; |
745 | case tok::pipe: |
746 | Res = LHS.Val | RHS.Val; |
747 | break; |
748 | case tok::ampamp: |
749 | Res = (LHS.Val != 0 && RHS.Val != 0); |
750 | Res.setIsUnsigned(false); |
751 | break; |
752 | case tok::pipepipe: |
753 | Res = (LHS.Val != 0 || RHS.Val != 0); |
754 | Res.setIsUnsigned(false); |
755 | break; |
756 | case tok::comma: |
757 | |
758 | |
759 | if (!PP.getLangOpts().C99 || ValueLive) |
760 | PP.Diag(OpLoc, diag::ext_pp_comma_expr) |
761 | << LHS.getRange() << RHS.getRange(); |
762 | Res = RHS.Val; |
763 | break; |
764 | case tok::question: { |
765 | |
766 | if (PeekTok.isNot(tok::colon)) { |
767 | PP.Diag(PeekTok.getLocation(), diag::err_expected) |
768 | << tok::colon << LHS.getRange() << RHS.getRange(); |
769 | PP.Diag(OpLoc, diag::note_matching) << tok::question; |
770 | return true; |
771 | } |
772 | |
773 | PP.LexNonComment(PeekTok); |
774 | |
775 | |
776 | bool AfterColonLive = ValueLive && LHS.Val == 0; |
777 | PPValue AfterColonVal(LHS.getBitWidth()); |
778 | DefinedTracker DT; |
779 | if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP)) |
780 | return true; |
781 | |
782 | |
783 | |
784 | if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec, |
785 | PeekTok, AfterColonLive, |
786 | IncludedUndefinedIds, PP)) |
787 | return true; |
788 | |
789 | |
790 | Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val; |
791 | RHS.setEnd(AfterColonVal.getRange().getEnd()); |
792 | |
793 | |
794 | |
795 | Res.setIsUnsigned(RHS.isUnsigned() | AfterColonVal.isUnsigned()); |
796 | |
797 | |
798 | PeekPrec = getPrecedence(PeekTok.getKind()); |
799 | break; |
800 | } |
801 | case tok::colon: |
802 | |
803 | PP.Diag(OpLoc, diag::err_pp_colon_without_question) |
804 | << LHS.getRange() << RHS.getRange(); |
805 | return true; |
806 | } |
807 | |
808 | |
809 | if (Overflow && ValueLive) |
810 | PP.Diag(OpLoc, diag::warn_pp_expr_overflow) |
811 | << LHS.getRange() << RHS.getRange(); |
812 | |
813 | |
814 | LHS.Val = Res; |
815 | LHS.setEnd(RHS.getRange().getEnd()); |
816 | RHS.setIdentifier(nullptr); |
817 | } |
818 | } |
819 | |
820 | |
821 | |
822 | |
823 | Preprocessor::DirectiveEvalResult |
824 | Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro) { |
825 | SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true); |
826 | |
827 | |
828 | |
829 | |
830 | |
831 | |
832 | bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion; |
833 | DisableMacroExpansion = false; |
834 | |
835 | |
836 | Token Tok; |
837 | LexNonComment(Tok); |
838 | |
839 | |
840 | unsigned BitWidth = getTargetInfo().getIntMaxTWidth(); |
841 | |
842 | PPValue ResVal(BitWidth); |
843 | DefinedTracker DT; |
844 | SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation()); |
845 | if (EvaluateValue(ResVal, Tok, DT, true, *this)) { |
846 | |
847 | SourceRange ConditionRange = ExprStartLoc; |
848 | if (Tok.isNot(tok::eod)) |
849 | ConditionRange = DiscardUntilEndOfDirective(); |
850 | |
851 | |
852 | DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; |
853 | |
854 | |
855 | |
856 | |
857 | return {false, |
858 | DT.IncludedUndefinedIds, |
859 | {ExprStartLoc, ConditionRange.getEnd()}}; |
860 | } |
861 | |
862 | |
863 | |
864 | |
865 | if (Tok.is(tok::eod)) { |
866 | |
867 | |
868 | if (DT.State == DefinedTracker::NotDefinedMacro) |
869 | IfNDefMacro = DT.TheMacro; |
870 | |
871 | |
872 | DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; |
873 | return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()}; |
874 | } |
875 | |
876 | |
877 | |
878 | if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question), |
879 | Tok, true, DT.IncludedUndefinedIds, *this)) { |
880 | |
881 | if (Tok.isNot(tok::eod)) |
882 | DiscardUntilEndOfDirective(); |
883 | |
884 | |
885 | DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; |
886 | return {false, DT.IncludedUndefinedIds, ResVal.getRange()}; |
887 | } |
888 | |
889 | |
890 | |
891 | if (Tok.isNot(tok::eod)) { |
892 | Diag(Tok, diag::err_pp_expected_eol); |
893 | DiscardUntilEndOfDirective(); |
894 | } |
895 | |
896 | |
897 | DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective; |
898 | return {ResVal.Val != 0, DT.IncludedUndefinedIds, ResVal.getRange()}; |
899 | } |
900 | |