aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Lex/PPExpressions.cpp
diff options
context:
space:
mode:
authorcor3ntin <corentinjabot@gmail.com>2025-05-31 12:26:49 +0200
committerGitHub <noreply@github.com>2025-05-31 12:26:49 +0200
commit6f7268e204ed0a2c014324828e0582d90e8fcd04 (patch)
tree9a9913211ff75b1eb91f129e814dd31d6c43aa50 /clang/lib/Lex/PPExpressions.cpp
parent3a989344741949be04bc2512a4633edc1c0e69d6 (diff)
downloadllvm-6f7268e204ed0a2c014324828e0582d90e8fcd04.zip
llvm-6f7268e204ed0a2c014324828e0582d90e8fcd04.tar.gz
llvm-6f7268e204ed0a2c014324828e0582d90e8fcd04.tar.bz2
[Clang] Improve infrastructure for libstdc++ workarounds (#141977)
This introduces a way detect the libstdc++ version, use that to enable workarounds. The version is cached. This should make it easier in the future to find and remove these hacks. I did not find the need for enabling a hack between or after specific versions, so it's left as a future exercise. We can extend this fature to other libraries as the need arise.
Diffstat (limited to 'clang/lib/Lex/PPExpressions.cpp')
-rw-r--r--clang/lib/Lex/PPExpressions.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/lib/Lex/PPExpressions.cpp b/clang/lib/Lex/PPExpressions.cpp
index cf7e32b..118d4ae 100644
--- a/clang/lib/Lex/PPExpressions.cpp
+++ b/clang/lib/Lex/PPExpressions.cpp
@@ -979,3 +979,49 @@ Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,
return EvaluateDirectiveExpression(IfNDefMacro, Tok, EvaluatedDefined,
CheckForEoD);
}
+
+static std::optional<CXXStandardLibraryVersionInfo>
+getCXXStandardLibraryVersion(Preprocessor &PP, StringRef MacroName,
+ CXXStandardLibraryVersionInfo::Library Lib) {
+ MacroInfo *Macro = PP.getMacroInfo(PP.getIdentifierInfo(MacroName));
+
+ if (!Macro || Macro->getNumTokens() != 1 || !Macro->isObjectLike())
+ return std::nullopt;
+
+ const Token &RevisionDateTok = Macro->getReplacementToken(0);
+
+ bool Invalid = false;
+ llvm::SmallVector<char, 10> Buffer;
+ llvm::StringRef RevisionDate =
+ PP.getSpelling(RevisionDateTok, Buffer, &Invalid);
+ if (!Invalid) {
+ unsigned Value;
+ // We don't use NumericParser to avoid diagnostics
+ if (!RevisionDate.consumeInteger(10, Value))
+ return CXXStandardLibraryVersionInfo{Lib, Value};
+ }
+ return CXXStandardLibraryVersionInfo{CXXStandardLibraryVersionInfo::Unknown,
+ 0};
+}
+
+std::optional<unsigned> Preprocessor::getStdLibCxxVersion() {
+ if (!CXXStandardLibraryVersion)
+ CXXStandardLibraryVersion = getCXXStandardLibraryVersion(
+ *this, "__GLIBCXX__", CXXStandardLibraryVersionInfo::LibStdCXX);
+ if (!CXXStandardLibraryVersion)
+ return std::nullopt;
+
+ if (CXXStandardLibraryVersion->Lib ==
+ CXXStandardLibraryVersionInfo::LibStdCXX)
+ return CXXStandardLibraryVersion->Version;
+ return std::nullopt;
+}
+
+bool Preprocessor::NeedsStdLibCxxWorkaroundBefore(unsigned FixedVersion) {
+ assert(FixedVersion >= 2000'00'00 && FixedVersion <= 2100'00'00 &&
+ "invalid value for __GLIBCXX__");
+ std::optional<unsigned> Ver = getStdLibCxxVersion();
+ if (!Ver)
+ return false;
+ return *Ver < FixedVersion;
+}