Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Reapply "[Clang][Sema] Refactor collection of multi-level template argument lists (#106585)" (#111173)" #111766

Merged
merged 1 commit into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -477,9 +477,6 @@ Bug Fixes to C++ Support
in certain friend declarations. (#GH93099)
- Clang now instantiates the correct lambda call operator when a lambda's class type is
merged across modules. (#GH110401)
- Clang now uses the correct set of template argument lists when comparing the constraints of
out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
a class template. (#GH102320)
- Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460)

Bug Fixes to AST Handling
Expand Down
66 changes: 39 additions & 27 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -781,11 +781,15 @@ class RedeclarableTemplateDecl : public TemplateDecl,
EntryType *Entry, void *InsertPos);

struct CommonBase {
CommonBase() {}
CommonBase() : InstantiatedFromMember(nullptr, false) {}

/// The template from which this was most
/// directly instantiated (or null).
RedeclarableTemplateDecl *InstantiatedFromMember = nullptr;
///
/// The boolean value indicates whether this template
/// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;

/// If non-null, points to an array of specializations (including
/// partial specializations) known only by their external declaration IDs.
Expand All @@ -805,19 +809,14 @@ class RedeclarableTemplateDecl : public TemplateDecl,
};

/// Pointer to the common data shared by all declarations of this
/// template, and a flag indicating if the template is a member
/// specialization.
mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;

CommonBase *getCommonPtrInternal() const { return Common.getPointer(); }
/// template.
mutable CommonBase *Common = nullptr;

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

void setCommonPtr(CommonBase *C) const { Common.setPointer(C); }

virtual CommonBase *newCommon(ASTContext &C) const = 0;

// Construct a template decl with name, parameters, and templated element.
Expand Down Expand Up @@ -858,12 +857,15 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() const { return Common.getInt(); }
bool isMemberSpecialization() const {
return getCommonPtr()->InstantiatedFromMember.getInt();
}

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

/// Retrieve the member template from which this template was
Expand Down Expand Up @@ -903,12 +905,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// void X<T>::f(T, U);
/// \endcode
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
return getCommonPtr()->InstantiatedFromMember;
return getCommonPtr()->InstantiatedFromMember.getPointer();
}

void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember);
getCommonPtr()->InstantiatedFromMember = TD;
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}

/// Retrieve the "injected" template arguments that correspond to the
Expand Down Expand Up @@ -1987,8 +1989,6 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
Expand All @@ -2000,8 +2000,6 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Note that this class template specialization is an instantiation
/// of the given class template.
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Previously set to a class template partial specialization!");
SpecializedTemplate = TemplDecl;
Expand Down Expand Up @@ -2189,11 +2187,18 @@ class ClassTemplatePartialSpecializationDecl
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() const {
return InstantiatedFromMember.getInt();
const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}

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

/// Retrieves the injected specialization type for this partial
/// specialization. This is not the same as the type-decl-type for
Expand Down Expand Up @@ -2263,6 +2268,10 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}

void setCommonPtr(Common *C) {
RedeclarableTemplateDecl::Common = C;
}

public:

friend class ASTDeclReader;
Expand Down Expand Up @@ -2745,8 +2754,6 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// template arguments have been deduced.
void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Already set to a variable template partial specialization!");
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
Expand All @@ -2758,8 +2765,6 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Note that this variable template specialization is an instantiation
/// of the given variable template.
void setInstantiationOf(VarTemplateDecl *TemplDecl) {
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Previously set to a variable template partial specialization!");
SpecializedTemplate = TemplDecl;
Expand Down Expand Up @@ -2944,11 +2949,18 @@ class VarTemplatePartialSpecializationDecl
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
/// \endcode
bool isMemberSpecialization() const {
return InstantiatedFromMember.getInt();
const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}

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

SourceRange getSourceRange() const override LLVM_READONLY;

Expand Down
25 changes: 19 additions & 6 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11325,9 +11325,9 @@ class Sema final : public SemaBase {
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc,
ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists,
SkipBodyInfo *SkipBody = nullptr);

/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
Expand Down Expand Up @@ -11366,8 +11366,7 @@ class Sema final : public SemaBase {
DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization,
bool IsMemberSpecialization);
StorageClass SC, bool IsPartialSpecialization);

/// Get the specialization of the given variable template corresponding to
/// the specified argument list, or a null-but-valid result if the arguments
Expand Down Expand Up @@ -13008,14 +13007,28 @@ class Sema final : public SemaBase {
/// dealing with a specialization. This is only relevant for function
/// template specializations.
///
/// \param Pattern If non-NULL, indicates the pattern from which we will be
/// instantiating the definition of the given declaration, \p ND. This is
/// used to determine the proper set of template instantiation arguments for
/// friend function template specializations.
///
/// \param ForConstraintInstantiation when collecting arguments,
/// ForConstraintInstantiation indicates we should continue looking when
/// encountering a lambda generic call operator, and continue looking for
/// arguments on an enclosing class template.
///
/// \param SkipForSpecialization when specified, any template specializations
/// in a traversal would be ignored.
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
/// when encountering a specialized member function template, rather than
/// returning immediately.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
bool ForConstraintInstantiation = false,
bool SkipForSpecialization = false,
bool ForDefaultArgumentSubstitution = false);

/// RAII object to handle the state changes required to synthesize
/// a function body.
Expand Down
49 changes: 19 additions & 30 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2696,27 +2696,21 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
while (!VTD->isMemberSpecialization()) {
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
if (!NewVTD)
break;
VTD = NewVTD;
}
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (true) {
VTPSD = VTPSD->getMostRecentDecl();
if (VTPSD->isMemberSpecialization())
break;
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
while (!VTPSD->isMemberSpecialization()) {
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
if (!NewVTPSD)
break;
VTPSD = NewVTPSD;
}
return getDefinitionOrSelf<VarDecl>(VTPSD);
}
Expand All @@ -2725,17 +2719,15 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {

// If this is the pattern of a variable template, find where it was
// instantiated from. FIXME: Is this necessary?
if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
while (!VarTemplate->isMemberSpecialization()) {
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
if (!NewVT)
break;
VarTemplate = NewVT;
}
return getDefinitionOrSelf(VTD->getTemplatedDecl());

return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
}

if (VD == this)
Expand Down Expand Up @@ -4150,14 +4142,11 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
// If we hit a point where the user provided a specialization of this
// template, we're done looking.
while (true) {
Primary = Primary->getMostRecentDecl();
if (ForDefinition && Primary->isMemberSpecialization())
break;
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
while (!ForDefinition || !Primary->isMemberSpecialization()) {
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
if (!NewPrimary)
break;
Primary = NewPrimary;
}

return getDefinitionOrSelf(Primary->getTemplatedDecl());
Expand Down
20 changes: 6 additions & 14 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,27 +2023,19 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
while (true) {
CTD = CTD->getMostRecentDecl();
if (CTD->isMemberSpecialization())
break;
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
if (NewCTD->isMemberSpecialization())
break;
CTD = NewCTD;
}
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (true) {
CTPSD = CTPSD->getMostRecentDecl();
if (CTPSD->isMemberSpecialization())
break;
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
if (NewCTPSD->isMemberSpecialization())
break;
CTPSD = NewCTPSD;
}
return GetDefinitionOrSelf(CTPSD);
}
Expand Down
Loading
Loading