-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Revert "[Clang][Sema] Always use latest redeclaration of primary template" #114304
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-clang Author: Felipe de Azevedo Piovezan (felipepiovezan) ChangesClang importer doesn't seem to work well with this change, see discussion in the original PR. Reverts llvm/llvm-project#114258 Full diff: https://github.com/llvm/llvm-project/pull/114304.diff 9 Files Affected:
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 0ca3fd48e81cf4..a572e3380f1655 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -857,6 +857,16 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// \endcode
bool isMemberSpecialization() const { return Common.getInt(); }
+ /// Determines whether any redeclaration of this template was
+ /// a specialization of a member template.
+ bool hasMemberSpecialization() const {
+ for (const auto *D : redecls()) {
+ if (D->isMemberSpecialization())
+ return true;
+ }
+ return false;
+ }
+
/// Note that this member template is a specialization.
void setMemberSpecialization() {
assert(!isMemberSpecialization() && "already a member specialization");
@@ -1955,7 +1965,13 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// specialization which was specialized by this.
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
- getSpecializedTemplateOrPartial() const;
+ getSpecializedTemplateOrPartial() const {
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<ClassTemplateDecl*>();
+ }
/// Retrieve the set of template arguments that should be used
/// to instantiate members of the class template or class template partial
@@ -2192,6 +2208,17 @@ class ClassTemplatePartialSpecializationDecl
return InstantiatedFromMember.getInt();
}
+ /// Determines whether any redeclaration of this this class template partial
+ /// specialization was a specialization of a member partial specialization.
+ bool hasMemberSpecialization() const {
+ for (const auto *D : redecls()) {
+ if (cast<ClassTemplatePartialSpecializationDecl>(D)
+ ->isMemberSpecialization())
+ return true;
+ }
+ return false;
+ }
+
/// Note that this member template is a specialization.
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
@@ -2713,7 +2740,13 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Retrieve the variable template or variable template partial
/// specialization which was specialized by this.
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
- getSpecializedTemplateOrPartial() const;
+ getSpecializedTemplateOrPartial() const {
+ if (const auto *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
/// Retrieve the set of template arguments that should be used
/// to instantiate the initializer of the variable template or variable
@@ -2947,6 +2980,18 @@ class VarTemplatePartialSpecializationDecl
return InstantiatedFromMember.getInt();
}
+ /// Determines whether any redeclaration of this this variable template
+ /// partial specialization was a specialization of a member partial
+ /// specialization.
+ bool hasMemberSpecialization() const {
+ for (const auto *D : redecls()) {
+ if (cast<VarTemplatePartialSpecializationDecl>(D)
+ ->isMemberSpecialization())
+ return true;
+ }
+ return false;
+ }
+
/// Note that this member template is a specialization.
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }
@@ -3119,9 +3164,6 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
return makeSpecIterator(getSpecializations(), true);
}
- /// Merge \p Prev with our RedeclarableTemplateDecl::Common.
- void mergePrevDecl(VarTemplateDecl *Prev);
-
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == VarTemplate; }
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index cd173d17263792..86913763ef9ff5 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2708,7 +2708,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
- while (!VTD->isMemberSpecialization()) {
+ while (!VTD->hasMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
@@ -2718,7 +2718,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- while (!VTPSD->isMemberSpecialization()) {
+ while (!VTPSD->hasMemberSpecialization()) {
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
@@ -2732,7 +2732,7 @@ 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 (!VTD->isMemberSpecialization()) {
+ while (!VTD->hasMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
@@ -4153,7 +4153,7 @@ 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 (!ForDefinition || !Primary->isMemberSpecialization()) {
+ while (!ForDefinition || !Primary->hasMemberSpecialization()) {
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
@@ -4170,7 +4170,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
- return Info->getTemplate()->getMostRecentDecl();
+ return Info->getTemplate();
}
return nullptr;
}
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 1c92fd9e3ff067..db0ea62a2323eb 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2030,7 +2030,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
- while (!CTD->isMemberSpecialization()) {
+ while (!CTD->hasMemberSpecialization()) {
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
@@ -2040,7 +2040,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- while (!CTPSD->isMemberSpecialization()) {
+ while (!CTPSD->hasMemberSpecialization()) {
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 1db02d0d04448c..755ec72f00bf77 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -993,17 +993,7 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
- return SpecializedTemplate.get<ClassTemplateDecl *>()->getMostRecentDecl();
-}
-
-llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
-ClassTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return PartialSpec->PartialSpecialization->getMostRecentDecl();
-
- return SpecializedTemplate.get<ClassTemplateDecl *>()->getMostRecentDecl();
+ return SpecializedTemplate.get<ClassTemplateDecl*>();
}
SourceRange
@@ -1293,39 +1283,6 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
return CommonPtr;
}
-void VarTemplateDecl::mergePrevDecl(VarTemplateDecl *Prev) {
- // If we haven't created a common pointer yet, then it can just be created
- // with the usual method.
- if (!getCommonPtrInternal())
- return;
-
- Common *ThisCommon = static_cast<Common *>(getCommonPtrInternal());
- Common *PrevCommon = nullptr;
- SmallVector<VarTemplateDecl *, 8> PreviousDecls;
- for (; Prev; Prev = Prev->getPreviousDecl()) {
- if (CommonBase *C = Prev->getCommonPtrInternal()) {
- PrevCommon = static_cast<Common *>(C);
- break;
- }
- PreviousDecls.push_back(Prev);
- }
-
- // If the previous redecl chain hasn't created a common pointer yet, then just
- // use this common pointer.
- if (!PrevCommon) {
- for (auto *D : PreviousDecls)
- D->setCommonPtr(ThisCommon);
- return;
- }
-
- // Ensure we don't leak any important state.
- assert(ThisCommon->Specializations.empty() &&
- ThisCommon->PartialSpecializations.empty() &&
- "Can't merge incompatible declarations!");
-
- setCommonPtr(PrevCommon);
-}
-
VarTemplateSpecializationDecl *
VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
void *&InsertPos) {
@@ -1448,16 +1405,7 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
if (const auto *PartialSpec =
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
- return SpecializedTemplate.get<VarTemplateDecl *>()->getMostRecentDecl();
-}
-
-llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
-VarTemplateSpecializationDecl::getSpecializedTemplateOrPartial() const {
- if (const auto *PartialSpec =
- SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
- return PartialSpec->PartialSpecialization->getMostRecentDecl();
-
- return SpecializedTemplate.get<VarTemplateDecl *>()->getMostRecentDecl();
+ return SpecializedTemplate.get<VarTemplateDecl *>();
}
SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3e8b76e8dfd625..f8e5f3c6d309d6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -4696,10 +4696,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Keep a chain of previous declarations.
New->setPreviousDecl(Old);
- if (NewTemplate) {
- NewTemplate->mergePrevDecl(OldTemplate);
+ if (NewTemplate)
NewTemplate->setPreviousDecl(OldTemplate);
- }
// Inherit access appropriately.
New->setAccess(Old->getAccess());
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index e2a59f63ccf589..573e90aced3eea 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -9954,7 +9954,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
auto SynthesizeAggrGuide = [&](InitListExpr *ListInit) {
auto *Pattern = Template;
while (Pattern->getInstantiatedFromMemberTemplate()) {
- if (Pattern->isMemberSpecialization())
+ if (Pattern->hasMemberSpecialization())
break;
Pattern = Pattern->getInstantiatedFromMemberTemplate();
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index de0ec0128905ff..b63063813f1b56 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -343,7 +343,7 @@ struct TemplateInstantiationArgumentCollecter
// If this function was instantiated from a specialized member that is
// a function template, we're done.
assert(FD->getPrimaryTemplate() && "No function template?");
- if (FD->getPrimaryTemplate()->isMemberSpecialization())
+ if (FD->getPrimaryTemplate()->hasMemberSpecialization())
return Done();
// If this function is a generic lambda specialization, we are done.
@@ -442,11 +442,11 @@ struct TemplateInstantiationArgumentCollecter
Specialized = CTSD->getSpecializedTemplateOrPartial();
if (auto *CTPSD =
Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- if (CTPSD->isMemberSpecialization())
+ if (CTPSD->hasMemberSpecialization())
return Done();
} else {
auto *CTD = Specialized.get<ClassTemplateDecl *>();
- if (CTD->isMemberSpecialization())
+ if (CTD->hasMemberSpecialization())
return Done();
}
return UseNextDecl(CTSD);
@@ -478,11 +478,11 @@ struct TemplateInstantiationArgumentCollecter
Specialized = VTSD->getSpecializedTemplateOrPartial();
if (auto *VTPSD =
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
- if (VTPSD->isMemberSpecialization())
+ if (VTPSD->hasMemberSpecialization())
return Done();
} else {
auto *VTD = Specialized.get<VarTemplateDecl *>();
- if (VTD->isMemberSpecialization())
+ if (VTD->hasMemberSpecialization())
return Done();
}
return UseNextDecl(VTSD);
@@ -4141,7 +4141,7 @@ getPatternForClassTemplateSpecialization(
CXXRecordDecl *Pattern = nullptr;
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
if (auto *CTD = Specialized.dyn_cast<ClassTemplateDecl *>()) {
- while (!CTD->isMemberSpecialization()) {
+ while (!CTD->hasMemberSpecialization()) {
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
@@ -4151,7 +4151,7 @@ getPatternForClassTemplateSpecialization(
} else if (auto *CTPSD =
Specialized
.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
- while (!CTPSD->isMemberSpecialization()) {
+ while (!CTPSD->hasMemberSpecialization()) {
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index 7b998f20944f49..e84241cee922f5 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -530,7 +530,7 @@ namespace testCanonicalTemplate {
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} parent 0x{{.+}} <col:5, col:40> col:40 friend_undeclared TestClassTemplate{{$}}
// CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{.+}} <col:14, col:23> col:23 typename depth 1 index 0 T2{{$}}
// CHECK-NEXT: | `-CXXRecordDecl 0x{{.+}} parent 0x{{.+}} <col:34, col:40> col:40 class TestClassTemplate{{$}}
- // CHECK-NEXT: `-ClassTemplateSpecializationDecl 0x{{.+}} <col:5, col:40> line:[[@LINE-19]]:31 class TestClassTemplate definition implicit_instantiation{{$}}
+ // CHECK-NEXT: `-ClassTemplateSpecializationDecl 0x{{.+}} <line:[[@LINE-19]]:3, line:[[@LINE-17]]:3> line:[[@LINE-19]]:31 class TestClassTemplate definition implicit_instantiation{{$}}
// CHECK-NEXT: |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init{{$}}
// CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr defaulted_is_constexpr{{$}}
// CHECK-NEXT: | |-CopyConstructor simple trivial has_const_param implicit_has_const_param{{$}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
index e7e4738032f647..87127366eb58a5 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p7.cpp
@@ -177,93 +177,6 @@ namespace Defined {
static_assert(A<short>::B<int*>::y == 2);
} // namespace Defined
-namespace Constrained {
- template<typename T>
- struct A {
- template<typename U, bool V> requires V
- static constexpr int f(); // expected-note {{declared here}}
-
- template<typename U, bool V> requires V
- static const int x; // expected-note {{declared here}}
-
- template<typename U, bool V> requires V
- static const int x<U*, V>; // expected-note {{declared here}}
-
- template<typename U, bool V> requires V
- struct B; // expected-note {{template is declared here}}
-
- template<typename U, bool V> requires V
- struct B<U*, V>; // expected-note {{template is declared here}}
- };
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<short>::f() {
- return A<long>::f<U, V>();
- }
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<short>::x = A<long>::x<U, V>;
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<short>::x<U*, V> = A<long>::x<U*, V>;
-
- template<>
- template<typename U, bool V> requires V
- struct A<short>::B<U*, V> {
- static constexpr int y = A<long>::B<U*, V>::y;
- };
-
- template<>
- template<typename U, bool V> requires V
- struct A<short>::B {
- static constexpr int y = A<long>::B<U, V>::y;
- };
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<long>::f() {
- return 1;
- }
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<long>::x = 1;
-
- template<>
- template<typename U, bool V> requires V
- constexpr int A<long>::x<U*, V> = 2;
-
- template<>
- template<typename U, bool V> requires V
- struct A<long>::B {
- static constexpr int y = 1;
- };
-
- template<>
- template<typename U, bool V> requires V
- struct A<long>::B<U*, V> {
- static constexpr int y = 2;
- };
-
- static_assert(A<int>::f<int, true>() == 0); // expected-error {{static assertion expression is not an integral constant expression}}
- // expected-note@-1 {{undefined function 'f<int, true>' cannot be used in a constant expression}}
- static_assert(A<int>::x<int, true> == 0); // expected-error {{static assertion expression is not an integral constant expression}}
- // expected-note@-1 {{initializer of 'x<int, true>' is unknown}}
- static_assert(A<int>::x<int*, true> == 0); // expected-error {{static assertion expression is not an integral constant expression}}
- // expected-note@-1 {{initializer of 'x<int *, true>' is unknown}}
- static_assert(A<int>::B<int, true>::y == 0); // expected-error {{implicit instantiation of undefined template 'Constrained::A<int>::B<int, true>'}}
- static_assert(A<int>::B<int*, true>::y == 0); // expected-error {{implicit instantiation of undefined template 'Constrained::A<int>::B<int *, true>'}}
-
- static_assert(A<short>::f<int, true>() == 1);
- static_assert(A<short>::x<int, true> == 1);
- static_assert(A<short>::x<int*, true> == 2);
- static_assert(A<short>::B<int, true>::y == 1);
- static_assert(A<short>::B<int*, true>::y == 2);
-} // namespace Constrained
-
namespace Dependent {
template<int I>
struct A {
|
sdkrystian
added a commit
to sdkrystian/llvm-project
that referenced
this pull request
Oct 31, 2024
…plate" (llvm#114304) This reverts commit 4afa978.
sdkrystian
added a commit
to sdkrystian/llvm-project
that referenced
this pull request
Nov 1, 2024
…plate" (llvm#114304) This reverts commit 4afa978.
smallp-o-p
pushed a commit
to smallp-o-p/llvm-project
that referenced
this pull request
Nov 3, 2024
…late" (llvm#114304) Clang importer doesn't seem to work well with this change, see discussion in the original PR. Reverts llvm#114258
NoumanAmir657
pushed a commit
to NoumanAmir657/llvm-project
that referenced
this pull request
Nov 4, 2024
…late" (llvm#114304) Clang importer doesn't seem to work well with this change, see discussion in the original PR. Reverts llvm#114258
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
clang:frontend
Language frontend issues, e.g. anything involving "Sema"
clang
Clang issues not falling into any other category
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Clang importer doesn't seem to work well with this change, see discussion in the original PR.
Reverts #114258