Skip to content

Commit 4cff3be

Browse files
author
git apple-llvm automerger
committed
Merge commit '6f7268e204ed' from llvm.org/main into next
2 parents 02d0bbd + 6f7268e commit 4cff3be

10 files changed

+97
-46
lines changed

clang/include/clang/Lex/Preprocessor.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ enum class EmbedResult {
130130
Empty = 2, // Corresponds to __STDC_EMBED_EMPTY__
131131
};
132132

133+
struct CXXStandardLibraryVersionInfo {
134+
enum Library { Unknown, LibStdCXX };
135+
Library Lib;
136+
unsigned Version;
137+
};
138+
133139
/// Engages in a tight little dance with the lexer to efficiently
134140
/// preprocess tokens.
135141
///
@@ -2743,6 +2749,15 @@ class Preprocessor {
27432749
return IsFileLexer(CurLexer.get(), CurPPLexer);
27442750
}
27452751

2752+
//===--------------------------------------------------------------------===//
2753+
// Standard Library Identification
2754+
std::optional<CXXStandardLibraryVersionInfo> CXXStandardLibraryVersion;
2755+
2756+
public:
2757+
std::optional<unsigned> getStdLibCxxVersion();
2758+
bool NeedsStdLibCxxWorkaroundBefore(unsigned FixedVersion);
2759+
2760+
private:
27462761
//===--------------------------------------------------------------------===//
27472762
// Caching stuff.
27482763
void CachingLex(Token &Result);

clang/lib/Lex/PPExpressions.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,3 +979,49 @@ Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro,
979979
return EvaluateDirectiveExpression(IfNDefMacro, Tok, EvaluatedDefined,
980980
CheckForEoD);
981981
}
982+
983+
static std::optional<CXXStandardLibraryVersionInfo>
984+
getCXXStandardLibraryVersion(Preprocessor &PP, StringRef MacroName,
985+
CXXStandardLibraryVersionInfo::Library Lib) {
986+
MacroInfo *Macro = PP.getMacroInfo(PP.getIdentifierInfo(MacroName));
987+
988+
if (!Macro || Macro->getNumTokens() != 1 || !Macro->isObjectLike())
989+
return std::nullopt;
990+
991+
const Token &RevisionDateTok = Macro->getReplacementToken(0);
992+
993+
bool Invalid = false;
994+
llvm::SmallVector<char, 10> Buffer;
995+
llvm::StringRef RevisionDate =
996+
PP.getSpelling(RevisionDateTok, Buffer, &Invalid);
997+
if (!Invalid) {
998+
unsigned Value;
999+
// We don't use NumericParser to avoid diagnostics
1000+
if (!RevisionDate.consumeInteger(10, Value))
1001+
return CXXStandardLibraryVersionInfo{Lib, Value};
1002+
}
1003+
return CXXStandardLibraryVersionInfo{CXXStandardLibraryVersionInfo::Unknown,
1004+
0};
1005+
}
1006+
1007+
std::optional<unsigned> Preprocessor::getStdLibCxxVersion() {
1008+
if (!CXXStandardLibraryVersion)
1009+
CXXStandardLibraryVersion = getCXXStandardLibraryVersion(
1010+
*this, "__GLIBCXX__", CXXStandardLibraryVersionInfo::LibStdCXX);
1011+
if (!CXXStandardLibraryVersion)
1012+
return std::nullopt;
1013+
1014+
if (CXXStandardLibraryVersion->Lib ==
1015+
CXXStandardLibraryVersionInfo::LibStdCXX)
1016+
return CXXStandardLibraryVersion->Version;
1017+
return std::nullopt;
1018+
}
1019+
1020+
bool Preprocessor::NeedsStdLibCxxWorkaroundBefore(unsigned FixedVersion) {
1021+
assert(FixedVersion >= 2000'00'00 && FixedVersion <= 2100'00'00 &&
1022+
"invalid value for __GLIBCXX__");
1023+
std::optional<unsigned> Ver = getStdLibCxxVersion();
1024+
if (!Ver)
1025+
return false;
1026+
return *Ver < FixedVersion;
1027+
}

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13198,6 +13198,7 @@ NamedDecl *Sema::BuildUsingDeclaration(
1319813198
if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") &&
1319913199
CurContext->isStdNamespace() &&
1320013200
isa<TranslationUnitDecl>(LookupContext) &&
13201+
PP.NeedsStdLibCxxWorkaroundBefore(2016'12'21) &&
1320113202
getSourceManager().isInSystemHeader(UsingLoc))
1320213203
return nullptr;
1320313204
UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),

