Skip to content

Commit d4a81dd

Browse files
committed
Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (llvm#106585, llvm#111173, llvm#111852)"
1 parent 0fa0545 commit d4a81dd

File tree

23 files changed

+1276
-722
lines changed

23 files changed

+1276
-722
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,9 @@ Bug Fixes to C++ Support
914914
in certain friend declarations. (#GH93099)
915915
- Clang now instantiates the correct lambda call operator when a lambda's class type is
916916
merged across modules. (#GH110401)
917+
- Clang now uses the correct set of template argument lists when comparing the constraints of
918+
out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
919+
a class template. (#GH102320)
917920
- Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460)
918921
- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
919922
and undeclared templates. (#GH107047), (#GH49093)

clang/include/clang/AST/DeclTemplate.h

Lines changed: 34 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -795,26 +795,27 @@ class RedeclarableTemplateDecl : public TemplateDecl,
795795
EntryType *Entry, void *InsertPos);
796796

797797
struct CommonBase {
798-
CommonBase() : InstantiatedFromMember(nullptr, false) {}
798+
CommonBase() {}
799799

800800
/// The template from which this was most
801801
/// directly instantiated (or null).
802-
///
803-
/// The boolean value indicates whether this template
804-
/// was explicitly specialized.
805-
llvm::PointerIntPair<RedeclarableTemplateDecl *, 1, bool>
806-
InstantiatedFromMember;
802+
RedeclarableTemplateDecl *InstantiatedFromMember = nullptr;
807803
};
808804

809805
/// Pointer to the common data shared by all declarations of this
810-
/// template.
811-
mutable CommonBase *Common = nullptr;
806+
/// template, and a flag indicating if the template is a member
807+
/// specialization.
808+
mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;
809+
810+
CommonBase *getCommonPtrInternal() const { return Common.getPointer(); }
812811

813812
/// Retrieves the "common" pointer shared by all (re-)declarations of
814813
/// the same template. Calling this routine may implicitly allocate memory
815814
/// for the common pointer.
816815
CommonBase *getCommonPtr() const;
817816

817+
void setCommonPtr(CommonBase *C) const { Common.setPointer(C); }
818+
818819
virtual CommonBase *newCommon(ASTContext &C) const = 0;
819820

820821
// Construct a template decl with name, parameters, and templated element.
@@ -855,15 +856,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
855856
/// template<> template<typename T>
856857
/// struct X<int>::Inner { /* ... */ };
857858
/// \endcode
858-
bool isMemberSpecialization() const {
859-
return getCommonPtr()->InstantiatedFromMember.getInt();
860-
}
859+
bool isMemberSpecialization() const { return Common.getInt(); }
861860

862861
/// Note that this member template is a specialization.
863862
void setMemberSpecialization() {
864-
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
865-
"Only member templates can be member template specializations");
866-
getCommonPtr()->InstantiatedFromMember.setInt(true);
863+
assert(!isMemberSpecialization() && "already a member specialization");
864+
Common.setInt(true);
867865
}
868866

869867
/// Retrieve the member template from which this template was
@@ -903,12 +901,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
903901
/// void X<T>::f(T, U);
904902
/// \endcode
905903
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
906-
return getCommonPtr()->InstantiatedFromMember.getPointer();
904+
return getCommonPtr()->InstantiatedFromMember;
907905
}
908906

909907
void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
910-
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
911-
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
908+
assert(!getCommonPtr()->InstantiatedFromMember);
909+
getCommonPtr()->InstantiatedFromMember = TD;
912910
}
913911

914912
/// Retrieve the "injected" template arguments that correspond to the
@@ -1958,13 +1956,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
19581956
/// specialization which was specialized by this.
19591957
llvm::PointerUnion<ClassTemplateDecl *,
19601958
ClassTemplatePartialSpecializationDecl *>
1961-
getSpecializedTemplateOrPartial() const {
1962-
if (const auto *PartialSpec =
1963-
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
1964-
return PartialSpec->PartialSpecialization;
1965-
1966-
return cast<ClassTemplateDecl *>(SpecializedTemplate);
1967-
}
1959+
getSpecializedTemplateOrPartial() const;
19681960

19691961
/// Retrieve the set of template arguments that should be used
19701962
/// to instantiate members of the class template or class template partial
@@ -1990,7 +1982,9 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
19901982
/// template arguments have been deduced.
19911983
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
19921984
const TemplateArgumentList *TemplateArgs) {
1993-
assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) &&
1985+
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
1986+
"A partial specialization cannot be instantiated from a template");
1987+
assert(!isa<SpecializedPartialSpecialization*>(SpecializedTemplate) &&
19941988
"Already set to a class template partial specialization!");
19951989
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
19961990
PS->PartialSpecialization = PartialSpec;
@@ -2001,7 +1995,9 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
20011995
/// Note that this class template specialization is an instantiation
20021996
/// of the given class template.
20031997
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
2004-
assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) &&
1998+
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
1999+
"A partial specialization cannot be instantiated from a template");
2000+
assert(!isa<SpecializedPartialSpecialization*>(SpecializedTemplate) &&
20052001
"Previously set to a class template partial specialization!");
20062002
SpecializedTemplate = TemplDecl;
20072003
}
@@ -2194,18 +2190,11 @@ class ClassTemplatePartialSpecializationDecl
21942190
/// struct X<int>::Inner<T*> { /* ... */ };
21952191
/// \endcode
21962192
bool isMemberSpecialization() const {
2197-
const auto *First =
2198-
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
2199-
return First->InstantiatedFromMember.getInt();
2193+
return InstantiatedFromMember.getInt();
22002194
}
22012195

