31#include "llvm/ADT/APSInt.h"
32#include "llvm/ADT/STLExtras.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/ErrorHandling.h"
36#include "llvm/Support/SaveAndRestore.h"
53 PPValue(
unsigned BitWidth) : Val(BitWidth) {}
60 unsigned getBitWidth()
const {
return Val.getBitWidth(); }
61 bool isUnsigned()
const {
return Val.isUnsigned(); }
76 Token &PeekTok,
bool ValueLive,
77 bool &IncludedUndefinedIds,
105 Result.setBegin(beginLoc);
112 if (PeekTok.
is(tok::l_paren)) {
118 if (PeekTok.
is(tok::code_completion)) {
132 Result.Val = !!
Macro;
133 Result.Val.setIsUnsigned(
false);
138 (II->
getName() ==
"INFINITY" || II->
getName() ==
"NAN") ?
true :
false);
141 if (Result.Val != 0 && ValueLive)
145 Token macroToken(PeekTok);
153 if (PeekTok.
isNot(tok::r_paren)) {
155 <<
"'defined'" << tok::r_paren;
156 PP.
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
187 bool IsFunctionTypeMacro =
207 if (IsFunctionTypeMacro)
208 PP.
Diag(beginLoc, diag::warn_defined_in_function_type_macro);
210 PP.
Diag(beginLoc, diag::warn_defined_in_object_type_macro);
215 Callbacks->Defined(macroToken,
Macro,
237 Result.setIdentifier(
nullptr);
239 if (PeekTok.
is(tok::code_completion)) {
253 if (II->
isStr(
"defined"))
261 unsigned DiagID = II->
getName() ==
"true"
262 ? diag::warn_pp_undef_true_identifier
263 : diag::warn_pp_undef_identifier;
264 PP.
Diag(PeekTok, DiagID) << II;
269 const std::vector<std::string> UndefPrefixes =
271 const StringRef IdentifierName = II->
getName();
272 if (llvm::any_of(UndefPrefixes,
273 [&IdentifierName](
const std::string &Prefix) {
274 return IdentifierName.starts_with(Prefix);
276 PP.
Diag(PeekTok, diag::warn_pp_undef_prefix)
281 Result.Val.setIsUnsigned(
false);
282 Result.setIdentifier(II);
289 PP.
Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
294 PP.
Diag(PeekTok, diag::err_pp_expected_value_in_expr);
296 case tok::numeric_constant: {
298 bool NumberInvalid =
false;
299 StringRef Spelling = PP.
getSpelling(PeekTok, IntegerBuffer,
307 if (Literal.hadError)
310 if (Literal.isFloatingLiteral() || Literal.isImaginary) {
311 PP.
Diag(PeekTok, diag::err_pp_illegal_floating_literal);
314 assert(Literal.isIntegerLiteral() &&
"Unknown ppnumber");
317 if (Literal.hasUDSuffix())
318 PP.
Diag(PeekTok, diag::err_pp_invalid_udl) << 1;
325 diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
327 PP.
Diag(PeekTok, diag::ext_c99_longlong);
334 ? diag::warn_cxx20_compat_size_t_suffix
335 : diag::ext_cxx23_size_t_suffix
336 : diag::err_cxx23_size_t_suffix);
340 if (Literal.isBitInt)
341 PP.
Diag(PeekTok, PP.
getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
343 ? diag::warn_c23_compat_bitint_suffix
344 : diag::ext_c23_bitint_suffix);
347 if (Literal.GetIntegerValue(Result.Val)) {
349 PP.
Diag(PeekTok, diag::err_integer_literal_too_large) << 1;
350 Result.Val.setIsUnsigned(
true);
354 Result.Val.setIsUnsigned(Literal.isUnsigned);
360 if (!Literal.isUnsigned && Result.Val.isNegative()) {
363 if (ValueLive && Literal.getRadix() == 10)
364 PP.
Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);
365 Result.Val.setIsUnsigned(
true);
374 case tok::char_constant:
375 case tok::wide_char_constant:
376 case tok::utf8_char_constant:
377 case tok::utf16_char_constant:
378 case tok::utf32_char_constant: {
381 PP.
Diag(PeekTok, diag::err_pp_invalid_udl) << 0;
384 bool CharInvalid =
false;
385 StringRef ThisTok = PP.
getSpelling(PeekTok, CharBuffer, &CharInvalid);
391 if (Literal.hadError())
397 if (Literal.isMultiChar())
399 else if (Literal.isWide())
401 else if (Literal.isUTF16())
403 else if (Literal.isUTF32())
409 llvm::APSInt Val(NumBits);
411 Val = Literal.getValue();
414 if (Literal.isWide())
416 else if (Literal.isUTF16() || Literal.isUTF32())
417 Val.setIsUnsigned(
true);
418 else if (Literal.isUTF8()) {
423 Val.setIsUnsigned(
true);
427 if (Result.Val.getBitWidth() > Val.getBitWidth()) {
428 Result.Val = Val.extend(Result.Val.getBitWidth());
430 assert(Result.Val.getBitWidth() == Val.getBitWidth() &&
431 "intmax_t smaller than char/wchar_t?");
445 if (
EvaluateValue(Result, PeekTok, DT, ValueLive, PP))
return true;
449 if (PeekTok.
is(tok::r_paren)) {
457 if (PeekTok.
isNot(tok::r_paren)) {
459 << Result.getRange();
460 PP.
Diag(Start, diag::note_matching) << tok::l_paren;
466 Result.setIdentifier(
nullptr);
474 if (
EvaluateValue(Result, PeekTok, DT, ValueLive, PP))
return true;
475 Result.setBegin(Start);
476 Result.setIdentifier(
nullptr);
482 if (
EvaluateValue(Result, PeekTok, DT, ValueLive, PP))
return true;
483 Result.setBegin(
Loc);
484 Result.setIdentifier(
nullptr);
487 Result.Val = -Result.Val;
490 bool Overflow = !Result.isUnsigned() && Result.Val.isMinSignedValue();
493 if (Overflow && ValueLive)
494 PP.
Diag(
Loc, diag::warn_pp_expr_overflow) << Result.getRange();
503 if (
EvaluateValue(Result, PeekTok, DT, ValueLive, PP))
return true;
504 Result.setBegin(Start);
505 Result.setIdentifier(
nullptr);
508 Result.Val = ~Result.Val;
516 if (
EvaluateValue(Result, PeekTok, DT, ValueLive, PP))
return true;
517 Result.setBegin(Start);
518 Result.Val = !Result.Val;
520 Result.Val.setIsUnsigned(
false);
521 Result.setIdentifier(
nullptr);
531 Result.Val = PeekTok.
getKind() == tok::kw_true;
532 Result.Val.setIsUnsigned(
false);
552 case tok::star:
return 14;
554 case tok::minus:
return 13;
556 case tok::greatergreater:
return 12;
559 case tok::greaterequal:
560 case tok::greater:
return 11;
561 case tok::exclaimequal:
562 case tok::equalequal:
return 10;
563 case tok::amp:
return 9;
564 case tok::caret:
return 8;
565 case tok::pipe:
return 7;
566 case tok::ampamp:
return 6;
567 case tok::pipepipe:
return 5;
568 case tok::question:
return 4;
569 case tok::comma:
return 3;
570 case tok::colon:
return 2;
571 case tok::r_paren:
return 0;
572 case tok::eod:
return 0;
578 if (Tok.
is(tok::l_paren) && LHS.getIdentifier())
579 PP.
Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
580 << LHS.getIdentifier();
593 Token &PeekTok,
bool ValueLive,
594 bool &IncludedUndefinedIds,
607 if (PeekPrec == ~0
U) {
615 if (PeekPrec < MinPrec)
626 if (Operator == tok::ampamp && LHS.Val == 0)
628 else if (Operator == tok::pipepipe && LHS.Val != 0)
630 else if (Operator == tok::question && LHS.Val == 0)
633 RHSIsLive = ValueLive;
639 PPValue RHS(LHS.getBitWidth());
642 if (
EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP))
return true;
647 unsigned ThisPrec = PeekPrec;
651 if (PeekPrec == ~0
U) {
667 if (Operator == tok::question)
671 RHSPrec = ThisPrec+1;
673 if (PeekPrec >= RHSPrec) {
675 IncludedUndefinedIds, PP))
679 assert(PeekPrec <= ThisPrec &&
"Recursion didn't work!");
683 llvm::APSInt Res(LHS.getBitWidth());
687 case tok::greatergreater:
693 Res.setIsUnsigned(LHS.isUnsigned() || RHS.isUnsigned());
696 if (ValueLive && Res.isUnsigned()) {
697 if (!LHS.isUnsigned() && LHS.Val.isNegative())
698 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
699 <<
toString(LHS.Val, 10,
true) +
" to " +
701 << LHS.getRange() << RHS.getRange();
702 if (!RHS.isUnsigned() && RHS.Val.isNegative())
703 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
704 <<
toString(RHS.Val, 10,
true) +
" to " +
706 << LHS.getRange() << RHS.getRange();
708 LHS.Val.setIsUnsigned(Res.isUnsigned());
709 RHS.Val.setIsUnsigned(Res.isUnsigned());
712 bool Overflow =
false;
714 default: llvm_unreachable(
"Unknown operator token!");
717 Res = LHS.Val % RHS.Val;
718 else if (ValueLive) {
719 PP.
Diag(OpLoc, diag::err_pp_remainder_by_zero)
720 << LHS.getRange() << RHS.getRange();
726 if (LHS.Val.isSigned())
727 Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow),
false);
729 Res = LHS.Val / RHS.Val;
730 }
else if (ValueLive) {
731 PP.
Diag(OpLoc, diag::err_pp_division_by_zero)
732 << LHS.getRange() << RHS.getRange();
739 Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow),
false);
741 Res = LHS.Val * RHS.Val;
743 case tok::lessless: {
745 if (LHS.isUnsigned())
746 Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
748 Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow),
false);
751 case tok::greatergreater: {
753 unsigned ShAmt =
static_cast<unsigned>(RHS.Val.getLimitedValue());
754 if (ShAmt >= LHS.getBitWidth()) {
756 ShAmt = LHS.getBitWidth()-1;
758 Res = LHS.Val >> ShAmt;
762 if (LHS.isUnsigned())
763 Res = LHS.Val + RHS.Val;
765 Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow),
false);
768 if (LHS.isUnsigned())
769 Res = LHS.Val - RHS.Val;
771 Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow),
false);
774 Res = LHS.Val <= RHS.Val;
775 Res.setIsUnsigned(
false);
778 Res = LHS.Val < RHS.Val;
779 Res.setIsUnsigned(
false);
781 case tok::greaterequal:
782 Res = LHS.Val >= RHS.Val;
783 Res.setIsUnsigned(
false);
786 Res = LHS.Val > RHS.Val;
787 Res.setIsUnsigned(
false);
789 case tok::exclaimequal:
790 Res = LHS.Val != RHS.Val;
791 Res.setIsUnsigned(
false);
793 case tok::equalequal:
794 Res = LHS.Val == RHS.Val;
795 Res.setIsUnsigned(
false);
798 Res = LHS.Val & RHS.Val;
801 Res = LHS.Val ^ RHS.Val;
804 Res = LHS.Val | RHS.Val;
807 Res = (LHS.Val != 0 && RHS.Val != 0);
808 Res.setIsUnsigned(
false);
811 Res = (LHS.Val != 0 || RHS.Val != 0);
812 Res.setIsUnsigned(
false);
818 PP.
Diag(OpLoc, diag::ext_pp_comma_expr)
819 << LHS.getRange() << RHS.getRange();
822 case tok::question: {
824 if (PeekTok.
isNot(tok::colon)) {
826 << tok::colon << LHS.getRange() << RHS.getRange();
827 PP.
Diag(OpLoc, diag::note_matching) << tok::question;
834 bool AfterColonLive = ValueLive && LHS.Val == 0;
835 PPValue AfterColonVal(LHS.getBitWidth());
837 if (
EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
843 PeekTok, AfterColonLive,
844 IncludedUndefinedIds, PP))
848 Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
849 RHS.setEnd(AfterColonVal.getRange().getEnd());
853 Res.setIsUnsigned(RHS.isUnsigned() || AfterColonVal.isUnsigned());
861 PP.
Diag(OpLoc, diag::err_pp_colon_without_question)
862 << LHS.getRange() << RHS.getRange();
867 if (Overflow && ValueLive)
868 PP.
Diag(OpLoc, diag::warn_pp_expr_overflow)
869 << LHS.getRange() << RHS.getRange();
873 LHS.setEnd(RHS.getRange().getEnd());
874 RHS.setIdentifier(
nullptr);
881Preprocessor::DirectiveEvalResult
882Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
883 Token &Tok,
bool &EvaluatedDefined,
892 bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
893 DisableMacroExpansion =
false;
901 PPValue ResVal(BitWidth);
906 if (Tok.
isNot(tok::eod))
910 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
915 return {std::nullopt,
926 if (Tok.
is(tok::eod)) {
933 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
934 bool IsNonZero = ResVal.Val != 0;
945 if (Tok.
isNot(tok::eod))
949 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
950 return {std::nullopt,
959 if (Tok.
isNot(tok::eod)) {
960 Diag(Tok, diag::err_pp_expected_eol);
968 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
969 bool IsNonZero = ResVal.Val != 0;
974Preprocessor::DirectiveEvalResult
975Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
978 bool EvaluatedDefined;
979 return EvaluateDirectiveExpression(IfNDefMacro, Tok, EvaluatedDefined,
983static std::optional<CXXStandardLibraryVersionInfo>
990 const Token &RevisionDateTok =
Macro->getReplacementToken(0);
994 llvm::StringRef RevisionDate =
999 if (!RevisionDate.consumeInteger(10,
Value))
1007 if (!CXXStandardLibraryVersion)
1010 if (!CXXStandardLibraryVersion)
1011 return std::nullopt;
1013 if (CXXStandardLibraryVersion->Lib ==
1015 return CXXStandardLibraryVersion->Version;
1016 return std::nullopt;
1020 assert(FixedVersion >= 2000'00'00 && FixedVersion <= 2100'00'00 &&
1021 "invalid value for __GLIBCXX__");
1025 return *Ver < FixedVersion;
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::MacroInfo and clang::MacroDirective classes.
Defines the PPCallbacks interface.
static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP)
EvaluateValue - Evaluate the token PeekTok (and any others needed) and return the computed value in R...
static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS, Token &Tok)
static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, bool &IncludedUndefinedIds, Preprocessor &PP)
EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is PeekTok,...
static std::optional< CXXStandardLibraryVersionInfo > getCXXStandardLibraryVersion(Preprocessor &PP, StringRef MacroName, CXXStandardLibraryVersionInfo::Library Lib)
static unsigned getPrecedence(tok::TokenKind Kind)
getPrecedence - Return the precedence of the specified binary operator token.
static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP)
EvaluateDefined - Process a 'defined(sym)' expression.
static StringRef getIdentifier(const Token &Tok)
Defines the clang::Preprocessor interface.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
CharLiteralParser - Perform interpretation and semantic analysis of a character literal.
virtual void CodeCompleteMacroName(bool IsDefinition)
Callback invoked when performing code completion in a context where the name of a macro is expected.
virtual void CodeCompletePreprocessorExpression()
Callback invoked when performing code completion in a preprocessor expression, such as the condition ...
std::vector< std::string > UndefPrefixes
The list of prefixes from -Wundef-prefix=... used to generate warnings for undefined macros.
Concrete class used by the front-end to report problems and issues.
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
One of these records is kept for each identifier that is lexed.
bool isCPlusPlusOperatorKeyword() const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
A description of the current definition of a macro.
Encapsulates the data about a macro definition (e.g.
NumericLiteralParser - This performs strict semantic analysis of the content of a ppnumber,...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
bool SingleFileParseMode
When enabled, preprocessor is in a mode for parsing a single file only.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
PPCallbacks * getPPCallbacks() const
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
void markMacroAsUsed(MacroInfo *MI)
A macro is used, update information about macros that need unused warnings.
void setCodeCompletionReached()
Note that we hit the code-completion point.
void LexNonComment(Token &Result)
Lex a token.
SourceRange DiscardUntilEndOfDirective()
Read and discard all tokens remaining on the current line until the tok::eod token is found.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
SourceManager & getSourceManager() const
MacroDefinition getMacroDefinition(const IdentifierInfo *II)
bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, bool *ShadowFlag=nullptr)
std::optional< std::uint64_t > getStdLibCxxVersion()
const TargetInfo & getTargetInfo() const
void LexUnexpandedNonComment(Token &Result)
Like LexNonComment, but this disables macro expansion of identifier tokens.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
void emitMacroExpansionWarnings(const Token &Identifier, bool IsIfnDef=false) const
bool NeedsStdLibCxxWorkaroundBefore(std::uint64_t FixedVersion)
CodeCompletionHandler * getCodeCompletionHandler() const
Retrieve the current code-completion handler.
const PreprocessorOptions & getPreprocessorOpts() const
Retrieve the preprocessor options used to initialize this preprocessor.
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const
Forwarding function for diagnostics.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
void setEnd(SourceLocation e)
bool isFunctionMacroExpansion() const
const ExpansionInfo & getExpansion() const
Exposes information about the current target.
unsigned getChar32Width() const
getChar32Width/Align - Return the size of 'char32_t' for this target, in bits.
static bool isTypeSigned(IntType T)
Returns true if the type is signed; false otherwise.
unsigned getChar16Width() const
getChar16Width/Align - Return the size of 'char16_t' for this target, in bits.
unsigned getIntWidth() const
getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for this target,...
IntType getWCharType() const
unsigned getWCharWidth() const
getWCharWidth/Align - Return the size of 'wchar_t' for this target, in bits.
unsigned getIntMaxTWidth() const
Return the size of intmax_t and uintmax_t for this target, in bits.
unsigned getCharWidth() const
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isNot(tok::TokenKind K) const
bool hasUDSuffix() const
Return true if this token is a string or character literal which has a ud-suffix.
Defines the clang::TargetInfo interface.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
The JSON file list parser is used to communicate input to InstallAPI.
DefinedTracker - This struct is used while parsing expressions to keep track of whether !...
TrackerState
Each time a Value is evaluated, it returns information about whether the parsed value is of the form ...
bool IncludedUndefinedIds
IdentifierInfo * TheMacro
TheMacro - When the state is DefinedMacro or NotDefinedMacro, this indicates the macro that was check...
enum DefinedTracker::TrackerState State