10b57cec5SDimitry Andric //===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the Preprocessor::EvaluateDirectiveExpression method,
100b57cec5SDimitry Andric // which parses and evaluates integer constant expressions for #if directives.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric // FIXME: implement testing for #assert's.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
190b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
200b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
210b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
220b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
230b57cec5SDimitry Andric #include "clang/Lex/CodeCompletionHandler.h"
240b57cec5SDimitry Andric #include "clang/Lex/LexDiagnostic.h"
250b57cec5SDimitry Andric #include "clang/Lex/LiteralSupport.h"
260b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h"
270b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h"
285ffd83dbSDimitry Andric #include "clang/Lex/Preprocessor.h"
290b57cec5SDimitry Andric #include "clang/Lex/Token.h"
300b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
315ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
320b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
335ffd83dbSDimitry Andric #include "llvm/ADT/StringExtras.h"
340b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
370b57cec5SDimitry Andric #include <cassert>
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric using namespace clang;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric namespace {
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric /// PPValue - Represents the value of a subexpression of a preprocessor
440b57cec5SDimitry Andric /// conditional and the source range covered by it.
450b57cec5SDimitry Andric class PPValue {
460b57cec5SDimitry Andric SourceRange Range;
4706c3fb27SDimitry Andric IdentifierInfo *II = nullptr;
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric public:
500b57cec5SDimitry Andric llvm::APSInt Val;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric // Default ctor - Construct an 'invalid' PPValue.
PPValue(unsigned BitWidth)530b57cec5SDimitry Andric PPValue(unsigned BitWidth) : Val(BitWidth) {}
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric // If this value was produced by directly evaluating an identifier, produce
560b57cec5SDimitry Andric // that identifier.
getIdentifier() const570b57cec5SDimitry Andric IdentifierInfo *getIdentifier() const { return II; }
setIdentifier(IdentifierInfo * II)580b57cec5SDimitry Andric void setIdentifier(IdentifierInfo *II) { this->II = II; }
590b57cec5SDimitry Andric
getBitWidth() const600b57cec5SDimitry Andric unsigned getBitWidth() const { return Val.getBitWidth(); }
isUnsigned() const610b57cec5SDimitry Andric bool isUnsigned() const { return Val.isUnsigned(); }
620b57cec5SDimitry Andric
getRange() const630b57cec5SDimitry Andric SourceRange getRange() const { return Range; }
640b57cec5SDimitry Andric
setRange(SourceLocation L)650b57cec5SDimitry Andric void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }
setRange(SourceLocation B,SourceLocation E)660b57cec5SDimitry Andric void setRange(SourceLocation B, SourceLocation E) {
670b57cec5SDimitry Andric Range.setBegin(B); Range.setEnd(E);
680b57cec5SDimitry Andric }
setBegin(SourceLocation L)690b57cec5SDimitry Andric void setBegin(SourceLocation L) { Range.setBegin(L); }
setEnd(SourceLocation L)700b57cec5SDimitry Andric void setEnd(SourceLocation L) { Range.setEnd(L); }
710b57cec5SDimitry Andric };
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric } // end anonymous namespace
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
760b57cec5SDimitry Andric Token &PeekTok, bool ValueLive,
770b57cec5SDimitry Andric bool &IncludedUndefinedIds,
780b57cec5SDimitry Andric Preprocessor &PP);
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric /// DefinedTracker - This struct is used while parsing expressions to keep track
810b57cec5SDimitry Andric /// of whether !defined(X) has been seen.
820b57cec5SDimitry Andric ///
830b57cec5SDimitry Andric /// With this simple scheme, we handle the basic forms:
840b57cec5SDimitry Andric /// !defined(X) and !defined X
850b57cec5SDimitry Andric /// but we also trivially handle (silly) stuff like:
860b57cec5SDimitry Andric /// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).
870b57cec5SDimitry Andric struct DefinedTracker {
880b57cec5SDimitry Andric /// Each time a Value is evaluated, it returns information about whether the
890b57cec5SDimitry Andric /// parsed value is of the form defined(X), !defined(X) or is something else.
900b57cec5SDimitry Andric enum TrackerState {
910b57cec5SDimitry Andric DefinedMacro, // defined(X)
920b57cec5SDimitry Andric NotDefinedMacro, // !defined(X)
930b57cec5SDimitry Andric Unknown // Something else.
940b57cec5SDimitry Andric } State;
950b57cec5SDimitry Andric /// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this
960b57cec5SDimitry Andric /// indicates the macro that was checked.
970b57cec5SDimitry Andric IdentifierInfo *TheMacro;
980b57cec5SDimitry Andric bool IncludedUndefinedIds = false;
990b57cec5SDimitry Andric };
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andric /// EvaluateDefined - Process a 'defined(sym)' expression.
EvaluateDefined(PPValue & Result,Token & PeekTok,DefinedTracker & DT,bool ValueLive,Preprocessor & PP)1020b57cec5SDimitry Andric static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
1030b57cec5SDimitry Andric bool ValueLive, Preprocessor &PP) {
1040b57cec5SDimitry Andric SourceLocation beginLoc(PeekTok.getLocation());
1050b57cec5SDimitry Andric Result.setBegin(beginLoc);
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric // Get the next token, don't expand it.
1080b57cec5SDimitry Andric PP.LexUnexpandedNonComment(PeekTok);
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric // Two options, it can either be a pp-identifier or a (.
1110b57cec5SDimitry Andric SourceLocation LParenLoc;
1120b57cec5SDimitry Andric if (PeekTok.is(tok::l_paren)) {
1130b57cec5SDimitry Andric // Found a paren, remember we saw it and skip it.
1140b57cec5SDimitry Andric LParenLoc = PeekTok.getLocation();
1150b57cec5SDimitry Andric PP.LexUnexpandedNonComment(PeekTok);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric if (PeekTok.is(tok::code_completion)) {
1190b57cec5SDimitry Andric if (PP.getCodeCompletionHandler())
1200b57cec5SDimitry Andric PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);
1210b57cec5SDimitry Andric PP.setCodeCompletionReached();
1220b57cec5SDimitry Andric PP.LexUnexpandedNonComment(PeekTok);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric // If we don't have a pp-identifier now, this is an error.
1260b57cec5SDimitry Andric if (PP.CheckMacroName(PeekTok, MU_Other))
1270b57cec5SDimitry Andric return true;
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric // Otherwise, we got an identifier, is it defined to something?
1300b57cec5SDimitry Andric IdentifierInfo *II = PeekTok.getIdentifierInfo();
1310b57cec5SDimitry Andric MacroDefinition Macro = PP.getMacroDefinition(II);
1320b57cec5SDimitry Andric Result.Val = !!Macro;
1330b57cec5SDimitry Andric Result.Val.setIsUnsigned(false); // Result is signed intmax_t.
1340b57cec5SDimitry Andric DT.IncludedUndefinedIds = !Macro;
1350b57cec5SDimitry Andric
136b3edf446SDimitry Andric PP.emitMacroExpansionWarnings(
137b3edf446SDimitry Andric PeekTok,
138b3edf446SDimitry Andric (II->getName() == "INFINITY" || II->getName() == "NAN") ? true : false);
139349cc55cSDimitry Andric
1400b57cec5SDimitry Andric // If there is a macro, mark it used.
1410b57cec5SDimitry Andric if (Result.Val != 0 && ValueLive)
1420b57cec5SDimitry Andric PP.markMacroAsUsed(Macro.getMacroInfo());
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // Save macro token for callback.
1450b57cec5SDimitry Andric Token macroToken(PeekTok);
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric // If we are in parens, ensure we have a trailing ).
1480b57cec5SDimitry Andric if (LParenLoc.isValid()) {
1490b57cec5SDimitry Andric // Consume identifier.
1500b57cec5SDimitry Andric Result.setEnd(PeekTok.getLocation());
1510b57cec5SDimitry Andric PP.LexUnexpandedNonComment(PeekTok);
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric if (PeekTok.isNot(tok::r_paren)) {
1540b57cec5SDimitry Andric PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after)
1550b57cec5SDimitry Andric << "'defined'" << tok::r_paren;
1560b57cec5SDimitry Andric PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;
1570b57cec5SDimitry Andric return true;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric // Consume the ).
1600b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
1610b57cec5SDimitry Andric Result.setEnd(PeekTok.getLocation());
1620b57cec5SDimitry Andric } else {
1630b57cec5SDimitry Andric // Consume identifier.
1640b57cec5SDimitry Andric Result.setEnd(PeekTok.getLocation());
1650b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric // [cpp.cond]p4:
1690b57cec5SDimitry Andric // Prior to evaluation, macro invocations in the list of preprocessing
1700b57cec5SDimitry Andric // tokens that will become the controlling constant expression are replaced
1710b57cec5SDimitry Andric // (except for those macro names modified by the 'defined' unary operator),
1720b57cec5SDimitry Andric // just as in normal text. If the token 'defined' is generated as a result
1730b57cec5SDimitry Andric // of this replacement process or use of the 'defined' unary operator does
1740b57cec5SDimitry Andric // not match one of the two specified forms prior to macro replacement, the
1750b57cec5SDimitry Andric // behavior is undefined.
1760b57cec5SDimitry Andric // This isn't an idle threat, consider this program:
1770b57cec5SDimitry Andric // #define FOO
1780b57cec5SDimitry Andric // #define BAR defined(FOO)
1790b57cec5SDimitry Andric // #if BAR
1800b57cec5SDimitry Andric // ...
1810b57cec5SDimitry Andric // #else
1820b57cec5SDimitry Andric // ...
1830b57cec5SDimitry Andric // #endif
1840b57cec5SDimitry Andric // clang and gcc will pick the #if branch while Visual Studio will take the
1850b57cec5SDimitry Andric // #else branch. Emit a warning about this undefined behavior.
1860b57cec5SDimitry Andric if (beginLoc.isMacroID()) {
1870b57cec5SDimitry Andric bool IsFunctionTypeMacro =
1880b57cec5SDimitry Andric PP.getSourceManager()
1890b57cec5SDimitry Andric .getSLocEntry(PP.getSourceManager().getFileID(beginLoc))
1900b57cec5SDimitry Andric .getExpansion()
1910b57cec5SDimitry Andric .isFunctionMacroExpansion();
1920b57cec5SDimitry Andric // For object-type macros, it's easy to replace
1930b57cec5SDimitry Andric // #define FOO defined(BAR)
1940b57cec5SDimitry Andric // with
1950b57cec5SDimitry Andric // #if defined(BAR)
1960b57cec5SDimitry Andric // #define FOO 1
1970b57cec5SDimitry Andric // #else
1980b57cec5SDimitry Andric // #define FOO 0
1990b57cec5SDimitry Andric // #endif
2000b57cec5SDimitry Andric // and doing so makes sense since compilers handle this differently in
2010b57cec5SDimitry Andric // practice (see example further up). But for function-type macros,
2020b57cec5SDimitry Andric // there is no good way to write
2030b57cec5SDimitry Andric // # define FOO(x) (defined(M_ ## x) && M_ ## x)
2040b57cec5SDimitry Andric // in a different way, and compilers seem to agree on how to behave here.
2050b57cec5SDimitry Andric // So warn by default on object-type macros, but only warn in -pedantic
2060b57cec5SDimitry Andric // mode on function-type macros.
2070b57cec5SDimitry Andric if (IsFunctionTypeMacro)
2080b57cec5SDimitry Andric PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro);
2090b57cec5SDimitry Andric else
2100b57cec5SDimitry Andric PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro);
2110b57cec5SDimitry Andric }
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric // Invoke the 'defined' callback.
2140b57cec5SDimitry Andric if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
2150b57cec5SDimitry Andric Callbacks->Defined(macroToken, Macro,
2160b57cec5SDimitry Andric SourceRange(beginLoc, PeekTok.getLocation()));
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric // Success, remember that we saw defined(X).
2200b57cec5SDimitry Andric DT.State = DefinedTracker::DefinedMacro;
2210b57cec5SDimitry Andric DT.TheMacro = II;
2220b57cec5SDimitry Andric return false;
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric /// EvaluateValue - Evaluate the token PeekTok (and any others needed) and
2260b57cec5SDimitry Andric /// return the computed value in Result. Return true if there was an error
2270b57cec5SDimitry Andric /// parsing. This function also returns information about the form of the
2280b57cec5SDimitry Andric /// expression in DT. See above for information on what DT means.
2290b57cec5SDimitry Andric ///
2300b57cec5SDimitry Andric /// If ValueLive is false, then this value is being evaluated in a context where
2310b57cec5SDimitry Andric /// the result is not used. As such, avoid diagnostics that relate to
2320b57cec5SDimitry Andric /// evaluation.
EvaluateValue(PPValue & Result,Token & PeekTok,DefinedTracker & DT,bool ValueLive,Preprocessor & PP)2330b57cec5SDimitry Andric static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
2340b57cec5SDimitry Andric bool ValueLive, Preprocessor &PP) {
2350b57cec5SDimitry Andric DT.State = DefinedTracker::Unknown;
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric Result.setIdentifier(nullptr);
2380b57cec5SDimitry Andric
2390b57cec5SDimitry Andric if (PeekTok.is(tok::code_completion)) {
2400b57cec5SDimitry Andric if (PP.getCodeCompletionHandler())
2410b57cec5SDimitry Andric PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
2420b57cec5SDimitry Andric PP.setCodeCompletionReached();
2430b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric switch (PeekTok.getKind()) {
2470b57cec5SDimitry Andric default:
2480b57cec5SDimitry Andric // If this token's spelling is a pp-identifier, check to see if it is
2490b57cec5SDimitry Andric // 'defined' or if it is a macro. Note that we check here because many
2500b57cec5SDimitry Andric // keywords are pp-identifiers, so we can't check the kind.
2510b57cec5SDimitry Andric if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {
2520b57cec5SDimitry Andric // Handle "defined X" and "defined(X)".
2530b57cec5SDimitry Andric if (II->isStr("defined"))
2540b57cec5SDimitry Andric return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP);
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric if (!II->isCPlusPlusOperatorKeyword()) {
2570b57cec5SDimitry Andric // If this identifier isn't 'defined' or one of the special
2580b57cec5SDimitry Andric // preprocessor keywords and it wasn't macro expanded, it turns
2590b57cec5SDimitry Andric // into a simple 0
2605ffd83dbSDimitry Andric if (ValueLive) {
2610b57cec5SDimitry Andric PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;
2625ffd83dbSDimitry Andric
2635ffd83dbSDimitry Andric const DiagnosticsEngine &DiagEngine = PP.getDiagnostics();
2645ffd83dbSDimitry Andric // If 'Wundef' is enabled, do not emit 'undef-prefix' diagnostics.
2655ffd83dbSDimitry Andric if (DiagEngine.isIgnored(diag::warn_pp_undef_identifier,
2665ffd83dbSDimitry Andric PeekTok.getLocation())) {
2675ffd83dbSDimitry Andric const std::vector<std::string> UndefPrefixes =
2685ffd83dbSDimitry Andric DiagEngine.getDiagnosticOptions().UndefPrefixes;
2695ffd83dbSDimitry Andric const StringRef IdentifierName = II->getName();
2705ffd83dbSDimitry Andric if (llvm::any_of(UndefPrefixes,
2715ffd83dbSDimitry Andric [&IdentifierName](const std::string &Prefix) {
2725f757f3fSDimitry Andric return IdentifierName.starts_with(Prefix);
2735ffd83dbSDimitry Andric }))
2745ffd83dbSDimitry Andric PP.Diag(PeekTok, diag::warn_pp_undef_prefix)
2755ffd83dbSDimitry Andric << AddFlagValue{llvm::join(UndefPrefixes, ",")} << II;
2765ffd83dbSDimitry Andric }
2775ffd83dbSDimitry Andric }
2780b57cec5SDimitry Andric Result.Val = 0;
2790b57cec5SDimitry Andric Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
2800b57cec5SDimitry Andric Result.setIdentifier(II);
2810b57cec5SDimitry Andric Result.setRange(PeekTok.getLocation());
2820b57cec5SDimitry Andric DT.IncludedUndefinedIds = true;
2830b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
2840b57cec5SDimitry Andric return false;
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
2880b57cec5SDimitry Andric return true;
2890b57cec5SDimitry Andric case tok::eod:
2900b57cec5SDimitry Andric case tok::r_paren:
2910b57cec5SDimitry Andric // If there is no expression, report and exit.
2920b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);
2930b57cec5SDimitry Andric return true;
2940b57cec5SDimitry Andric case tok::numeric_constant: {
2950b57cec5SDimitry Andric SmallString<64> IntegerBuffer;
2960b57cec5SDimitry Andric bool NumberInvalid = false;
2970b57cec5SDimitry Andric StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,
2980b57cec5SDimitry Andric &NumberInvalid);
2990b57cec5SDimitry Andric if (NumberInvalid)
3000b57cec5SDimitry Andric return true; // a diagnostic was already reported
3010b57cec5SDimitry Andric
3025ffd83dbSDimitry Andric NumericLiteralParser Literal(Spelling, PeekTok.getLocation(),
3035ffd83dbSDimitry Andric PP.getSourceManager(), PP.getLangOpts(),
3045ffd83dbSDimitry Andric PP.getTargetInfo(), PP.getDiagnostics());
3050b57cec5SDimitry Andric if (Literal.hadError)
3060b57cec5SDimitry Andric return true; // a diagnostic was already reported.
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric if (Literal.isFloatingLiteral() || Literal.isImaginary) {
3090b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);
3100b57cec5SDimitry Andric return true;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric assert(Literal.isIntegerLiteral() && "Unknown ppnumber");
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andric // Complain about, and drop, any ud-suffix.
3150b57cec5SDimitry Andric if (Literal.hasUDSuffix())
3160b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*integer*/1;
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric // 'long long' is a C99 or C++11 feature.
3190b57cec5SDimitry Andric if (!PP.getLangOpts().C99 && Literal.isLongLong) {
3200b57cec5SDimitry Andric if (PP.getLangOpts().CPlusPlus)
3210b57cec5SDimitry Andric PP.Diag(PeekTok,
3220b57cec5SDimitry Andric PP.getLangOpts().CPlusPlus11 ?
3230b57cec5SDimitry Andric diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
3240b57cec5SDimitry Andric else
3250b57cec5SDimitry Andric PP.Diag(PeekTok, diag::ext_c99_longlong);
3260b57cec5SDimitry Andric }
3270b57cec5SDimitry Andric
32806c3fb27SDimitry Andric // 'z/uz' literals are a C++23 feature.
329fe6060f1SDimitry Andric if (Literal.isSizeT)
330fe6060f1SDimitry Andric PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus
33106c3fb27SDimitry Andric ? PP.getLangOpts().CPlusPlus23
332fe6060f1SDimitry Andric ? diag::warn_cxx20_compat_size_t_suffix
33306c3fb27SDimitry Andric : diag::ext_cxx23_size_t_suffix
33406c3fb27SDimitry Andric : diag::err_cxx23_size_t_suffix);
335fe6060f1SDimitry Andric
336*0fca6ea1SDimitry Andric // 'wb/uwb' literals are a C23 feature.
337*0fca6ea1SDimitry Andric // '__wb/__uwb' are a C++ extension.
33881ad6265SDimitry Andric if (Literal.isBitInt)
339*0fca6ea1SDimitry Andric PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
340*0fca6ea1SDimitry Andric : PP.getLangOpts().C23
3415f757f3fSDimitry Andric ? diag::warn_c23_compat_bitint_suffix
3425f757f3fSDimitry Andric : diag::ext_c23_bitint_suffix);
34381ad6265SDimitry Andric
3440b57cec5SDimitry Andric // Parse the integer literal into Result.
3450b57cec5SDimitry Andric if (Literal.GetIntegerValue(Result.Val)) {
3460b57cec5SDimitry Andric // Overflow parsing integer literal.
3470b57cec5SDimitry Andric if (ValueLive)
3480b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_integer_literal_too_large)
3490b57cec5SDimitry Andric << /* Unsigned */ 1;
3500b57cec5SDimitry Andric Result.Val.setIsUnsigned(true);
3510b57cec5SDimitry Andric } else {
3520b57cec5SDimitry Andric // Set the signedness of the result to match whether there was a U suffix
3530b57cec5SDimitry Andric // or not.
3540b57cec5SDimitry Andric Result.Val.setIsUnsigned(Literal.isUnsigned);
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric // Detect overflow based on whether the value is signed. If signed
3570b57cec5SDimitry Andric // and if the value is too large, emit a warning "integer constant is so
3580b57cec5SDimitry Andric // large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
3590b57cec5SDimitry Andric // is 64-bits.
3600b57cec5SDimitry Andric if (!Literal.isUnsigned && Result.Val.isNegative()) {
3610b57cec5SDimitry Andric // Octal, hexadecimal, and binary literals are implicitly unsigned if
3620b57cec5SDimitry Andric // the value does not fit into a signed integer type.
3630b57cec5SDimitry Andric if (ValueLive && Literal.getRadix() == 10)
3640b57cec5SDimitry Andric PP.Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);
3650b57cec5SDimitry Andric Result.Val.setIsUnsigned(true);
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric // Consume the token.
3700b57cec5SDimitry Andric Result.setRange(PeekTok.getLocation());
3710b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
3720b57cec5SDimitry Andric return false;
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric case tok::char_constant: // 'x'
3750b57cec5SDimitry Andric case tok::wide_char_constant: // L'x'
3760b57cec5SDimitry Andric case tok::utf8_char_constant: // u8'x'
3770b57cec5SDimitry Andric case tok::utf16_char_constant: // u'x'
3780b57cec5SDimitry Andric case tok::utf32_char_constant: { // U'x'
3790b57cec5SDimitry Andric // Complain about, and drop, any ud-suffix.
3800b57cec5SDimitry Andric if (PeekTok.hasUDSuffix())
3810b57cec5SDimitry Andric PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*character*/0;
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric SmallString<32> CharBuffer;
3840b57cec5SDimitry Andric bool CharInvalid = false;
3850b57cec5SDimitry Andric StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
3860b57cec5SDimitry Andric if (CharInvalid)
3870b57cec5SDimitry Andric return true;
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),
3900b57cec5SDimitry Andric PeekTok.getLocation(), PP, PeekTok.getKind());
3910b57cec5SDimitry Andric if (Literal.hadError())
3920b57cec5SDimitry Andric return true; // A diagnostic was already emitted.
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric // Character literals are always int or wchar_t, expand to intmax_t.
3950b57cec5SDimitry Andric const TargetInfo &TI = PP.getTargetInfo();
3960b57cec5SDimitry Andric unsigned NumBits;
3970b57cec5SDimitry Andric if (Literal.isMultiChar())
3980b57cec5SDimitry Andric NumBits = TI.getIntWidth();
3990b57cec5SDimitry Andric else if (Literal.isWide())
4000b57cec5SDimitry Andric NumBits = TI.getWCharWidth();
4010b57cec5SDimitry Andric else if (Literal.isUTF16())
4020b57cec5SDimitry Andric NumBits = TI.getChar16Width();
4030b57cec5SDimitry Andric else if (Literal.isUTF32())
4040b57cec5SDimitry Andric NumBits = TI.getChar32Width();
4050b57cec5SDimitry Andric else // char or char8_t
4060b57cec5SDimitry Andric NumBits = TI.getCharWidth();
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric // Set the width.
4090b57cec5SDimitry Andric llvm::APSInt Val(NumBits);
4100b57cec5SDimitry Andric // Set the value.
4110b57cec5SDimitry Andric Val = Literal.getValue();
4120b57cec5SDimitry Andric // Set the signedness. UTF-16 and UTF-32 are always unsigned
41381ad6265SDimitry Andric // UTF-8 is unsigned if -fchar8_t is specified.
4140b57cec5SDimitry Andric if (Literal.isWide())
4150b57cec5SDimitry Andric Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType()));
41681ad6265SDimitry Andric else if (Literal.isUTF16() || Literal.isUTF32())
41781ad6265SDimitry Andric Val.setIsUnsigned(true);
41881ad6265SDimitry Andric else if (Literal.isUTF8()) {
41981ad6265SDimitry Andric if (PP.getLangOpts().CPlusPlus)
42081ad6265SDimitry Andric Val.setIsUnsigned(
42181ad6265SDimitry Andric PP.getLangOpts().Char8 ? true : !PP.getLangOpts().CharIsSigned);
42281ad6265SDimitry Andric else
42381ad6265SDimitry Andric Val.setIsUnsigned(true);
42481ad6265SDimitry Andric } else
4250b57cec5SDimitry Andric Val.setIsUnsigned(!PP.getLangOpts().CharIsSigned);
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric if (Result.Val.getBitWidth() > Val.getBitWidth()) {
4280b57cec5SDimitry Andric Result.Val = Val.extend(Result.Val.getBitWidth());
4290b57cec5SDimitry Andric } else {
4300b57cec5SDimitry Andric assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
4310b57cec5SDimitry Andric "intmax_t smaller than char/wchar_t?");
4320b57cec5SDimitry Andric Result.Val = Val;
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andric // Consume the token.
4360b57cec5SDimitry Andric Result.setRange(PeekTok.getLocation());
4370b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
4380b57cec5SDimitry Andric return false;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric case tok::l_paren: {
4410b57cec5SDimitry Andric SourceLocation Start = PeekTok.getLocation();
4420b57cec5SDimitry Andric PP.LexNonComment(PeekTok); // Eat the (.
4430b57cec5SDimitry Andric // Parse the value and if there are any binary operators involved, parse
4440b57cec5SDimitry Andric // them.
4450b57cec5SDimitry Andric if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andric // If this is a silly value like (X), which doesn't need parens, check for
4480b57cec5SDimitry Andric // !(defined X).
4490b57cec5SDimitry Andric if (PeekTok.is(tok::r_paren)) {
4500b57cec5SDimitry Andric // Just use DT unmodified as our result.
4510b57cec5SDimitry Andric } else {
4520b57cec5SDimitry Andric // Otherwise, we have something like (x+y), and we consumed '(x'.
4530b57cec5SDimitry Andric if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive,
4540b57cec5SDimitry Andric DT.IncludedUndefinedIds, PP))
4550b57cec5SDimitry Andric return true;
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric if (PeekTok.isNot(tok::r_paren)) {
4580b57cec5SDimitry Andric PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)
4590b57cec5SDimitry Andric << Result.getRange();
4600b57cec5SDimitry Andric PP.Diag(Start, diag::note_matching) << tok::l_paren;
4610b57cec5SDimitry Andric return true;
4620b57cec5SDimitry Andric }
4630b57cec5SDimitry Andric DT.State = DefinedTracker::Unknown;
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric Result.setRange(Start, PeekTok.getLocation());
4660b57cec5SDimitry Andric Result.setIdentifier(nullptr);
4670b57cec5SDimitry Andric PP.LexNonComment(PeekTok); // Eat the ).
4680b57cec5SDimitry Andric return false;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric case tok::plus: {
4710b57cec5SDimitry Andric SourceLocation Start = PeekTok.getLocation();
4720b57cec5SDimitry Andric // Unary plus doesn't modify the value.
4730b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
4740b57cec5SDimitry Andric if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
4750b57cec5SDimitry Andric Result.setBegin(Start);
4760b57cec5SDimitry Andric Result.setIdentifier(nullptr);
4770b57cec5SDimitry Andric return false;
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric case tok::minus: {
4800b57cec5SDimitry Andric SourceLocation Loc = PeekTok.getLocation();
4810b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
4820b57cec5SDimitry Andric if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
4830b57cec5SDimitry Andric Result.setBegin(Loc);
4840b57cec5SDimitry Andric Result.setIdentifier(nullptr);
4850b57cec5SDimitry Andric
4860b57cec5SDimitry Andric // C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
4870b57cec5SDimitry Andric Result.Val = -Result.Val;
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andric // -MININT is the only thing that overflows. Unsigned never overflows.
4900b57cec5SDimitry Andric bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric // If this operator is live and overflowed, report the issue.
4930b57cec5SDimitry Andric if (Overflow && ValueLive)
4940b57cec5SDimitry Andric PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange();
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andric DT.State = DefinedTracker::Unknown;
4970b57cec5SDimitry Andric return false;
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric case tok::tilde: {
5010b57cec5SDimitry Andric SourceLocation Start = PeekTok.getLocation();
5020b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
5030b57cec5SDimitry Andric if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
5040b57cec5SDimitry Andric Result.setBegin(Start);
5050b57cec5SDimitry Andric Result.setIdentifier(nullptr);
5060b57cec5SDimitry Andric
5070b57cec5SDimitry Andric // C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
5080b57cec5SDimitry Andric Result.Val = ~Result.Val;
5090b57cec5SDimitry Andric DT.State = DefinedTracker::Unknown;
5100b57cec5SDimitry Andric return false;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric case tok::exclaim: {
5140b57cec5SDimitry Andric SourceLocation Start = PeekTok.getLocation();
5150b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
5160b57cec5SDimitry Andric if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
5170b57cec5SDimitry Andric Result.setBegin(Start);
5180b57cec5SDimitry Andric Result.Val = !Result.Val;
5190b57cec5SDimitry Andric // C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
5200b57cec5SDimitry Andric Result.Val.setIsUnsigned(false);
5210b57cec5SDimitry Andric Result.setIdentifier(nullptr);
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric if (DT.State == DefinedTracker::DefinedMacro)
5240b57cec5SDimitry Andric DT.State = DefinedTracker::NotDefinedMacro;
5250b57cec5SDimitry Andric else if (DT.State == DefinedTracker::NotDefinedMacro)
5260b57cec5SDimitry Andric DT.State = DefinedTracker::DefinedMacro;
5270b57cec5SDimitry Andric return false;
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric case tok::kw_true:
5300b57cec5SDimitry Andric case tok::kw_false:
5310b57cec5SDimitry Andric Result.Val = PeekTok.getKind() == tok::kw_true;
5320b57cec5SDimitry Andric Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.
5330b57cec5SDimitry Andric Result.setIdentifier(PeekTok.getIdentifierInfo());
5340b57cec5SDimitry Andric Result.setRange(PeekTok.getLocation());
5350b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
5360b57cec5SDimitry Andric return false;
5370b57cec5SDimitry Andric
5380b57cec5SDimitry Andric // FIXME: Handle #assert
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric /// getPrecedence - Return the precedence of the specified binary operator
5430b57cec5SDimitry Andric /// token. This returns:
5440b57cec5SDimitry Andric /// ~0 - Invalid token.
5450b57cec5SDimitry Andric /// 14 -> 3 - various operators.
5460b57cec5SDimitry Andric /// 0 - 'eod' or ')'
getPrecedence(tok::TokenKind Kind)5470b57cec5SDimitry Andric static unsigned getPrecedence(tok::TokenKind Kind) {
5480b57cec5SDimitry Andric switch (Kind) {
5490b57cec5SDimitry Andric default: return ~0U;
5500b57cec5SDimitry Andric case tok::percent:
5510b57cec5SDimitry Andric case tok::slash:
5520b57cec5SDimitry Andric case tok::star: return 14;
5530b57cec5SDimitry Andric case tok::plus:
5540b57cec5SDimitry Andric case tok::minus: return 13;
5550b57cec5SDimitry Andric case tok::lessless:
5560b57cec5SDimitry Andric case tok::greatergreater: return 12;
5570b57cec5SDimitry Andric case tok::lessequal:
5580b57cec5SDimitry Andric case tok::less:
5590b57cec5SDimitry Andric case tok::greaterequal:
5600b57cec5SDimitry Andric case tok::greater: return 11;
5610b57cec5SDimitry Andric case tok::exclaimequal:
5620b57cec5SDimitry Andric case tok::equalequal: return 10;
5630b57cec5SDimitry Andric case tok::amp: return 9;
5640b57cec5SDimitry Andric case tok::caret: return 8;
5650b57cec5SDimitry Andric case tok::pipe: return 7;
5660b57cec5SDimitry Andric case tok::ampamp: return 6;
5670b57cec5SDimitry Andric case tok::pipepipe: return 5;
5680b57cec5SDimitry Andric case tok::question: return 4;
5690b57cec5SDimitry Andric case tok::comma: return 3;
5700b57cec5SDimitry Andric case tok::colon: return 2;
5710b57cec5SDimitry Andric case tok::r_paren: return 0;// Lowest priority, end of expr.
5720b57cec5SDimitry Andric case tok::eod: return 0;// Lowest priority, end of directive.
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
diagnoseUnexpectedOperator(Preprocessor & PP,PPValue & LHS,Token & Tok)5760b57cec5SDimitry Andric static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,
5770b57cec5SDimitry Andric Token &Tok) {
5780b57cec5SDimitry Andric if (Tok.is(tok::l_paren) && LHS.getIdentifier())
5790b57cec5SDimitry Andric PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
5800b57cec5SDimitry Andric << LHS.getIdentifier();
5810b57cec5SDimitry Andric else
5820b57cec5SDimitry Andric PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
5830b57cec5SDimitry Andric << LHS.getRange();
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andric /// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
5870b57cec5SDimitry Andric /// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS.
5880b57cec5SDimitry Andric ///
5890b57cec5SDimitry Andric /// If ValueLive is false, then this value is being evaluated in a context where
5900b57cec5SDimitry Andric /// the result is not used. As such, avoid diagnostics that relate to
5910b57cec5SDimitry Andric /// evaluation, such as division by zero warnings.
EvaluateDirectiveSubExpr(PPValue & LHS,unsigned MinPrec,Token & PeekTok,bool ValueLive,bool & IncludedUndefinedIds,Preprocessor & PP)5920b57cec5SDimitry Andric static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,
5930b57cec5SDimitry Andric Token &PeekTok, bool ValueLive,
5940b57cec5SDimitry Andric bool &IncludedUndefinedIds,
5950b57cec5SDimitry Andric Preprocessor &PP) {
5960b57cec5SDimitry Andric unsigned PeekPrec = getPrecedence(PeekTok.getKind());
5970b57cec5SDimitry Andric // If this token isn't valid, report the error.
5980b57cec5SDimitry Andric if (PeekPrec == ~0U) {
5990b57cec5SDimitry Andric diagnoseUnexpectedOperator(PP, LHS, PeekTok);
6000b57cec5SDimitry Andric return true;
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric while (true) {
6040b57cec5SDimitry Andric // If this token has a lower precedence than we are allowed to parse, return
6050b57cec5SDimitry Andric // it so that higher levels of the recursion can parse it.
6060b57cec5SDimitry Andric if (PeekPrec < MinPrec)
6070b57cec5SDimitry Andric return false;
6080b57cec5SDimitry Andric
6090b57cec5SDimitry Andric tok::TokenKind Operator = PeekTok.getKind();
6100b57cec5SDimitry Andric
6110b57cec5SDimitry Andric // If this is a short-circuiting operator, see if the RHS of the operator is
6120b57cec5SDimitry Andric // dead. Note that this cannot just clobber ValueLive. Consider
6130b57cec5SDimitry Andric // "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In
6140b57cec5SDimitry Andric // this example, the RHS of the && being dead does not make the rest of the
6150b57cec5SDimitry Andric // expr dead.
6160b57cec5SDimitry Andric bool RHSIsLive;
6170b57cec5SDimitry Andric if (Operator == tok::ampamp && LHS.Val == 0)
6180b57cec5SDimitry Andric RHSIsLive = false; // RHS of "0 && x" is dead.
6190b57cec5SDimitry Andric else if (Operator == tok::pipepipe && LHS.Val != 0)
6200b57cec5SDimitry Andric RHSIsLive = false; // RHS of "1 || x" is dead.
6210b57cec5SDimitry Andric else if (Operator == tok::question && LHS.Val == 0)
6220b57cec5SDimitry Andric RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.
6230b57cec5SDimitry Andric else
6240b57cec5SDimitry Andric RHSIsLive = ValueLive;
6250b57cec5SDimitry Andric
6260b57cec5SDimitry Andric // Consume the operator, remembering the operator's location for reporting.
6270b57cec5SDimitry Andric SourceLocation OpLoc = PeekTok.getLocation();
6280b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andric PPValue RHS(LHS.getBitWidth());
6310b57cec5SDimitry Andric // Parse the RHS of the operator.
6320b57cec5SDimitry Andric DefinedTracker DT;
6330b57cec5SDimitry Andric if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
6340b57cec5SDimitry Andric IncludedUndefinedIds = DT.IncludedUndefinedIds;
6350b57cec5SDimitry Andric
6360b57cec5SDimitry Andric // Remember the precedence of this operator and get the precedence of the
6370b57cec5SDimitry Andric // operator immediately to the right of the RHS.
6380b57cec5SDimitry Andric unsigned ThisPrec = PeekPrec;
6390b57cec5SDimitry Andric PeekPrec = getPrecedence(PeekTok.getKind());
6400b57cec5SDimitry Andric
6410b57cec5SDimitry Andric // If this token isn't valid, report the error.
6420b57cec5SDimitry Andric if (PeekPrec == ~0U) {
6430b57cec5SDimitry Andric diagnoseUnexpectedOperator(PP, RHS, PeekTok);
6440b57cec5SDimitry Andric return true;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric // Decide whether to include the next binop in this subexpression. For
6480b57cec5SDimitry Andric // example, when parsing x+y*z and looking at '*', we want to recursively
6490b57cec5SDimitry Andric // handle y*z as a single subexpression. We do this because the precedence
6500b57cec5SDimitry Andric // of * is higher than that of +. The only strange case we have to handle
6510b57cec5SDimitry Andric // here is for the ?: operator, where the precedence is actually lower than
6520b57cec5SDimitry Andric // the LHS of the '?'. The grammar rule is:
6530b57cec5SDimitry Andric //
6540b57cec5SDimitry Andric // conditional-expression ::=
6550b57cec5SDimitry Andric // logical-OR-expression ? expression : conditional-expression
6560b57cec5SDimitry Andric // where 'expression' is actually comma-expression.
6570b57cec5SDimitry Andric unsigned RHSPrec;
6580b57cec5SDimitry Andric if (Operator == tok::question)
6590b57cec5SDimitry Andric // The RHS of "?" should be maximally consumed as an expression.
6600b57cec5SDimitry Andric RHSPrec = getPrecedence(tok::comma);
6610b57cec5SDimitry Andric else // All others should munch while higher precedence.
6620b57cec5SDimitry Andric RHSPrec = ThisPrec+1;
6630b57cec5SDimitry Andric
6640b57cec5SDimitry Andric if (PeekPrec >= RHSPrec) {
6650b57cec5SDimitry Andric if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive,
6660b57cec5SDimitry Andric IncludedUndefinedIds, PP))
6670b57cec5SDimitry Andric return true;
6680b57cec5SDimitry Andric PeekPrec = getPrecedence(PeekTok.getKind());
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric assert(PeekPrec <= ThisPrec && "Recursion didn't work!");
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
6730b57cec5SDimitry Andric // either operand is unsigned.
6740b57cec5SDimitry Andric llvm::APSInt Res(LHS.getBitWidth());
6750b57cec5SDimitry Andric switch (Operator) {
6760b57cec5SDimitry Andric case tok::question: // No UAC for x and y in "x ? y : z".
6770b57cec5SDimitry Andric case tok::lessless: // Shift amount doesn't UAC with shift value.
6780b57cec5SDimitry Andric case tok::greatergreater: // Shift amount doesn't UAC with shift value.
6790b57cec5SDimitry Andric case tok::comma: // Comma operands are not subject to UACs.
6800b57cec5SDimitry Andric case tok::pipepipe: // Logical || does not do UACs.
6810b57cec5SDimitry Andric case tok::ampamp: // Logical && does not do UACs.
6820b57cec5SDimitry Andric break; // No UAC
6830b57cec5SDimitry Andric default:
684349cc55cSDimitry Andric Res.setIsUnsigned(LHS.isUnsigned() || RHS.isUnsigned());
6850b57cec5SDimitry Andric // If this just promoted something from signed to unsigned, and if the
6860b57cec5SDimitry Andric // value was negative, warn about it.
6870b57cec5SDimitry Andric if (ValueLive && Res.isUnsigned()) {
6880b57cec5SDimitry Andric if (!LHS.isUnsigned() && LHS.Val.isNegative())
6890b57cec5SDimitry Andric PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
690fe6060f1SDimitry Andric << toString(LHS.Val, 10, true) + " to " +
691fe6060f1SDimitry Andric toString(LHS.Val, 10, false)
6920b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
6930b57cec5SDimitry Andric if (!RHS.isUnsigned() && RHS.Val.isNegative())
6940b57cec5SDimitry Andric PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
695fe6060f1SDimitry Andric << toString(RHS.Val, 10, true) + " to " +
696fe6060f1SDimitry Andric toString(RHS.Val, 10, false)
6970b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric LHS.Val.setIsUnsigned(Res.isUnsigned());
7000b57cec5SDimitry Andric RHS.Val.setIsUnsigned(Res.isUnsigned());
7010b57cec5SDimitry Andric }
7020b57cec5SDimitry Andric
7030b57cec5SDimitry Andric bool Overflow = false;
7040b57cec5SDimitry Andric switch (Operator) {
7050b57cec5SDimitry Andric default: llvm_unreachable("Unknown operator token!");
7060b57cec5SDimitry Andric case tok::percent:
7070b57cec5SDimitry Andric if (RHS.Val != 0)
7080b57cec5SDimitry Andric Res = LHS.Val % RHS.Val;
7090b57cec5SDimitry Andric else if (ValueLive) {
7100b57cec5SDimitry Andric PP.Diag(OpLoc, diag::err_pp_remainder_by_zero)
7110b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
7120b57cec5SDimitry Andric return true;
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric break;
7150b57cec5SDimitry Andric case tok::slash:
7160b57cec5SDimitry Andric if (RHS.Val != 0) {
7170b57cec5SDimitry Andric if (LHS.Val.isSigned())
7180b57cec5SDimitry Andric Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false);
7190b57cec5SDimitry Andric else
7200b57cec5SDimitry Andric Res = LHS.Val / RHS.Val;
7210b57cec5SDimitry Andric } else if (ValueLive) {
7220b57cec5SDimitry Andric PP.Diag(OpLoc, diag::err_pp_division_by_zero)
7230b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
7240b57cec5SDimitry Andric return true;
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric break;
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andric case tok::star:
7290b57cec5SDimitry Andric if (Res.isSigned())
7300b57cec5SDimitry Andric Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false);
7310b57cec5SDimitry Andric else
7320b57cec5SDimitry Andric Res = LHS.Val * RHS.Val;
7330b57cec5SDimitry Andric break;
7340b57cec5SDimitry Andric case tok::lessless: {
7350b57cec5SDimitry Andric // Determine whether overflow is about to happen.
7360b57cec5SDimitry Andric if (LHS.isUnsigned())
7370b57cec5SDimitry Andric Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
7380b57cec5SDimitry Andric else
7390b57cec5SDimitry Andric Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow), false);
7400b57cec5SDimitry Andric break;
7410b57cec5SDimitry Andric }
7420b57cec5SDimitry Andric case tok::greatergreater: {
7430b57cec5SDimitry Andric // Determine whether overflow is about to happen.
7440b57cec5SDimitry Andric unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());
7450b57cec5SDimitry Andric if (ShAmt >= LHS.getBitWidth()) {
7460b57cec5SDimitry Andric Overflow = true;
7470b57cec5SDimitry Andric ShAmt = LHS.getBitWidth()-1;
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric Res = LHS.Val >> ShAmt;
7500b57cec5SDimitry Andric break;
7510b57cec5SDimitry Andric }
7520b57cec5SDimitry Andric case tok::plus:
7530b57cec5SDimitry Andric if (LHS.isUnsigned())
7540b57cec5SDimitry Andric Res = LHS.Val + RHS.Val;
7550b57cec5SDimitry Andric else
7560b57cec5SDimitry Andric Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false);
7570b57cec5SDimitry Andric break;
7580b57cec5SDimitry Andric case tok::minus:
7590b57cec5SDimitry Andric if (LHS.isUnsigned())
7600b57cec5SDimitry Andric Res = LHS.Val - RHS.Val;
7610b57cec5SDimitry Andric else
7620b57cec5SDimitry Andric Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false);
7630b57cec5SDimitry Andric break;
7640b57cec5SDimitry Andric case tok::lessequal:
7650b57cec5SDimitry Andric Res = LHS.Val <= RHS.Val;
7660b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
7670b57cec5SDimitry Andric break;
7680b57cec5SDimitry Andric case tok::less:
7690b57cec5SDimitry Andric Res = LHS.Val < RHS.Val;
7700b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
7710b57cec5SDimitry Andric break;
7720b57cec5SDimitry Andric case tok::greaterequal:
7730b57cec5SDimitry Andric Res = LHS.Val >= RHS.Val;
7740b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
7750b57cec5SDimitry Andric break;
7760b57cec5SDimitry Andric case tok::greater:
7770b57cec5SDimitry Andric Res = LHS.Val > RHS.Val;
7780b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)
7790b57cec5SDimitry Andric break;
7800b57cec5SDimitry Andric case tok::exclaimequal:
7810b57cec5SDimitry Andric Res = LHS.Val != RHS.Val;
7820b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
7830b57cec5SDimitry Andric break;
7840b57cec5SDimitry Andric case tok::equalequal:
7850b57cec5SDimitry Andric Res = LHS.Val == RHS.Val;
7860b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)
7870b57cec5SDimitry Andric break;
7880b57cec5SDimitry Andric case tok::amp:
7890b57cec5SDimitry Andric Res = LHS.Val & RHS.Val;
7900b57cec5SDimitry Andric break;
7910b57cec5SDimitry Andric case tok::caret:
7920b57cec5SDimitry Andric Res = LHS.Val ^ RHS.Val;
7930b57cec5SDimitry Andric break;
7940b57cec5SDimitry Andric case tok::pipe:
7950b57cec5SDimitry Andric Res = LHS.Val | RHS.Val;
7960b57cec5SDimitry Andric break;
7970b57cec5SDimitry Andric case tok::ampamp:
7980b57cec5SDimitry Andric Res = (LHS.Val != 0 && RHS.Val != 0);
7990b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.13p3, result is always int (signed)
8000b57cec5SDimitry Andric break;
8010b57cec5SDimitry Andric case tok::pipepipe:
8020b57cec5SDimitry Andric Res = (LHS.Val != 0 || RHS.Val != 0);
8030b57cec5SDimitry Andric Res.setIsUnsigned(false); // C99 6.5.14p3, result is always int (signed)
8040b57cec5SDimitry Andric break;
8050b57cec5SDimitry Andric case tok::comma:
8060b57cec5SDimitry Andric // Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99
8070b57cec5SDimitry Andric // if not being evaluated.
8080b57cec5SDimitry Andric if (!PP.getLangOpts().C99 || ValueLive)
8090b57cec5SDimitry Andric PP.Diag(OpLoc, diag::ext_pp_comma_expr)
8100b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
8110b57cec5SDimitry Andric Res = RHS.Val; // LHS = LHS,RHS -> RHS.
8120b57cec5SDimitry Andric break;
8130b57cec5SDimitry Andric case tok::question: {
8140b57cec5SDimitry Andric // Parse the : part of the expression.
8150b57cec5SDimitry Andric if (PeekTok.isNot(tok::colon)) {
8160b57cec5SDimitry Andric PP.Diag(PeekTok.getLocation(), diag::err_expected)
8170b57cec5SDimitry Andric << tok::colon << LHS.getRange() << RHS.getRange();
8180b57cec5SDimitry Andric PP.Diag(OpLoc, diag::note_matching) << tok::question;
8190b57cec5SDimitry Andric return true;
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric // Consume the :.
8220b57cec5SDimitry Andric PP.LexNonComment(PeekTok);
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric // Evaluate the value after the :.
8250b57cec5SDimitry Andric bool AfterColonLive = ValueLive && LHS.Val == 0;
8260b57cec5SDimitry Andric PPValue AfterColonVal(LHS.getBitWidth());
8270b57cec5SDimitry Andric DefinedTracker DT;
8280b57cec5SDimitry Andric if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
8290b57cec5SDimitry Andric return true;
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric // Parse anything after the : with the same precedence as ?. We allow
8320b57cec5SDimitry Andric // things of equal precedence because ?: is right associative.
8330b57cec5SDimitry Andric if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,
8340b57cec5SDimitry Andric PeekTok, AfterColonLive,
8350b57cec5SDimitry Andric IncludedUndefinedIds, PP))
8360b57cec5SDimitry Andric return true;
8370b57cec5SDimitry Andric
8380b57cec5SDimitry Andric // Now that we have the condition, the LHS and the RHS of the :, evaluate.
8390b57cec5SDimitry Andric Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
8400b57cec5SDimitry Andric RHS.setEnd(AfterColonVal.getRange().getEnd());
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric // Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if
8430b57cec5SDimitry Andric // either operand is unsigned.
844349cc55cSDimitry Andric Res.setIsUnsigned(RHS.isUnsigned() || AfterColonVal.isUnsigned());
8450b57cec5SDimitry Andric
8460b57cec5SDimitry Andric // Figure out the precedence of the token after the : part.
8470b57cec5SDimitry Andric PeekPrec = getPrecedence(PeekTok.getKind());
8480b57cec5SDimitry Andric break;
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric case tok::colon:
8510b57cec5SDimitry Andric // Don't allow :'s to float around without being part of ?: exprs.
8520b57cec5SDimitry Andric PP.Diag(OpLoc, diag::err_pp_colon_without_question)
8530b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
8540b57cec5SDimitry Andric return true;
8550b57cec5SDimitry Andric }
8560b57cec5SDimitry Andric
8570b57cec5SDimitry Andric // If this operator is live and overflowed, report the issue.
8580b57cec5SDimitry Andric if (Overflow && ValueLive)
8590b57cec5SDimitry Andric PP.Diag(OpLoc, diag::warn_pp_expr_overflow)
8600b57cec5SDimitry Andric << LHS.getRange() << RHS.getRange();
8610b57cec5SDimitry Andric
8620b57cec5SDimitry Andric // Put the result back into 'LHS' for our next iteration.
8630b57cec5SDimitry Andric LHS.Val = Res;
8640b57cec5SDimitry Andric LHS.setEnd(RHS.getRange().getEnd());
8650b57cec5SDimitry Andric RHS.setIdentifier(nullptr);
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric
8690b57cec5SDimitry Andric /// EvaluateDirectiveExpression - Evaluate an integer constant expression that
8700b57cec5SDimitry Andric /// may occur after a #if or #elif directive. If the expression is equivalent
8710b57cec5SDimitry Andric /// to "!defined(X)" return X in IfNDefMacro.
8720b57cec5SDimitry Andric Preprocessor::DirectiveEvalResult
EvaluateDirectiveExpression(IdentifierInfo * & IfNDefMacro,Token & Tok,bool & EvaluatedDefined,bool CheckForEoD)873*0fca6ea1SDimitry Andric Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,
874*0fca6ea1SDimitry Andric Token &Tok, bool &EvaluatedDefined,
875*0fca6ea1SDimitry Andric bool CheckForEoD) {
876bdd1243dSDimitry Andric SaveAndRestore PPDir(ParsingIfOrElifDirective, true);
8770b57cec5SDimitry Andric // Save the current state of 'DisableMacroExpansion' and reset it to false. If
8780b57cec5SDimitry Andric // 'DisableMacroExpansion' is true, then we must be in a macro argument list
8790b57cec5SDimitry Andric // in which case a directive is undefined behavior. We want macros to be able
8800b57cec5SDimitry Andric // to recursively expand in order to get more gcc-list behavior, so we force
8810b57cec5SDimitry Andric // DisableMacroExpansion to false and restore it when we're done parsing the
8820b57cec5SDimitry Andric // expression.
8830b57cec5SDimitry Andric bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
8840b57cec5SDimitry Andric DisableMacroExpansion = false;
8850b57cec5SDimitry Andric
8860b57cec5SDimitry Andric // Peek ahead one token.
8870b57cec5SDimitry Andric LexNonComment(Tok);
8880b57cec5SDimitry Andric
8890b57cec5SDimitry Andric // C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.
8900b57cec5SDimitry Andric unsigned BitWidth = getTargetInfo().getIntMaxTWidth();
8910b57cec5SDimitry Andric
8920b57cec5SDimitry Andric PPValue ResVal(BitWidth);
8930b57cec5SDimitry Andric DefinedTracker DT;
8940b57cec5SDimitry Andric SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation());
8950b57cec5SDimitry Andric if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
8960b57cec5SDimitry Andric // Parse error, skip the rest of the macro line.
8970b57cec5SDimitry Andric SourceRange ConditionRange = ExprStartLoc;
8980b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
899*0fca6ea1SDimitry Andric ConditionRange = DiscardUntilEndOfDirective(Tok);
9000b57cec5SDimitry Andric
9010b57cec5SDimitry Andric // Restore 'DisableMacroExpansion'.
9020b57cec5SDimitry Andric DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
9030b57cec5SDimitry Andric
9040b57cec5SDimitry Andric // We cannot trust the source range from the value because there was a
9050b57cec5SDimitry Andric // parse error. Track the range manually -- the end of the directive is the
9060b57cec5SDimitry Andric // end of the condition range.
907*0fca6ea1SDimitry Andric return {std::nullopt,
908*0fca6ea1SDimitry Andric false,
9090b57cec5SDimitry Andric DT.IncludedUndefinedIds,
9100b57cec5SDimitry Andric {ExprStartLoc, ConditionRange.getEnd()}};
9110b57cec5SDimitry Andric }
9120b57cec5SDimitry Andric
913*0fca6ea1SDimitry Andric EvaluatedDefined = DT.State != DefinedTracker::Unknown;
914*0fca6ea1SDimitry Andric
9150b57cec5SDimitry Andric // If we are at the end of the expression after just parsing a value, there
9160b57cec5SDimitry Andric // must be no (unparenthesized) binary operators involved, so we can exit
9170b57cec5SDimitry Andric // directly.
9180b57cec5SDimitry Andric if (Tok.is(tok::eod)) {
9190b57cec5SDimitry Andric // If the expression we parsed was of the form !defined(macro), return the
9200b57cec5SDimitry Andric // macro in IfNDefMacro.
9210b57cec5SDimitry Andric if (DT.State == DefinedTracker::NotDefinedMacro)
9220b57cec5SDimitry Andric IfNDefMacro = DT.TheMacro;
9230b57cec5SDimitry Andric
9240b57cec5SDimitry Andric // Restore 'DisableMacroExpansion'.
9250b57cec5SDimitry Andric DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
926*0fca6ea1SDimitry Andric bool IsNonZero = ResVal.Val != 0;
927*0fca6ea1SDimitry Andric SourceRange ValRange = ResVal.getRange();
928*0fca6ea1SDimitry Andric return {std::move(ResVal.Val), IsNonZero, DT.IncludedUndefinedIds,
929*0fca6ea1SDimitry Andric ValRange};
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric
9320b57cec5SDimitry Andric // Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
9330b57cec5SDimitry Andric // operator and the stuff after it.
9340b57cec5SDimitry Andric if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),
9350b57cec5SDimitry Andric Tok, true, DT.IncludedUndefinedIds, *this)) {
9360b57cec5SDimitry Andric // Parse error, skip the rest of the macro line.
9370b57cec5SDimitry Andric if (Tok.isNot(tok::eod))
938*0fca6ea1SDimitry Andric DiscardUntilEndOfDirective(Tok);
9390b57cec5SDimitry Andric
9400b57cec5SDimitry Andric // Restore 'DisableMacroExpansion'.
9410b57cec5SDimitry Andric DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
942*0fca6ea1SDimitry Andric SourceRange ValRange = ResVal.getRange();
943*0fca6ea1SDimitry Andric return {std::nullopt, false, DT.IncludedUndefinedIds, ValRange};
9440b57cec5SDimitry Andric }
9450b57cec5SDimitry Andric
946*0fca6ea1SDimitry Andric if (CheckForEoD) {
9470b57cec5SDimitry Andric // If we aren't at the tok::eod token, something bad happened, like an extra
9480b57cec5SDimitry Andric // ')' token.
9490b57cec5SDimitry Andric if (Tok.isNot(tok::eod)) {
9500b57cec5SDimitry Andric Diag(Tok, diag::err_pp_expected_eol);
951*0fca6ea1SDimitry Andric DiscardUntilEndOfDirective(Tok);
9520b57cec5SDimitry Andric }
953*0fca6ea1SDimitry Andric }
954*0fca6ea1SDimitry Andric
955*0fca6ea1SDimitry Andric EvaluatedDefined = EvaluatedDefined || DT.State != DefinedTracker::Unknown;
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric // Restore 'DisableMacroExpansion'.
9580b57cec5SDimitry Andric DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
959*0fca6ea1SDimitry Andric bool IsNonZero = ResVal.Val != 0;
960*0fca6ea1SDimitry Andric SourceRange ValRange = ResVal.getRange();
961*0fca6ea1SDimitry Andric return {std::move(ResVal.Val), IsNonZero, DT.IncludedUndefinedIds, ValRange};
962*0fca6ea1SDimitry Andric }
963*0fca6ea1SDimitry Andric
964*0fca6ea1SDimitry Andric Preprocessor::DirectiveEvalResult
EvaluateDirectiveExpression(IdentifierInfo * & IfNDefMacro,bool CheckForEoD)965*0fca6ea1SDimitry Andric Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,
966*0fca6ea1SDimitry Andric bool CheckForEoD) {
967*0fca6ea1SDimitry Andric Token Tok;
968*0fca6ea1SDimitry Andric bool EvaluatedDefined;
969*0fca6ea1SDimitry Andric return EvaluateDirectiveExpression(IfNDefMacro, Tok, EvaluatedDefined,
970*0fca6ea1SDimitry Andric CheckForEoD);
9710b57cec5SDimitry Andric }
972