clang/lib/Sema/SemaExceptionSpec.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/AST/TypeLoc.h"
1919
#include "clang/Basic/Diagnostic.h"
2020
#include "clang/Basic/SourceManager.h"
21+
#include "clang/Lex/Preprocessor.h"
2122
#include "clang/Sema/SemaInternal.h"
2223
#include "llvm/ADT/SmallPtrSet.h"
2324
#include <optional>
@@ -44,6 +45,8 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T)
4445
bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
4546
auto *RD = dyn_cast<CXXRecordDecl>(CurContext);
4647

48+
if (!getPreprocessor().NeedsStdLibCxxWorkaroundBefore(2016'04'27))
49+
return false;
4750
// All the problem cases are member functions named "swap" within class
4851
// templates declared directly within namespace std or std::__debug or
4952
// std::__profile.

clang/lib/Sema/SemaInit.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/Basic/SourceManager.h"
2424
#include "clang/Basic/Specifiers.h"
2525
#include "clang/Basic/TargetInfo.h"
26+
#include "clang/Lex/Preprocessor.h"
2627
#include "clang/Sema/Designator.h"
2728
#include "clang/Sema/EnterExpressionEvaluationContext.h"
2829
#include "clang/Sema/Initialization.h"
@@ -855,8 +856,10 @@ ExprResult InitListChecker::PerformEmptyInit(SourceLocation Loc,
855856
// in that case. stlport does so too.
856857
// Look for std::__debug for libstdc++, and for std:: for stlport.
857858
// This is effectively a compiler-side implementation of LWG2193.
858-
if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
859-
InitializationSequence::FK_ExplicitConstructor) {
859+
if (!InitSeq && EmptyInitList &&
860+
InitSeq.getFailureKind() ==
861+
InitializationSequence::FK_ExplicitConstructor &&
862+
SemaRef.getPreprocessor().NeedsStdLibCxxWorkaroundBefore(2014'04'22)) {
860863
OverloadCandidateSet::iterator Best;
861864
OverloadingResult O =
862865
InitSeq.getFailedCandidateSet()

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,35 +4444,16 @@ static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) {
44444444
!Var->getDeclContext()->isStdNamespace())
44454445
return false;
44464446

4447-
MacroInfo *MacroGLIBCXX =
4448-
PP.getMacroInfo(PP.getIdentifierInfo("__GLIBCXX__"));
4449-
4450-
if (!MacroGLIBCXX || MacroGLIBCXX->getNumTokens() != 1)
4451-
return false;
4452-
4453-
const Token &RevisionDateTok = MacroGLIBCXX->getReplacementToken(0);
4454-
bool Invalid = false;
4455-
std::string RevisionDate = PP.getSpelling(RevisionDateTok, &Invalid);
4456-
4447+
// Checking old versions of libstdc++ is not needed because 15.1 is the first
4448+
// release in which users can access std::format_kind.
44574449
// We can use 20250520 as the final date, see the following commits.
44584450
// GCC releases/gcc-15 branch:
44594451
// https://gcc.gnu.org/g:fedf81ef7b98e5c9ac899b8641bb670746c51205
44604452
// https://gcc.gnu.org/g:53680c1aa92d9f78e8255fbf696c0ed36f160650
44614453
// GCC master branch:
44624454
// https://gcc.gnu.org/g:9361966d80f625c5accc25cbb439f0278dd8b278
44634455
// https://gcc.gnu.org/g:c65725eccbabf3b9b5965f27fff2d3b9f6c75930
4464-
StringRef FixDate = "20250520";
4465-
4466-
if (Invalid)
4467-
return false;
4468-
4469-
// The format of the revision date is in compressed ISO date format.
4470-
// See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html
4471-
// So we can use string comparison.
4472-
//
4473-
// Checking old versions of libstdc++ is not needed because 15.1 is the first
4474-
// release in which users can access std::format_kind.
4475-
return RevisionDate.size() == 8 && RevisionDate < FixDate;
4456+
return PP.NeedsStdLibCxxWorkaroundBefore(2025'05'20);
44764457
}
44774458
} // end anonymous namespace
44784459

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,17 +1510,19 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
15101510
// happen to be processing that implementation, fake up the g++ ?:
15111511
// semantics. See LWG issue 2141 for more information on the bug. The bugs
15121512
// are fixed in g++ and libstdc++ 4.9.0 (2014-04-22).
1513-
const DecltypeType *DT = DI->getType()->getAs<DecltypeType>();
1514-
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
1515-
if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) &&
1516-
DT->isReferenceType() &&
1517-
RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() &&
1518-
RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") &&
1519-
D->getIdentifier() && D->getIdentifier()->isStr("type") &&
1520-
SemaRef.getSourceManager().isInSystemHeader(D->getBeginLoc()))
1521-
// Fold it to the (non-reference) type which g++ would have produced.
1522-
DI = SemaRef.Context.getTrivialTypeSourceInfo(
1523-
DI->getType().getNonReferenceType());
1513+
if (SemaRef.getPreprocessor().NeedsStdLibCxxWorkaroundBefore(2014'04'22)) {
1514+
const DecltypeType *DT = DI->getType()->getAs<DecltypeType>();
1515+
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
1516+
if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) &&
1517+
DT->isReferenceType() &&
1518+
RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() &&
1519+
RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") &&
1520+
D->getIdentifier() && D->getIdentifier()->isStr("type") &&
1521+
SemaRef.getSourceManager().isInSystemHeader(D->getBeginLoc()))
1522+
// Fold it to the (non-reference) type which g++ would have produced.
1523+
DI = SemaRef.Context.getTrivialTypeSourceInfo(
1524+
DI->getType().getNonReferenceType());
1525+
}
15241526

