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)) {
256 if (II->
isStr(
"defined"))
264 unsigned DiagID = II->
getName() ==
"true"
265 ? diag::warn_pp_undef_true_identifier
266 : diag::warn_pp_undef_identifier;
267 PP.
Diag(PeekTok, DiagID) << II;
272 const std::vector<std::string> UndefPrefixes =
274 const StringRef IdentifierName = II->
getName();
275 if (llvm::any_of(UndefPrefixes,
276 [&IdentifierName](
const std::string &Prefix) {
277 return IdentifierName.starts_with(Prefix);
279 PP.
Diag(PeekTok, diag::warn_pp_undef_prefix)
284 Result.Val.setIsUnsigned(
false);
292 PP.
Diag(PeekTok, diag::err_pp_expr_bad_token_start_expr);
297 PP.
Diag(PeekTok, diag::err_pp_expected_value_in_expr);
299 case tok::numeric_constant: {
301 bool NumberInvalid =
false;
302 StringRef Spelling = PP.
getSpelling(PeekTok, IntegerBuffer,
310 if (Literal.hadError)
313 if (Literal.isFloatingLiteral() || Literal.isImaginary) {
314 PP.
Diag(PeekTok, diag::err_pp_illegal_floating_literal);
317 assert(Literal.isIntegerLiteral() &&
"Unknown ppnumber");
320 if (Literal.hasUDSuffix())
321 PP.
Diag(PeekTok, diag::err_pp_invalid_udl) << 1;
328 diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
330 PP.
Diag(PeekTok, diag::ext_c99_longlong);
334 if (Literal.isSizeT) {
336 PP.
DiagCompat(PeekTok, diag_compat::size_t_suffix);
338 PP.
Diag(PeekTok, diag::err_cxx23_size_t_suffix);
344 if (Literal.isBitInt)
345 PP.
Diag(PeekTok, PP.
getLangOpts().CPlusPlus ? diag::ext_cxx_bitint_suffix
347 ? diag::warn_c23_compat_bitint_suffix
348 : diag::ext_c23_bitint_suffix);
351 if (Literal.GetIntegerValue(
Result.Val)) {
353 PP.
Diag(PeekTok, diag::err_integer_literal_too_large) << 1;
354 Result.Val.setIsUnsigned(
true);
358 Result.Val.setIsUnsigned(Literal.isUnsigned);
364 if (!Literal.isUnsigned &&
Result.Val.isNegative()) {
367 if (ValueLive && Literal.getRadix() == 10)
368 PP.
Diag(PeekTok, diag::ext_integer_literal_too_large_for_signed);
369 Result.Val.setIsUnsigned(
true);
378 case tok::char_constant:
379 case tok::wide_char_constant:
380 case tok::utf8_char_constant:
381 case tok::utf16_char_constant:
382 case tok::utf32_char_constant: {
385 PP.
Diag(PeekTok, diag::err_pp_invalid_udl) << 0;
388 bool CharInvalid =
false;
389 StringRef ThisTok = PP.
getSpelling(PeekTok, CharBuffer, &CharInvalid);
395 if (Literal.hadError())
401 if (Literal.isMultiChar())
403 else if (Literal.isWide())
405 else if (Literal.isUTF16())
407 else if (Literal.isUTF32())
413 llvm::APSInt Val(NumBits);
415 Val = Literal.getValue();
418 if (Literal.isWide())
420 else if (Literal.isUTF16() || Literal.isUTF32())
421 Val.setIsUnsigned(
true);
422 else if (Literal.isUTF8()) {
427 Val.setIsUnsigned(
true);
431 if (
Result.Val.getBitWidth() > Val.getBitWidth()) {
434 assert(
Result.Val.getBitWidth() == Val.getBitWidth() &&
435 "intmax_t smaller than char/wchar_t?");
436 Result.Val = std::move(Val);
453 if (PeekTok.
is(tok::r_paren)) {
461 if (PeekTok.
isNot(tok::r_paren)) {
464 PP.
Diag(Start, diag::note_matching) << tok::l_paren;
470 Result.setIdentifier(
nullptr);
480 Result.setIdentifier(
nullptr);
488 Result.setIdentifier(
nullptr);
494 bool Overflow = !
Result.isUnsigned() &&
Result.Val.isMinSignedValue();
497 if (Overflow && ValueLive)
498 PP.
Diag(Loc, diag::warn_pp_expr_overflow) <<
Result.getRange();
509 Result.setIdentifier(
nullptr);
524 Result.Val.setIsUnsigned(
false);
525 Result.setIdentifier(
nullptr);
536 Result.Val.setIsUnsigned(
false);
556 case tok::star:
return 14;
558 case tok::minus:
return 13;
560 case tok::greatergreater:
return 12;
563 case tok::greaterequal:
564 case tok::greater:
return 11;
565 case tok::exclaimequal:
566 case tok::equalequal:
return 10;
567 case tok::amp:
return 9;
568 case tok::caret:
return 8;
569 case tok::pipe:
return 7;
570 case tok::ampamp:
return 6;
571 case tok::pipepipe:
return 5;
572 case tok::question:
return 4;
573 case tok::comma:
return 3;
574 case tok::colon:
return 2;
575 case tok::r_paren:
return 0;
576 case tok::eod:
return 0;
582 if (
Tok.is(tok::l_paren) && LHS.getIdentifier())
583 PP.
Diag(LHS.getRange().getBegin(), diag::err_pp_expr_bad_token_lparen)
584 << LHS.getIdentifier();
586 PP.
Diag(
Tok.getLocation(), diag::err_pp_expr_bad_token_binop)
597 Token &PeekTok,
bool ValueLive,
598 bool &IncludedUndefinedIds,
602 IncludedUndefinedIds) {
609 if (PeekTok.
isNot(tok::eod))
616 if (PeekPrec == ~0
U) {
624 if (PeekPrec < MinPrec)
635 if (Operator == tok::ampamp && LHS.Val == 0)
637 else if (Operator == tok::pipepipe && LHS.Val != 0)
639 else if (Operator == tok::question && LHS.Val == 0)
642 RHSIsLive = ValueLive;
648 PPValue RHS(LHS.getBitWidth());
651 if (
EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP))
return true;
656 unsigned ThisPrec = PeekPrec;
660 if (PeekPrec == ~0
U) {
676 if (Operator == tok::question)
680 RHSPrec = ThisPrec+1;
682 if (PeekPrec >= RHSPrec) {
684 IncludedUndefinedIds, PP))
688 assert(PeekPrec <= ThisPrec &&
"Recursion didn't work!");
692 llvm::APSInt Res(LHS.getBitWidth());
696 case tok::greatergreater:
702 Res.setIsUnsigned(LHS.isUnsigned() || RHS.isUnsigned());
705 if (ValueLive && Res.isUnsigned()) {
706 if (!LHS.isUnsigned() && LHS.Val.isNegative())
707 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 0
708 <<
toString(LHS.Val, 10,
true) +
" to " +
710 << LHS.getRange() << RHS.getRange();
711 if (!RHS.isUnsigned() && RHS.Val.isNegative())
712 PP.
Diag(OpLoc, diag::warn_pp_convert_to_positive) << 1
713 <<
toString(RHS.Val, 10,
true) +
" to " +
715 << LHS.getRange() << RHS.getRange();
717 LHS.Val.setIsUnsigned(Res.isUnsigned());
718 RHS.Val.setIsUnsigned(Res.isUnsigned());
721 bool Overflow =
false;
723 default: llvm_unreachable(
"Unknown operator token!");
726 Res = LHS.Val % RHS.Val;
727 else if (ValueLive) {
728 PP.
Diag(OpLoc, diag::err_pp_remainder_by_zero)
729 << LHS.getRange() << RHS.getRange();
735 if (LHS.Val.isSigned())
736 Res = llvm::APSInt(LHS.Val.sdiv_ov(RHS.Val, Overflow),
false);
738 Res = LHS.Val / RHS.Val;
739 }
else if (ValueLive) {
740 PP.
Diag(OpLoc, diag::err_pp_division_by_zero)
741 << LHS.getRange() << RHS.getRange();
748 Res = llvm::APSInt(LHS.Val.smul_ov(RHS.Val, Overflow),
false);
750 Res = LHS.Val * RHS.Val;
752 case tok::lessless: {
754 if (LHS.isUnsigned())
755 Res = LHS.Val.ushl_ov(RHS.Val, Overflow);
757 Res = llvm::APSInt(LHS.Val.sshl_ov(RHS.Val, Overflow),
false);
760 case tok::greatergreater: {
762 unsigned ShAmt =
static_cast<unsigned>(RHS.Val.getLimitedValue());
763 if (ShAmt >= LHS.getBitWidth()) {
765 ShAmt = LHS.getBitWidth()-1;
767 Res = LHS.Val >> ShAmt;
771 if (LHS.isUnsigned())
772 Res = LHS.Val + RHS.Val;
774 Res = llvm::APSInt(LHS.Val.sadd_ov(RHS.Val, Overflow),
false);
777 if (LHS.isUnsigned())
778 Res = LHS.Val - RHS.Val;
780 Res = llvm::APSInt(LHS.Val.ssub_ov(RHS.Val, Overflow),
false);
783 Res = LHS.Val <= RHS.Val;
784 Res.setIsUnsigned(
false);
787 Res = LHS.Val < RHS.Val;
788 Res.setIsUnsigned(
false);
790 case tok::greaterequal:
791 Res = LHS.Val >= RHS.Val;
792 Res.setIsUnsigned(
false);
795 Res = LHS.Val > RHS.Val;
796 Res.setIsUnsigned(
false);
798 case tok::exclaimequal:
799 Res = LHS.Val != RHS.Val;
800 Res.setIsUnsigned(
false);
802 case tok::equalequal:
803 Res = LHS.Val == RHS.Val;
804 Res.setIsUnsigned(
false);
807 Res = LHS.Val & RHS.Val;
810 Res = LHS.Val ^ RHS.Val;
813 Res = LHS.Val | RHS.Val;
816 Res = (LHS.Val != 0 && RHS.Val != 0);
817 Res.setIsUnsigned(
false);
820 Res = (LHS.Val != 0 || RHS.Val != 0);
821 Res.setIsUnsigned(
false);
827 PP.
Diag(OpLoc, diag::ext_pp_comma_expr)
828 << LHS.getRange() << RHS.getRange();
831 case tok::question: {
833 if (PeekTok.
isNot(tok::colon)) {
835 << tok::colon << LHS.getRange() << RHS.getRange();
836 PP.
Diag(OpLoc, diag::note_matching) << tok::question;
843 bool AfterColonLive = ValueLive && LHS.Val == 0;
844 PPValue AfterColonVal(LHS.getBitWidth());
846 if (
EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
852 PeekTok, AfterColonLive,
853 IncludedUndefinedIds, PP))
857 Res = LHS.Val != 0 ? RHS.Val : AfterColonVal.Val;
858 RHS.setEnd(AfterColonVal.getRange().getEnd());
862 Res.setIsUnsigned(RHS.isUnsigned() || AfterColonVal.isUnsigned());
870 PP.
Diag(OpLoc, diag::err_pp_colon_without_question)
871 << LHS.getRange() << RHS.getRange();
876 if (Overflow && ValueLive)
877 PP.
Diag(OpLoc, diag::warn_pp_expr_overflow)
878 << LHS.getRange() << RHS.getRange();
882 LHS.setEnd(RHS.getRange().getEnd());
883 RHS.setIdentifier(
nullptr);
890Preprocessor::DirectiveEvalResult
891Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
894 SaveAndRestore PPDir(ParsingIfOrElifDirective,
true);
901 bool DisableMacroExpansionAtStartOfDirective = DisableMacroExpansion;
902 DisableMacroExpansion =
false;
910 PPValue ResVal(BitWidth);
912 SourceLocation ExprStartLoc = SourceMgr.getExpansionLoc(
Tok.
getLocation());
919 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
924 return {std::nullopt,
935 if (
Tok.
is(tok::eod)) {
942 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
943 bool IsNonZero = ResVal.Val != 0;
944 SourceRange ValRange = ResVal.getRange();
958 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
959 return {std::nullopt,
969 Diag(
Tok, diag::err_pp_expected_eol);
977 DisableMacroExpansion = DisableMacroExpansionAtStartOfDirective;
978 bool IsNonZero = ResVal.Val != 0;
979 SourceRange ValRange = ResVal.getRange();
983Preprocessor::DirectiveEvalResult
984Preprocessor::EvaluateDirectiveExpression(
IdentifierInfo *&IfNDefMacro,
987 bool EvaluatedDefined;
988 return EvaluateDirectiveExpression(IfNDefMacro,
Tok, EvaluatedDefined,
992static std::optional<CXXStandardLibraryVersionInfo>
999 const Token &RevisionDateTok =
Macro->getReplacementToken(0);
1003 llvm::StringRef RevisionDate =
1006 std::uint64_t
Value;
1008 if (!RevisionDate.consumeInteger(10,
Value))
1016 if (!CXXStandardLibraryVersion)
1019 if (!CXXStandardLibraryVersion)
1020 return std::nullopt;
1022 if (CXXStandardLibraryVersion->Lib ==
1024 return CXXStandardLibraryVersion->Version;
1025 return std::nullopt;
1029 CXXStandardLibraryVersion = {
1036 assert(FixedVersion >= 2000'00'00 && FixedVersion <= 2100'00'00 &&
1037 "invalid value for __GLIBCXX__");
1041 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 isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
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