22022196
/// Note that this member template is a specialization.
2203-
void setMemberSpecialization() {
2204-
auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
2205-
assert(First->InstantiatedFromMember.getPointer() &&
2206-
"Only member templates can be member template specializations");
2207-
return First->InstantiatedFromMember.setInt(true);
2208-
}
2197+
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
22092198

22102199
/// Retrieves the injected specialization type for this partial
22112200
/// specialization. This is not the same as the type-decl-type for
@@ -2275,8 +2264,6 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
22752264
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
22762265
}
22772266

2278-
void setCommonPtr(Common *C) { RedeclarableTemplateDecl::Common = C; }
2279-
22802267
public:
22812268

22822269
friend class ASTDeclReader;
@@ -2727,13 +2714,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
27272714
/// Retrieve the variable template or variable template partial
27282715
/// specialization which was specialized by this.
27292716
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
2730-
getSpecializedTemplateOrPartial() const {
2731-
if (const auto *PartialSpec =
2732-
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
2733-
return PartialSpec->PartialSpecialization;
2734-
2735-
return cast<VarTemplateDecl *>(SpecializedTemplate);
2736-
}
2717+
getSpecializedTemplateOrPartial() const;
27372718

27382719
/// Retrieve the set of template arguments that should be used
27392720
/// to instantiate the initializer of the variable template or variable
@@ -2759,6 +2740,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
27592740
/// template arguments have been deduced.
27602741
void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
27612742
const TemplateArgumentList *TemplateArgs) {
2743+
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
2744+
"A partial specialization cannot be instantiated from a template");
27622745
assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) &&
27632746
"Already set to a variable template partial specialization!");
27642747
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
@@ -2770,6 +2753,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
27702753
/// Note that this variable template specialization is an instantiation
27712754
/// of the given variable template.
27722755
void setInstantiationOf(VarTemplateDecl *TemplDecl) {
2756+
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
2757+
"A partial specialization cannot be instantiated from a template");
27732758
assert(!isa<SpecializedPartialSpecialization *>(SpecializedTemplate) &&
27742759
"Previously set to a variable template partial specialization!");
27752760
SpecializedTemplate = TemplDecl;
@@ -2960,18 +2945,11 @@ class VarTemplatePartialSpecializationDecl
29602945
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
29612946
/// \endcode
29622947
bool isMemberSpecialization() const {
2963-
const auto *First =
2964-
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
2965-
return First->InstantiatedFromMember.getInt();
2948+
return InstantiatedFromMember.getInt();
29662949
}
29672950

29682951
/// Note that this member template is a specialization.
2969-
void setMemberSpecialization() {
2970-
auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
2971-
assert(First->InstantiatedFromMember.getPointer() &&
2972-
"Only member templates can be member template specializations");
2973-
return First->InstantiatedFromMember.setInt(true);
2974-
}
2952+
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
29752953

29762954
SourceRange getSourceRange() const override LLVM_READONLY;
29772955

@@ -3142,6 +3120,9 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
31423120
return makeSpecIterator(getSpecializations(), true);
31433121
}
31443122

3123+
/// Merge \p Prev with our RedeclarableTemplateDecl::Common.
3124+
void mergePrevDecl(VarTemplateDecl *Prev);
3125+
31453126
// Implement isa/cast/dyncast support
31463127
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
31473128
static bool classofKind(Kind K) { return K == VarTemplate; }

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11367,9 +11367,9 @@ class Sema final : public SemaBase {
1136711367
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
1136811368
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
1136911369
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
11370-
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
11371-
TemplateParameterList **OuterTemplateParamLists,
11372-
SkipBodyInfo *SkipBody = nullptr);
11370+
SourceLocation FriendLoc,
11371+
ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
11372+
bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);
1137311373

1137411374
/// Translates template arguments as provided by the parser
1137511375
/// into template arguments used by semantic analysis.
@@ -11408,7 +11408,8 @@ class Sema final : public SemaBase {
1140811408
DeclResult ActOnVarTemplateSpecialization(
1140911409
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
1141011410
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
11411-
StorageClass SC, bool IsPartialSpecialization);
11411+
StorageClass SC, bool IsPartialSpecialization,
11412+
bool IsMemberSpecialization);
1141211413