15251527
// Create the new typedef
15261528
TypedefNameDecl *Typedef;

clang/test/SemaCXX/libstdcxx_common_type_hack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify
1+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -D__GLIBCXX__=20100000L
22

33
// This is a test for an egregious hack in Clang that works around
44
// an issue with GCC's <type_traits> implementation. std::common_type

clang/test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s
1+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers -D__GLIBCXX__=20100000L %s
22

33
// libstdc++4.6 in debug mode has explicit default constructors.
44
// stlport has this for all containers.

clang/test/SemaCXX/libstdcxx_pair_swap_hack.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@
77
// The same problem afflicts a bunch of other class templates. Those
88
// affected are array, pair, priority_queue, stack, and queue.
99

10-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array
11-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DPR28423
12-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=pair
13-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue
14-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack
15-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue
10+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=array
11+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=array -DPR28423
12+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=pair
13+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=priority_queue
14+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=stack
15+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=queue
1616
//
17-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug
18-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile
17+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=array -DNAMESPACE=__debug
18+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=array -DNAMESPACE=__profile
1919

2020
// MSVC's standard library uses a very similar pattern that relies on delayed
2121
// parsing of exception specifications.
2222
//
23-
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DMSVC
23+
// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -D__GLIBCXX__=20100000L -DCLASS=array -DMSVC
2424

2525
#ifdef BE_THE_HEADER
2626

0 commit comments

Comments
 (0)