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"
47 IdentifierInfo *II =
nullptr;
53 PPValue(
unsigned BitWidth) : Val(BitWidth) {}
58 void setIdentifier(IdentifierInfo *II) { this->II = II; }
60 unsigned getBitWidth()
const {
return Val.getBitWidth(); }
61 bool isUnsigned()
const {
return Val.isUnsigned(); }
63 SourceRange
getRange()
const {
return Range; }
65 void setRange(SourceLocation L) { Range.
setBegin(L); Range.setEnd(L); }
66 void setRange(SourceLocation B, SourceLocation E) {
67 Range.setBegin(B); Range.setEnd(E);
69 void setBegin(SourceLocation L) { Range.setBegin(L); }
70 void setEnd(SourceLocation L) { Range.setEnd(L); }
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)) {
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);
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);
331 if (Literal.isSizeT) {
333 PP.
DiagCompat(PeekTok, diag_compat::size_t_suffix);
335 PP.
Diag(PeekTok, diag::err_cxx23_size_t_suffix);
341 if (Literal.isBitInt)
342 PP.
Diag(PeekTok, PP.
getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
344 ? diag::warn_c23_compat_bitint_suffix
345 : diag::ext_c23_bitint_suffix);
348 if (Literal.GetIntegerValue(
Result.Val)) {
350 PP.
Diag(PeekTok, diag::err_integer_literal_too_large) << 1;
351 Result.Val.setIsUnsigned(
true);
355 Result.Val.setIsUnsigned(Literal.isUnsigned);
361 if (!Literal.isUnsigned &&
Result.Val.isNegative()) {
364 if (ValueLive && Literal.getRadix() == 10)
365 PP.
Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);
366 Result.Val.setIsUnsigned(
true);
375 case tok::char_constant:
376 case tok::wide_char_constant:
377 case tok::utf8_char_constant:
378 case tok::utf16_char_constant:
379 case tok::utf32_char_constant: {
382 PP.
Diag(PeekTok, diag::err_pp_invalid_udl) << 0;
385 bool CharInvalid =
false;
386 StringRef ThisTok = PP.
getSpelling(PeekTok, CharBuffer, &CharInvalid);
392 if (Literal.hadError())
398 if (Literal.isMultiChar())
400 else if (Literal.isWide())
402 else if (Literal.isUTF16())
404 else if (Literal.isUTF32())
410 llvm::APSInt Val(NumBits);
412 Val = Literal.getValue();
415 if (Literal.isWide())
417 else if (Literal.isUTF16() || Literal.isUTF32())
418 Val.setIsUnsigned(
true);
419 else if (Literal.isUTF8()) {
424 Val.setIsUnsigned(
true);
428 if (
Result.Val.getBitWidth() > Val.getBitWidth()) {
431 assert(
Result.Val.getBitWidth() == Val.getBitWidth() &&
432 "intmax_t smaller than char/wchar_t?");
433 Result.Val = std::move(Val);
450 if (PeekTok.
is(tok::r_paren)) {
458 if (PeekTok.
isNot(tok::r_paren)) {
461 PP.
Diag(Start, diag::note_matching) << tok::l_paren;
467 Result.setIdentifier(
nullptr);
477 Result.setIdentifier(
nullptr);
485 Result.setIdentifier(
nullptr);
491 bool Overflow = !
Result.isUnsigned() &&
Result.Val.isMinSignedValue();
494 if (Overflow && ValueLive)
495 PP.
Diag(Loc, diag::warn_pp_expr_overflow) <<
Result.getRange();
506 Result.setIdentifier(
nullptr);
521 Result.Val.setIsUnsigned(
false);
522 Result.setIdentifier(
nullptr);
533 Result.Val.setIsUnsigned(
false);
553 case tok::star:
return 14;
555 case tok::minus:
return 13;
557 case tok::greatergreater:
return 12;
560 case tok::greaterequal:
561 case tok::greater:
return 11;
562 case tok::exclaimequal:
563 case tok::equalequal:
return 10;
564 case tok::amp:
return 9;
565 case tok::caret:
return 8;
566 case tok::pipe:
return 7;
567 case tok::ampamp:
return 6;
568 case tok::pipepipe:
return 5;
569 case tok::question:
return 4;
570 case tok::comma:
return 3;
571 case tok::colon:
return 2;
572 case tok::r_paren:
return 0;
573 case tok::eod:
return 0;
579 if (
Tok.is(tok::l_paren) && LHS.getIdentifier())
580 PP.
Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
581 << LHS.getIdentifier();
583 PP.
Diag(
Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
594 Token &PeekTok,
bool ValueLive,
595 bool &IncludedUndefinedIds,
599 IncludedUndefinedIds) {
610 if (PeekPrec == ~0
U) {
618 if (PeekPrec < MinPrec)
629 if (Operator == tok::ampamp && LHS.Val == 0)
631 else if (Operator == tok::pipepipe && LHS.Val != 0)
633 else if (Operator == tok::question && LHS.Val == 0)
636 RHSIsLive = ValueLive;
642 PPValue RHS(LHS.getBitWidth());
645 if (
EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP))
return true;
650 unsigned ThisPrec = PeekPrec;
654 if (PeekPrec == ~0
U) {
670 if (Operator == tok::question)
674 RHSPrec = ThisPrec+1;
676 if (PeekPrec >= RHSPrec) {
678 IncludedUndefinedIds, PP))
682 assert(PeekPrec <= ThisPrec &&
"Recursion didn't work!");
686 llvm::APSInt Res(LHS.getBitWidth());
690 case tok::greatergreater:
696 Res.setIsUnsigned(LHS.isUnsigned() || RHS.isUnsigned());
699 if (ValueLive && Res.isUnsigned()) {
700 if (!LHS.isUnsigned() && LHS.Val.isNegative())
701 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
702 <<
toString(LHS.Val, 10,
true) +
" to " +
704 << LHS.getRange() << RHS.getRange();
705 if (!RHS.isUnsigned() && RHS.Val.isNegative())
706 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
707 <<
toString(RHS.Val, 10,
true) +
" to " +
709 << LHS.getRange() << RHS.getRange();
711 LHS.Val.setIsUnsigned(Res.isUnsigned());
712 RHS.Val.setIsUnsigned(Res.isUnsigned());
715 bool Overflow =
false;
717 default: llvm_unreachable(
"Unknown operator token!");
720 Res = LHS.Val % RHS.Val;
721 else if (ValueLive) {
722 PP.
Diag(OpLoc, diag::err_pp_remainder_by_zero)
723 << LHS.getRange() << RHS.getRange();
729 if (LHS.Val.isSigned())
730 Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow),
false);
732 Res = LHS.Val / RHS.Val;
733 }
else if (ValueLive) {
734 PP.
Diag(OpLoc, diag::err_pp_division_by_zero)
735 << LHS.getRange() << RHS.getRange();
742 Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow),
false);
744 Res = LHS.Val * RHS.Val;
746 case tok::lessless: {
748 if (LHS.isUnsigned())
749 Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
751 Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow),
false);
754 case tok::greatergreater: {
756 unsigned ShAmt =
static_cast<unsigned>(RHS.Val.getLimitedValue());
757 if (ShAmt >= LHS.getBitWidth()) {
759 ShAmt = LHS.getBitWidth()-1;
761 Res = LHS.Val >> ShAmt;
765 if (LHS.isUnsigned())
766 Res = LHS.Val + RHS.Val;
768 Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow),
false);
771 if (LHS.isUnsigned())
772 Res = LHS.Val - RHS.Val;
774 Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow),
false);
777 Res = LHS.Val <= RHS.Val;
778 Res.setIsUnsigned(
false);
781 Res = LHS.Val < RHS.Val;
782 Res.setIsUnsigned(
false);
784 case tok::greaterequal:
785 Res = LHS.Val >= RHS.Val;
786 Res.setIsUnsigned(
false);
789 Res = LHS.Val > RHS.Val;
790 Res.setIsUnsigned(
false);
792 case tok::exclaimequal:
793 Res = LHS.Val != RHS.Val;
794 Res.setIsUnsigned(
false);
796 case tok::equalequal:
797 Res = LHS.Val == RHS.Val;
798 Res.setIsUnsigned(
false);
801 Res = LHS.Val & RHS.Val;
804 Res = LHS.Val ^ RHS.Val;
807 Res = LHS.Val | RHS.Val;
810 Res = (LHS.Val != 0 && RHS.Val != 0);
811 Res.setIsUnsigned(
false);
814 Res = (LHS.Val != 0 || RHS.Val != 0);
815 Res.setIsUnsigned(
false);
821 PP.
Diag(OpLoc, diag::ext_pp_comma_expr)
822 << LHS.getRange() << RHS.getRange();
825 case tok::question: {
827 if (PeekTok.
isNot(tok::colon)) {
829 << tok::colon << LHS.getRange() << RHS.getRange();
830 PP.
Diag(OpLoc, diag::note_matching) << tok::question;
837 bool AfterColonLive = ValueLive && LHS.Val == 0;
838 PPValue AfterColonVal(LHS.getBitWidth());
840 if (
EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
846 PeekTok, AfterColonLive,
847 IncludedUndefinedIds, PP))
851 Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
852 RHS.setEnd(AfterColonVal.getRange().getEnd());
856 Res.setIsUnsigned(RHS.isUnsigned() || AfterColonVal.isUnsigned());
864 PP.
Diag(OpLoc, diag::err_pp_colon_without_question)
865 << LHS.getRange() << RHS.getRange();
870 if (Overflow && ValueLive)
871 PP.
Diag(OpLoc, diag::warn_pp_expr_overflow)
872 << LHS.getRange() << RHS.getRange();
876 LHS.setEnd(RHS.getRange().getEnd());
877 RHS.setIdentifier(
nullptr);
884Preprocessor::DirectiveEvalResult
885Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
888 SaveAndRestore PPDir(ParsingIfOrElifDirective,
true);
895 bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
896 DisableMacroExpansion =
false;
904 PPValue ResVal(BitWidth);
906 SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(
Tok.
getLocation());
913 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
918 return {std::nullopt,
929 if (
Tok.
is(tok::eod)) {
936 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
937 bool IsNonZero = ResVal.Val != 0;
938 SourceRange ValRange = ResVal.getRange();
952 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
953 return {std::nullopt,
963 Diag(
Tok, diag::err_pp_expected_eol);
971 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
972 bool IsNonZero = ResVal.Val != 0;
973 SourceRange ValRange = ResVal.getRange();
977Preprocessor::DirectiveEvalResult
978Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
981 bool EvaluatedDefined;
982 return EvaluateDirectiveExpression(IfNDefMacro,
Tok, EvaluatedDefined,
986static std::optional<CXXStandardLibraryVersionInfo>
993 const Token &RevisionDateTok =
Macro->getReplacementToken(0);
997 llvm::StringRef RevisionDate =
1000 std::uint64_t
Value;
1002 if (!RevisionDate.consumeInteger(10,
Value))
1010 if (!CXXStandardLibraryVersion)
1013 if (!CXXStandardLibraryVersion)
1014 return std::nullopt;
1016 if (CXXStandardLibraryVersion->Lib ==
1018 return CXXStandardLibraryVersion->Version;
1019 return std::nullopt;
1023 CXXStandardLibraryVersion = {
1030 assert(FixedVersion >= 2000'00'00 && FixedVersion <= 2100'00'00 &&
1031 "invalid value for __GLIBCXX__");
1035 return *Ver < FixedVersion;
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
static uint32_t getBitWidth(const Expr *E)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
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, IdentifierInfo *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.
void setBegin(SourceLocation b)
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.
bool SingleModuleParseMode
When enabled, preprocessor is in a mode for parsing a single module only.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void setStdLibCxxVersion(std::uint64_t Version)
PPCallbacks * getPPCallbacks() const
SourceRange DiscardUntilEndOfDirective(SmallVectorImpl< Token > *DiscardedToks=nullptr)
Read and discard all tokens remaining on the current line until the tok::eod token is found.
const MacroInfo * getMacroInfo(const IdentifierInfo *II) const
DiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagID) 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.
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.
const SrcMgr::SLocEntry & getSLocEntry(FileID FID, bool *Invalid=nullptr) const
A trivial tuple used to represent a source range.
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.
Top level wrappers for InstallAPI frontend operations.
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