1141311414
/// Get the specialization of the given variable template corresponding to
1141411415
/// the specified argument list, or a null-but-valid result if the arguments
@@ -13050,28 +13051,14 @@ class Sema final : public SemaBase {
1305013051
/// dealing with a specialization. This is only relevant for function
1305113052
/// template specializations.
1305213053
///
13053-
/// \param Pattern If non-NULL, indicates the pattern from which we will be
13054-
/// instantiating the definition of the given declaration, \p ND. This is
13055-
/// used to determine the proper set of template instantiation arguments for
13056-
/// friend function template specializations.
13057-
///
1305813054
/// \param ForConstraintInstantiation when collecting arguments,
1305913055
/// ForConstraintInstantiation indicates we should continue looking when
1306013056
/// encountering a lambda generic call operator, and continue looking for
1306113057
/// arguments on an enclosing class template.
13062-
///
13063-
/// \param SkipForSpecialization when specified, any template specializations
13064-
/// in a traversal would be ignored.
13065-
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
13066-
/// when encountering a specialized member function template, rather than
13067-
/// returning immediately.
1306813058
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
1306913059
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
1307013060
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
13071-
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
13072-
bool ForConstraintInstantiation = false,
13073-
bool SkipForSpecialization = false,
13074-
bool ForDefaultArgumentSubstitution = false);
13061+
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
1307513062

1307613063
/// RAII object to handle the state changes required to synthesize
1307713064
/// a function body.

clang/lib/AST/Decl.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,21 +2706,21 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
27062706
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
27072707
auto From = VDTemplSpec->getInstantiatedFrom();
27082708
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
2709-
while (!VTD->isMemberSpecialization()) {
2710-
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
2711-
if (!NewVTD)
2709+
while (!VTD->getMostRecentDecl()->isMemberSpecialization()) {
2710+
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
2711+
VTD = NewVTD;
2712+
else
27122713
break;
2713-
VTD = NewVTD;
27142714
}
27152715
return getDefinitionOrSelf(VTD->getTemplatedDecl());
27162716
}
27172717
if (auto *VTPSD =
27182718
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
2719-
while (!VTPSD->isMemberSpecialization()) {
2720-
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
2721-
if (!NewVTPSD)
2719+
while (!VTPSD->getMostRecentDecl()->isMemberSpecialization()) {
2720+
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
2721+
VTPSD = NewVTPSD;
2722+
else
27222723
break;
2723-
VTPSD = NewVTPSD;
27242724
}
27252725
return getDefinitionOrSelf<VarDecl>(VTPSD);
27262726
}
@@ -2729,15 +2729,14 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
27292729

27302730
// If this is the pattern of a variable template, find where it was
27312731
// instantiated from. FIXME: Is this necessary?
2732-
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
2733-
while (!VarTemplate->isMemberSpecialization()) {
2734-
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
2735-
if (!NewVT)
2732+
if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) {
2733+
while (!VTD->getMostRecentDecl()->isMemberSpecialization()) {
2734+
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
2735+
VTD = NewVTD;
2736+
else
27362737
break;
2737-
VarTemplate = NewVT;
27382738
}
2739-
2740-
return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
2739+
return getDefinitionOrSelf(VTD->getTemplatedDecl());
27412740
}
27422741

27432742
if (VD == this)
@@ -4156,11 +4155,11 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
41564155
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
41574156
// If we hit a point where the user provided a specialization of this
41584157
// template, we're done looking.
4159-
while (!ForDefinition || !Primary->isMemberSpecialization()) {
4160-
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
4161-
if (!NewPrimary)
4158+
while (!ForDefinition || !Primary->getMostRecentDecl()->isMemberSpecialization()) {
4159+
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
4160+
Primary = NewPrimary;
4161+
else
41624162
break;
4163-
Primary = NewPrimary;
41644163
}
41654164

41664165
return getDefinitionOrSelf(Primary->getTemplatedDecl());

clang/lib/AST/DeclCXX.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,19 +2046,21 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
20462046
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
20472047
auto From = TD->getInstantiatedFrom();
20482048
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
2049-
while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
2050-
if (NewCTD->isMemberSpecialization())
2049+
while (!CTD->getMostRecentDecl()->isMemberSpecialization()) {
2050+
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
2051+
CTD = NewCTD;
2052+
else
20512053
break;
2052-
CTD = NewCTD;
20532054
}
20542055
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
20552056
}
20562057
if (auto *CTPSD =
20572058
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
2058-
while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
2059-
if (NewCTPSD->isMemberSpecialization())
2059+
while (!CTPSD->getMostRecentDecl()->isMemberSpecialization()) {
2060+
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
2061+
CTPSD = NewCTPSD;
2062+
else
20602063
break;
2061-
CTPSD = NewCTPSD;
20622064
}
20632065
return GetDefinitionOrSelf(CTPSD);
20642066
}

0 commit comments

Comments
 (0)