Path: blob/main/contrib/llvm-project/clang/lib/Lex/PPExpressions.cpp
35233 views
//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the Preprocessor::EvaluateDirectiveExpression method,9// which parses and evaluates integer constant expressions for #if directives.10//11//===----------------------------------------------------------------------===//12//13// FIXME: implement testing for #assert's.14//15//===----------------------------------------------------------------------===//1617#include "clang/Basic/IdentifierTable.h"18#include "clang/Basic/SourceLocation.h"19#include "clang/Basic/SourceManager.h"20#include "clang/Basic/TargetInfo.h"21#include "clang/Basic/TokenKinds.h"22#include "clang/Lex/CodeCompletionHandler.h"23#include "clang/Lex/LexDiagnostic.h"24#include "clang/Lex/LiteralSupport.h"25#include "clang/Lex/MacroInfo.h"26#include "clang/Lex/PPCallbacks.h"27#include "clang/Lex/Preprocessor.h"28#include "clang/Lex/Token.h"29#include "llvm/ADT/APSInt.h"30#include "llvm/ADT/STLExtras.h"31#include "llvm/ADT/SmallString.h"32#include "llvm/ADT/StringExtras.h"33#include "llvm/ADT/StringRef.h"34#include "llvm/Support/ErrorHandling.h"35#include "llvm/Support/SaveAndRestore.h"36#include <cassert>3738using namespace clang;3940namespace {4142/// PPValue - Represents the value of a subexpression of a preprocessor43/// conditional and the source range covered by it.44class PPValue {45SourceRange Range;46IdentifierInfo *II = nullptr;4748public:49llvm::APSInt Val;5051// Default ctor - Construct an 'invalid' PPValue.52PPValue(unsigned BitWidth) : Val(BitWidth) {}5354// If this value was produced by directly evaluating an identifier, produce55// that identifier.56IdentifierInfo *getIdentifier() const { return II; }57void setIdentifier(IdentifierInfo *II) { this->II = II; }5859unsigned getBitWidth() const { return Val.getBitWidth(); }60bool isUnsigned() const { return Val.isUnsigned(); }6162SourceRange getRange() const { return Range; }6364void setRange(SourceLocation L) { Range.setBegin(L); Range.setEnd(L); }65void setRange(SourceLocation B, SourceLocation E) {66Range.setBegin(B); Range.setEnd(E);67}68void setBegin(SourceLocation L) { Range.setBegin(L); }69void setEnd(SourceLocation L) { Range.setEnd(L); }70};7172} // end anonymous namespace7374static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,75Token &PeekTok, bool ValueLive,76bool &IncludedUndefinedIds,77Preprocessor &PP);7879/// DefinedTracker - This struct is used while parsing expressions to keep track80/// of whether !defined(X) has been seen.81///82/// With this simple scheme, we handle the basic forms:83/// !defined(X) and !defined X84/// but we also trivially handle (silly) stuff like:85/// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)).86struct DefinedTracker {87/// Each time a Value is evaluated, it returns information about whether the88/// parsed value is of the form defined(X), !defined(X) or is something else.89enum TrackerState {90DefinedMacro, // defined(X)91NotDefinedMacro, // !defined(X)92Unknown // Something else.93} State;94/// TheMacro - When the state is DefinedMacro or NotDefinedMacro, this95/// indicates the macro that was checked.96IdentifierInfo *TheMacro;97bool IncludedUndefinedIds = false;98};99100/// EvaluateDefined - Process a 'defined(sym)' expression.101static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT,102bool ValueLive, Preprocessor &PP) {103SourceLocation beginLoc(PeekTok.getLocation());104Result.setBegin(beginLoc);105106// Get the next token, don't expand it.107PP.LexUnexpandedNonComment(PeekTok);108109// Two options, it can either be a pp-identifier or a (.110SourceLocation LParenLoc;111if (PeekTok.is(tok::l_paren)) {112// Found a paren, remember we saw it and skip it.113LParenLoc = PeekTok.getLocation();114PP.LexUnexpandedNonComment(PeekTok);115}116117if (PeekTok.is(tok::code_completion)) {118if (PP.getCodeCompletionHandler())119PP.getCodeCompletionHandler()->CodeCompleteMacroName(false);120PP.setCodeCompletionReached();121PP.LexUnexpandedNonComment(PeekTok);122}123124// If we don't have a pp-identifier now, this is an error.125if (PP.CheckMacroName(PeekTok, MU_Other))126return true;127128// Otherwise, we got an identifier, is it defined to something?129IdentifierInfo *II = PeekTok.getIdentifierInfo();130MacroDefinition Macro = PP.getMacroDefinition(II);131Result.Val = !!Macro;132Result.Val.setIsUnsigned(false); // Result is signed intmax_t.133DT.IncludedUndefinedIds = !Macro;134135PP.emitMacroExpansionWarnings(136PeekTok,137(II->getName() == "INFINITY" || II->getName() == "NAN") ? true : false);138139// If there is a macro, mark it used.140if (Result.Val != 0 && ValueLive)141PP.markMacroAsUsed(Macro.getMacroInfo());142143// Save macro token for callback.144Token macroToken(PeekTok);145146// If we are in parens, ensure we have a trailing ).147if (LParenLoc.isValid()) {148// Consume identifier.149Result.setEnd(PeekTok.getLocation());150PP.LexUnexpandedNonComment(PeekTok);151152if (PeekTok.isNot(tok::r_paren)) {153PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_after)154<< "'defined'" << tok::r_paren;155PP.Diag(LParenLoc, diag::note_matching) << tok::l_paren;156return true;157}158// Consume the ).159PP.LexNonComment(PeekTok);160Result.setEnd(PeekTok.getLocation());161} else {162// Consume identifier.163Result.setEnd(PeekTok.getLocation());164PP.LexNonComment(PeekTok);165}166167// [cpp.cond]p4:168// Prior to evaluation, macro invocations in the list of preprocessing169// tokens that will become the controlling constant expression are replaced170// (except for those macro names modified by the 'defined' unary operator),171// just as in normal text. If the token 'defined' is generated as a result172// of this replacement process or use of the 'defined' unary operator does173// not match one of the two specified forms prior to macro replacement, the174// behavior is undefined.175// This isn't an idle threat, consider this program:176// #define FOO177// #define BAR defined(FOO)178// #if BAR179// ...180// #else181// ...182// #endif183// clang and gcc will pick the #if branch while Visual Studio will take the184// #else branch. Emit a warning about this undefined behavior.185if (beginLoc.isMacroID()) {186bool IsFunctionTypeMacro =187PP.getSourceManager()188.getSLocEntry(PP.getSourceManager().getFileID(beginLoc))189.getExpansion()190.isFunctionMacroExpansion();191// For object-type macros, it's easy to replace192// #define FOO defined(BAR)193// with194// #if defined(BAR)195// #define FOO 1196// #else197// #define FOO 0198// #endif199// and doing so makes sense since compilers handle this differently in200// practice (see example further up). But for function-type macros,201// there is no good way to write202// # define FOO(x) (defined(M_ ## x) && M_ ## x)203// in a different way, and compilers seem to agree on how to behave here.204// So warn by default on object-type macros, but only warn in -pedantic205// mode on function-type macros.206if (IsFunctionTypeMacro)207PP.Diag(beginLoc, diag::warn_defined_in_function_type_macro);208else209PP.Diag(beginLoc, diag::warn_defined_in_object_type_macro);210}211212// Invoke the 'defined' callback.213if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {214Callbacks->Defined(macroToken, Macro,215SourceRange(beginLoc, PeekTok.getLocation()));216}217218// Success, remember that we saw defined(X).219DT.State = DefinedTracker::DefinedMacro;220DT.TheMacro = II;221return false;222}223224/// EvaluateValue - Evaluate the token PeekTok (and any others needed) and225/// return the computed value in Result. Return true if there was an error226/// parsing. This function also returns information about the form of the227/// expression in DT. See above for information on what DT means.228///229/// If ValueLive is false, then this value is being evaluated in a context where230/// the result is not used. As such, avoid diagnostics that relate to231/// evaluation.232static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,233bool ValueLive, Preprocessor &PP) {234DT.State = DefinedTracker::Unknown;235236Result.setIdentifier(nullptr);237238if (PeekTok.is(tok::code_completion)) {239if (PP.getCodeCompletionHandler())240PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();241PP.setCodeCompletionReached();242PP.LexNonComment(PeekTok);243}244245switch (PeekTok.getKind()) {246default:247// If this token's spelling is a pp-identifier, check to see if it is248// 'defined' or if it is a macro. Note that we check here because many249// keywords are pp-identifiers, so we can't check the kind.250if (IdentifierInfo *II = PeekTok.getIdentifierInfo()) {251// Handle "defined X" and "defined(X)".252if (II->isStr("defined"))253return EvaluateDefined(Result, PeekTok, DT, ValueLive, PP);254255if (!II->isCPlusPlusOperatorKeyword()) {256// If this identifier isn't 'defined' or one of the special257// preprocessor keywords and it wasn't macro expanded, it turns258// into a simple 0259if (ValueLive) {260PP.Diag(PeekTok, diag::warn_pp_undef_identifier) << II;261262const DiagnosticsEngine &DiagEngine = PP.getDiagnostics();263// If 'Wundef' is enabled, do not emit 'undef-prefix' diagnostics.264if (DiagEngine.isIgnored(diag::warn_pp_undef_identifier,265PeekTok.getLocation())) {266const std::vector<std::string> UndefPrefixes =267DiagEngine.getDiagnosticOptions().UndefPrefixes;268const StringRef IdentifierName = II->getName();269if (llvm::any_of(UndefPrefixes,270[&IdentifierName](const std::string &Prefix) {271return IdentifierName.starts_with(Prefix);272}))273PP.Diag(PeekTok, diag::warn_pp_undef_prefix)274<< AddFlagValue{llvm::join(UndefPrefixes, ",")} << II;275}276}277Result.Val = 0;278Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.279Result.setIdentifier(II);280Result.setRange(PeekTok.getLocation());281DT.IncludedUndefinedIds = true;282PP.LexNonComment(PeekTok);283return false;284}285}286PP.Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);287return true;288case tok::eod:289case tok::r_paren:290// If there is no expression, report and exit.291PP.Diag(PeekTok, diag::err_pp_expected_value_in_expr);292return true;293case tok::numeric_constant: {294SmallString<64> IntegerBuffer;295bool NumberInvalid = false;296StringRef Spelling = PP.getSpelling(PeekTok, IntegerBuffer,297&NumberInvalid);298if (NumberInvalid)299return true; // a diagnostic was already reported300301NumericLiteralParser Literal(Spelling, PeekTok.getLocation(),302PP.getSourceManager(), PP.getLangOpts(),303PP.getTargetInfo(), PP.getDiagnostics());304if (Literal.hadError)305return true; // a diagnostic was already reported.306307if (Literal.isFloatingLiteral() || Literal.isImaginary) {308PP.Diag(PeekTok, diag::err_pp_illegal_floating_literal);309return true;310}311assert(Literal.isIntegerLiteral() && "Unknown ppnumber");312313// Complain about, and drop, any ud-suffix.314if (Literal.hasUDSuffix())315PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*integer*/1;316317// 'long long' is a C99 or C++11 feature.318if (!PP.getLangOpts().C99 && Literal.isLongLong) {319if (PP.getLangOpts().CPlusPlus)320PP.Diag(PeekTok,321PP.getLangOpts().CPlusPlus11 ?322diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);323else324PP.Diag(PeekTok, diag::ext_c99_longlong);325}326327// 'z/uz' literals are a C++23 feature.328if (Literal.isSizeT)329PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus330? PP.getLangOpts().CPlusPlus23331? diag::warn_cxx20_compat_size_t_suffix332: diag::ext_cxx23_size_t_suffix333: diag::err_cxx23_size_t_suffix);334335// 'wb/uwb' literals are a C23 feature.336// '__wb/__uwb' are a C++ extension.337if (Literal.isBitInt)338PP.Diag(PeekTok, PP.getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix339: PP.getLangOpts().C23340? diag::warn_c23_compat_bitint_suffix341: diag::ext_c23_bitint_suffix);342343// Parse the integer literal into Result.344if (Literal.GetIntegerValue(Result.Val)) {345// Overflow parsing integer literal.346if (ValueLive)347PP.Diag(PeekTok, diag::err_integer_literal_too_large)348<< /* Unsigned */ 1;349Result.Val.setIsUnsigned(true);350} else {351// Set the signedness of the result to match whether there was a U suffix352// or not.353Result.Val.setIsUnsigned(Literal.isUnsigned);354355// Detect overflow based on whether the value is signed. If signed356// and if the value is too large, emit a warning "integer constant is so357// large that it is unsigned" e.g. on 12345678901234567890 where intmax_t358// is 64-bits.359if (!Literal.isUnsigned && Result.Val.isNegative()) {360// Octal, hexadecimal, and binary literals are implicitly unsigned if361// the value does not fit into a signed integer type.362if (ValueLive && Literal.getRadix() == 10)363PP.Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);364Result.Val.setIsUnsigned(true);365}366}367368// Consume the token.369Result.setRange(PeekTok.getLocation());370PP.LexNonComment(PeekTok);371return false;372}373case tok::char_constant: // 'x'374case tok::wide_char_constant: // L'x'375case tok::utf8_char_constant: // u8'x'376case tok::utf16_char_constant: // u'x'377case tok::utf32_char_constant: { // U'x'378// Complain about, and drop, any ud-suffix.379if (PeekTok.hasUDSuffix())380PP.Diag(PeekTok, diag::err_pp_invalid_udl) << /*character*/0;381382SmallString<32> CharBuffer;383bool CharInvalid = false;384StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);385if (CharInvalid)386return true;387388CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(),389PeekTok.getLocation(), PP, PeekTok.getKind());390if (Literal.hadError())391return true; // A diagnostic was already emitted.392393// Character literals are always int or wchar_t, expand to intmax_t.394const TargetInfo &TI = PP.getTargetInfo();395unsigned NumBits;396if (Literal.isMultiChar())397NumBits = TI.getIntWidth();398else if (Literal.isWide())399NumBits = TI.getWCharWidth();400else if (Literal.isUTF16())401NumBits = TI.getChar16Width();402else if (Literal.isUTF32())403NumBits = TI.getChar32Width();404else // char or char8_t405NumBits = TI.getCharWidth();406407// Set the width.408llvm::APSInt Val(NumBits);409// Set the value.410Val = Literal.getValue();411// Set the signedness. UTF-16 and UTF-32 are always unsigned412// UTF-8 is unsigned if -fchar8_t is specified.413if (Literal.isWide())414Val.setIsUnsigned(!TargetInfo::isTypeSigned(TI.getWCharType()));415else if (Literal.isUTF16() || Literal.isUTF32())416Val.setIsUnsigned(true);417else if (Literal.isUTF8()) {418if (PP.getLangOpts().CPlusPlus)419Val.setIsUnsigned(420PP.getLangOpts().Char8 ? true : !PP.getLangOpts().CharIsSigned);421else422Val.setIsUnsigned(true);423} else424Val.setIsUnsigned(!PP.getLangOpts().CharIsSigned);425426if (Result.Val.getBitWidth() > Val.getBitWidth()) {427Result.Val = Val.extend(Result.Val.getBitWidth());428} else {429assert(Result.Val.getBitWidth() == Val.getBitWidth() &&430"intmax_t smaller than char/wchar_t?");431Result.Val = Val;432}433434// Consume the token.435Result.setRange(PeekTok.getLocation());436PP.LexNonComment(PeekTok);437return false;438}439case tok::l_paren: {440SourceLocation Start = PeekTok.getLocation();441PP.LexNonComment(PeekTok); // Eat the (.442// Parse the value and if there are any binary operators involved, parse443// them.444if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;445446// If this is a silly value like (X), which doesn't need parens, check for447// !(defined X).448if (PeekTok.is(tok::r_paren)) {449// Just use DT unmodified as our result.450} else {451// Otherwise, we have something like (x+y), and we consumed '(x'.452if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive,453DT.IncludedUndefinedIds, PP))454return true;455456if (PeekTok.isNot(tok::r_paren)) {457PP.Diag(PeekTok.getLocation(), diag::err_pp_expected_rparen)458<< Result.getRange();459PP.Diag(Start, diag::note_matching) << tok::l_paren;460return true;461}462DT.State = DefinedTracker::Unknown;463}464Result.setRange(Start, PeekTok.getLocation());465Result.setIdentifier(nullptr);466PP.LexNonComment(PeekTok); // Eat the ).467return false;468}469case tok::plus: {470SourceLocation Start = PeekTok.getLocation();471// Unary plus doesn't modify the value.472PP.LexNonComment(PeekTok);473if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;474Result.setBegin(Start);475Result.setIdentifier(nullptr);476return false;477}478case tok::minus: {479SourceLocation Loc = PeekTok.getLocation();480PP.LexNonComment(PeekTok);481if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;482Result.setBegin(Loc);483Result.setIdentifier(nullptr);484485// C99 6.5.3.3p3: The sign of the result matches the sign of the operand.486Result.Val = -Result.Val;487488// -MININT is the only thing that overflows. Unsigned never overflows.489bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();490491// If this operator is live and overflowed, report the issue.492if (Overflow && ValueLive)493PP.Diag(Loc, diag::warn_pp_expr_overflow) << Result.getRange();494495DT.State = DefinedTracker::Unknown;496return false;497}498499case tok::tilde: {500SourceLocation Start = PeekTok.getLocation();501PP.LexNonComment(PeekTok);502if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;503Result.setBegin(Start);504Result.setIdentifier(nullptr);505506// C99 6.5.3.3p4: The sign of the result matches the sign of the operand.507Result.Val = ~Result.Val;508DT.State = DefinedTracker::Unknown;509return false;510}511512case tok::exclaim: {513SourceLocation Start = PeekTok.getLocation();514PP.LexNonComment(PeekTok);515if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;516Result.setBegin(Start);517Result.Val = !Result.Val;518// C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.519Result.Val.setIsUnsigned(false);520Result.setIdentifier(nullptr);521522if (DT.State == DefinedTracker::DefinedMacro)523DT.State = DefinedTracker::NotDefinedMacro;524else if (DT.State == DefinedTracker::NotDefinedMacro)525DT.State = DefinedTracker::DefinedMacro;526return false;527}528case tok::kw_true:529case tok::kw_false:530Result.Val = PeekTok.getKind() == tok::kw_true;531Result.Val.setIsUnsigned(false); // "0" is signed intmax_t 0.532Result.setIdentifier(PeekTok.getIdentifierInfo());533Result.setRange(PeekTok.getLocation());534PP.LexNonComment(PeekTok);535return false;536537// FIXME: Handle #assert538}539}540541/// getPrecedence - Return the precedence of the specified binary operator542/// token. This returns:543/// ~0 - Invalid token.544/// 14 -> 3 - various operators.545/// 0 - 'eod' or ')'546static unsigned getPrecedence(tok::TokenKind Kind) {547switch (Kind) {548default: return ~0U;549case tok::percent:550case tok::slash:551case tok::star: return 14;552case tok::plus:553case tok::minus: return 13;554case tok::lessless:555case tok::greatergreater: return 12;556case tok::lessequal:557case tok::less:558case tok::greaterequal:559case tok::greater: return 11;560case tok::exclaimequal:561case tok::equalequal: return 10;562case tok::amp: return 9;563case tok::caret: return 8;564case tok::pipe: return 7;565case tok::ampamp: return 6;566case tok::pipepipe: return 5;567case tok::question: return 4;568case tok::comma: return 3;569case tok::colon: return 2;570case tok::r_paren: return 0;// Lowest priority, end of expr.571case tok::eod: return 0;// Lowest priority, end of directive.572}573}574575static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS,576Token &Tok) {577if (Tok.is(tok::l_paren) && LHS.getIdentifier())578PP.Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)579<< LHS.getIdentifier();580else581PP.Diag(Tok.getLocation(), diag::err_pp_expr_bad_token_binop)582<< LHS.getRange();583}584585/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is586/// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS.587///588/// If ValueLive is false, then this value is being evaluated in a context where589/// the result is not used. As such, avoid diagnostics that relate to590/// evaluation, such as division by zero warnings.591static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec,592Token &PeekTok, bool ValueLive,593bool &IncludedUndefinedIds,594Preprocessor &PP) {595unsigned PeekPrec = getPrecedence(PeekTok.getKind());596// If this token isn't valid, report the error.597if (PeekPrec == ~0U) {598diagnoseUnexpectedOperator(PP, LHS, PeekTok);599return true;600}601602while (true) {603// If this token has a lower precedence than we are allowed to parse, return604// it so that higher levels of the recursion can parse it.605if (PeekPrec < MinPrec)606return false;607608tok::TokenKind Operator = PeekTok.getKind();609610// If this is a short-circuiting operator, see if the RHS of the operator is611// dead. Note that this cannot just clobber ValueLive. Consider612// "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In613// this example, the RHS of the && being dead does not make the rest of the614// expr dead.615bool RHSIsLive;616if (Operator == tok::ampamp && LHS.Val == 0)617RHSIsLive = false; // RHS of "0 && x" is dead.618else if (Operator == tok::pipepipe && LHS.Val != 0)619RHSIsLive = false; // RHS of "1 || x" is dead.620else if (Operator == tok::question && LHS.Val == 0)621RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.622else623RHSIsLive = ValueLive;624625// Consume the operator, remembering the operator's location for reporting.626SourceLocation OpLoc = PeekTok.getLocation();627PP.LexNonComment(PeekTok);628629PPValue RHS(LHS.getBitWidth());630// Parse the RHS of the operator.631DefinedTracker DT;632if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;633IncludedUndefinedIds = DT.IncludedUndefinedIds;634635// Remember the precedence of this operator and get the precedence of the636// operator immediately to the right of the RHS.637unsigned ThisPrec = PeekPrec;638PeekPrec = getPrecedence(PeekTok.getKind());639640// If this token isn't valid, report the error.641if (PeekPrec == ~0U) {642diagnoseUnexpectedOperator(PP, RHS, PeekTok);643return true;644}645646// Decide whether to include the next binop in this subexpression. For647// example, when parsing x+y*z and looking at '*', we want to recursively648// handle y*z as a single subexpression. We do this because the precedence649// of * is higher than that of +. The only strange case we have to handle650// here is for the ?: operator, where the precedence is actually lower than651// the LHS of the '?'. The grammar rule is:652//653// conditional-expression ::=654// logical-OR-expression ? expression : conditional-expression655// where 'expression' is actually comma-expression.656unsigned RHSPrec;657if (Operator == tok::question)658// The RHS of "?" should be maximally consumed as an expression.659RHSPrec = getPrecedence(tok::comma);660else // All others should munch while higher precedence.661RHSPrec = ThisPrec+1;662663if (PeekPrec >= RHSPrec) {664if (EvaluateDirectiveSubExpr(RHS, RHSPrec, PeekTok, RHSIsLive,665IncludedUndefinedIds, PP))666return true;667PeekPrec = getPrecedence(PeekTok.getKind());668}669assert(PeekPrec <= ThisPrec && "Recursion didn't work!");670671// Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if672// either operand is unsigned.673llvm::APSInt Res(LHS.getBitWidth());674switch (Operator) {675case tok::question: // No UAC for x and y in "x ? y : z".676case tok::lessless: // Shift amount doesn't UAC with shift value.677case tok::greatergreater: // Shift amount doesn't UAC with shift value.678case tok::comma: // Comma operands are not subject to UACs.679case tok::pipepipe: // Logical || does not do UACs.680case tok::ampamp: // Logical && does not do UACs.681break; // No UAC682default:683Res.setIsUnsigned(LHS.isUnsigned() || RHS.isUnsigned());684// If this just promoted something from signed to unsigned, and if the685// value was negative, warn about it.686if (ValueLive && Res.isUnsigned()) {687if (!LHS.isUnsigned() && LHS.Val.isNegative())688PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0689<< toString(LHS.Val, 10, true) + " to " +690toString(LHS.Val, 10, false)691<< LHS.getRange() << RHS.getRange();692if (!RHS.isUnsigned() && RHS.Val.isNegative())693PP.Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1694<< toString(RHS.Val, 10, true) + " to " +695toString(RHS.Val, 10, false)696<< LHS.getRange() << RHS.getRange();697}698LHS.Val.setIsUnsigned(Res.isUnsigned());699RHS.Val.setIsUnsigned(Res.isUnsigned());700}701702bool Overflow = false;703switch (Operator) {704default: llvm_unreachable("Unknown operator token!");705case tok::percent:706if (RHS.Val != 0)707Res = LHS.Val % RHS.Val;708else if (ValueLive) {709PP.Diag(OpLoc, diag::err_pp_remainder_by_zero)710<< LHS.getRange() << RHS.getRange();711return true;712}713break;714case tok::slash:715if (RHS.Val != 0) {716if (LHS.Val.isSigned())717Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow), false);718else719Res = LHS.Val / RHS.Val;720} else if (ValueLive) {721PP.Diag(OpLoc, diag::err_pp_division_by_zero)722<< LHS.getRange() << RHS.getRange();723return true;724}725break;726727case tok::star:728if (Res.isSigned())729Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow), false);730else731Res = LHS.Val * RHS.Val;732break;733case tok::lessless: {734// Determine whether overflow is about to happen.735if (LHS.isUnsigned())736Res = LHS.Val.ushl_ov(RHS.Val, Overflow);737else738Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow), false);739break;740}741case tok::greatergreater: {742// Determine whether overflow is about to happen.743unsigned ShAmt = static_cast<unsigned>(RHS.Val.getLimitedValue());744if (ShAmt >= LHS.getBitWidth()) {745Overflow = true;746ShAmt = LHS.getBitWidth()-1;747}748Res = LHS.Val >> ShAmt;749break;750}751case tok::plus:752if (LHS.isUnsigned())753Res = LHS.Val + RHS.Val;754else755Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow), false);756break;757case tok::minus:758if (LHS.isUnsigned())759Res = LHS.Val - RHS.Val;760else761Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow), false);762break;763case tok::lessequal:764Res = LHS.Val <= RHS.Val;765Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)766break;767case tok::less:768Res = LHS.Val < RHS.Val;769Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)770break;771case tok::greaterequal:772Res = LHS.Val >= RHS.Val;773Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)774break;775case tok::greater:776Res = LHS.Val > RHS.Val;777Res.setIsUnsigned(false); // C99 6.5.8p6, result is always int (signed)778break;779case tok::exclaimequal:780Res = LHS.Val != RHS.Val;781Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)782break;783case tok::equalequal:784Res = LHS.Val == RHS.Val;785Res.setIsUnsigned(false); // C99 6.5.9p3, result is always int (signed)786break;787case tok::amp:788Res = LHS.Val & RHS.Val;789break;790case tok::caret:791Res = LHS.Val ^ RHS.Val;792break;793case tok::pipe:794Res = LHS.Val | RHS.Val;795break;796case tok::ampamp:797Res = (LHS.Val != 0 && RHS.Val != 0);798Res.setIsUnsigned(false); // C99 6.5.13p3, result is always int (signed)799break;800case tok::pipepipe:801Res = (LHS.Val != 0 || RHS.Val != 0);802Res.setIsUnsigned(false); // C99 6.5.14p3, result is always int (signed)803break;804case tok::comma:805// Comma is invalid in pp expressions in c89/c++ mode, but is valid in C99806// if not being evaluated.807if (!PP.getLangOpts().C99 || ValueLive)808PP.Diag(OpLoc, diag::ext_pp_comma_expr)809<< LHS.getRange() << RHS.getRange();810Res = RHS.Val; // LHS = LHS,RHS -> RHS.811break;812case tok::question: {813// Parse the : part of the expression.814if (PeekTok.isNot(tok::colon)) {815PP.Diag(PeekTok.getLocation(), diag::err_expected)816<< tok::colon << LHS.getRange() << RHS.getRange();817PP.Diag(OpLoc, diag::note_matching) << tok::question;818return true;819}820// Consume the :.821PP.LexNonComment(PeekTok);822823// Evaluate the value after the :.824bool AfterColonLive = ValueLive && LHS.Val == 0;825PPValue AfterColonVal(LHS.getBitWidth());826DefinedTracker DT;827if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))828return true;829830// Parse anything after the : with the same precedence as ?. We allow831// things of equal precedence because ?: is right associative.832if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec,833PeekTok, AfterColonLive,834IncludedUndefinedIds, PP))835return true;836837// Now that we have the condition, the LHS and the RHS of the :, evaluate.838Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;839RHS.setEnd(AfterColonVal.getRange().getEnd());840841// Usual arithmetic conversions (C99 6.3.1.8p1): result is unsigned if842// either operand is unsigned.843Res.setIsUnsigned(RHS.isUnsigned() || AfterColonVal.isUnsigned());844845// Figure out the precedence of the token after the : part.846PeekPrec = getPrecedence(PeekTok.getKind());847break;848}849case tok::colon:850// Don't allow :'s to float around without being part of ?: exprs.851PP.Diag(OpLoc, diag::err_pp_colon_without_question)852<< LHS.getRange() << RHS.getRange();853return true;854}855856// If this operator is live and overflowed, report the issue.857if (Overflow && ValueLive)858PP.Diag(OpLoc, diag::warn_pp_expr_overflow)859<< LHS.getRange() << RHS.getRange();860861// Put the result back into 'LHS' for our next iteration.862LHS.Val = Res;863LHS.setEnd(RHS.getRange().getEnd());864RHS.setIdentifier(nullptr);865}866}867868/// EvaluateDirectiveExpression - Evaluate an integer constant expression that869/// may occur after a #if or #elif directive. If the expression is equivalent870/// to "!defined(X)" return X in IfNDefMacro.871Preprocessor::DirectiveEvalResult872Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,873Token &Tok, bool &EvaluatedDefined,874bool CheckForEoD) {875SaveAndRestore PPDir(ParsingIfOrElifDirective, true);876// Save the current state of 'DisableMacroExpansion' and reset it to false. If877// 'DisableMacroExpansion' is true, then we must be in a macro argument list878// in which case a directive is undefined behavior. We want macros to be able879// to recursively expand in order to get more gcc-list behavior, so we force880// DisableMacroExpansion to false and restore it when we're done parsing the881// expression.882bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;883DisableMacroExpansion = false;884885// Peek ahead one token.886LexNonComment(Tok);887888// C99 6.10.1p3 - All expressions are evaluated as intmax_t or uintmax_t.889unsigned BitWidth = getTargetInfo().getIntMaxTWidth();890891PPValue ResVal(BitWidth);892DefinedTracker DT;893SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(Tok.getLocation());894if (EvaluateValue(ResVal, Tok, DT, true, *this)) {895// Parse error, skip the rest of the macro line.896SourceRange ConditionRange = ExprStartLoc;897if (Tok.isNot(tok::eod))898ConditionRange = DiscardUntilEndOfDirective(Tok);899900// Restore 'DisableMacroExpansion'.901DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;902903// We cannot trust the source range from the value because there was a904// parse error. Track the range manually -- the end of the directive is the905// end of the condition range.906return {std::nullopt,907false,908DT.IncludedUndefinedIds,909{ExprStartLoc, ConditionRange.getEnd()}};910}911912EvaluatedDefined = DT.State != DefinedTracker::Unknown;913914// If we are at the end of the expression after just parsing a value, there915// must be no (unparenthesized) binary operators involved, so we can exit916// directly.917if (Tok.is(tok::eod)) {918// If the expression we parsed was of the form !defined(macro), return the919// macro in IfNDefMacro.920if (DT.State == DefinedTracker::NotDefinedMacro)921IfNDefMacro = DT.TheMacro;922923// Restore 'DisableMacroExpansion'.924DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;925bool IsNonZero = ResVal.Val != 0;926SourceRange ValRange = ResVal.getRange();927return {std::move(ResVal.Val), IsNonZero, DT.IncludedUndefinedIds,928ValRange};929}930931// Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the932// operator and the stuff after it.933if (EvaluateDirectiveSubExpr(ResVal, getPrecedence(tok::question),934Tok, true, DT.IncludedUndefinedIds, *this)) {935// Parse error, skip the rest of the macro line.936if (Tok.isNot(tok::eod))937DiscardUntilEndOfDirective(Tok);938939// Restore 'DisableMacroExpansion'.940DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;941SourceRange ValRange = ResVal.getRange();942return {std::nullopt, false, DT.IncludedUndefinedIds, ValRange};943}944945if (CheckForEoD) {946// If we aren't at the tok::eod token, something bad happened, like an extra947// ')' token.948if (Tok.isNot(tok::eod)) {949Diag(Tok, diag::err_pp_expected_eol);950DiscardUntilEndOfDirective(Tok);951}952}953954EvaluatedDefined = EvaluatedDefined || DT.State != DefinedTracker::Unknown;955956// Restore 'DisableMacroExpansion'.957DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;958bool IsNonZero = ResVal.Val != 0;959SourceRange ValRange = ResVal.getRange();960return {std::move(ResVal.Val), IsNonZero, DT.IncludedUndefinedIds, ValRange};961}962963Preprocessor::DirectiveEvalResult964Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,965bool CheckForEoD) {966Token Tok;967bool EvaluatedDefined;968return EvaluateDirectiveExpression(IfNDefMacro, Tok, EvaluatedDefined,969CheckForEoD);970}971972973