[clang] 5c24847 - Revert "[clang] Track function template instantiation from definition (#112241)"
Martin Storsjö via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 30 02:21:26 PST 2025
Author: Martin Storsjö
Date: 2025-01-30T12:05:56+02:00
New Revision: 5c24847e7dba01dde230e18b39a3074022279c89
URL: https://github.com/llvm/llvm-project/commit/5c24847e7dba01dde230e18b39a3074022279c89
DIFF: https://github.com/llvm/llvm-project/commit/5c24847e7dba01dde230e18b39a3074022279c89.diff
LOG: Revert "[clang] Track function template instantiation from definition (#112241)"
This reverts commit 07a0e2be86f33beb6d519a3d466b95c2257e93cb.
This change broke compiling Qt; see
https://github.com/llvm/llvm-project/pull/112241 for details.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Decl.h
clang/include/clang/AST/DeclBase.h
clang/include/clang/AST/DeclTemplate.h
clang/lib/AST/Decl.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
Removed:
clang/test/SemaTemplate/GH55509.cpp
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b8b47103d95177..d754c49f2aa3a4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -128,8 +128,6 @@ Bug Fixes to Attribute Support
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
-- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
-
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index f305cbbce4c609..499d27a9be5a8a 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2298,13 +2298,6 @@ class FunctionDecl : public DeclaratorDecl,
FunctionDeclBits.IsLateTemplateParsed = ILT;
}
- bool isInstantiatedFromMemberTemplate() const {
- return FunctionDeclBits.IsInstantiatedFromMemberTemplate;
- }
- void setInstantiatedFromMemberTemplate(bool Val = true) {
- FunctionDeclBits.IsInstantiatedFromMemberTemplate = Val;
- }
-
/// Whether this function is "trivial" in some specialized C++ senses.
/// Can only be true for default constructors, copy constructors,
/// copy assignment operators, and destructors. Not meaningful until
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 3a13309a6100ee..2c0c3a8dc2f9d5 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1777,8 +1777,6 @@ class DeclContext {
uint64_t HasImplicitReturnZero : 1;
LLVM_PREFERRED_TYPE(bool)
uint64_t IsLateTemplateParsed : 1;
- LLVM_PREFERRED_TYPE(bool)
- uint64_t IsInstantiatedFromMemberTemplate : 1;
/// Kind of contexpr specifier as defined by ConstexprSpecKind.
LLVM_PREFERRED_TYPE(ConstexprSpecKind)
@@ -1829,7 +1827,7 @@ class DeclContext {
};
/// Number of inherited and non-inherited bits in FunctionDeclBitfields.
- enum { NumFunctionDeclBits = NumDeclContextBits + 32 };
+ enum { NumFunctionDeclBits = NumDeclContextBits + 31 };
/// Stores the bits used by CXXConstructorDecl. If modified
/// NumCXXConstructorDeclBits and the accessor
@@ -1840,12 +1838,12 @@ class DeclContext {
LLVM_PREFERRED_TYPE(FunctionDeclBitfields)
uint64_t : NumFunctionDeclBits;
- /// 19 bits to fit in the remaining available space.
+ /// 20 bits to fit in the remaining available space.
/// Note that this makes CXXConstructorDeclBitfields take
/// exactly 64 bits and thus the width of NumCtorInitializers
/// will need to be shrunk if some bit is added to NumDeclContextBitfields,
/// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
- uint64_t NumCtorInitializers : 16;
+ uint64_t NumCtorInitializers : 17;
LLVM_PREFERRED_TYPE(bool)
uint64_t IsInheritingConstructor : 1;
@@ -1859,7 +1857,7 @@ class DeclContext {
};
/// Number of inherited and non-inherited bits in CXXConstructorDeclBitfields.
- enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 19 };
+ enum { NumCXXConstructorDeclBits = NumFunctionDeclBits + 20 };
/// Stores the bits used by ObjCMethodDecl.
/// If modified NumObjCMethodDeclBits and the accessor
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 0c706036ff7022..9ecff2c898acd5 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1011,15 +1011,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
- bool isCompatibleWithDefinition() const {
- return getTemplatedDecl()->isInstantiatedFromMemberTemplate() ||
- isThisDeclarationADefinition();
- }
- void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *D) {
- getTemplatedDecl()->setInstantiatedFromMemberTemplate();
- RedeclarableTemplateDecl::setInstantiatedFromMemberTemplate(D);
- }
-
/// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args,
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 610207cf8b9a4a..7e8a172ae4c37f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3065,7 +3065,6 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.IsIneligibleOrNotSelected = false;
FunctionDeclBits.HasImplicitReturnZero = false;
FunctionDeclBits.IsLateTemplateParsed = false;
- FunctionDeclBits.IsInstantiatedFromMemberTemplate = false;
FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false;
FunctionDeclBits.InstantiationIsPending = false;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 6aaf86a6a6ff36..137942f0c30bfe 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -4074,7 +4074,22 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
if (FunctionTemplate->getFriendObjectKind())
Owner = FunctionTemplate->getLexicalDeclContext();
FunctionDecl *FD = FunctionTemplate->getTemplatedDecl();
-
+ // additional check for inline friend,
+ // ```
+ // template <class F1> int foo(F1 X);
+ // template <int A1> struct A {
+ // template <class F1> friend int foo(F1 X) { return A1; }
+ // };
+ // template struct A<1>;
+ // int a = foo(1.0);
+ // ```
+ const FunctionDecl *FDFriend;
+ if (FD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None &&
+ FD->isDefined(FDFriend, /*CheckForPendingFriendDefinition*/ true) &&
+ FDFriend->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None) {
+ FD = const_cast<FunctionDecl *>(FDFriend);
+ Owner = FD->getLexicalDeclContext();
+ }
MultiLevelTemplateArgumentList SubstArgs(
FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
/*Final=*/false);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 12e98a33d07853..dc3bfa97eff399 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -479,6 +479,9 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
using namespace TemplateInstArgsHelpers;
const Decl *CurDecl = ND;
+ if (!CurDecl)
+ CurDecl = Decl::castFromDeclContext(DC);
+
if (Innermost) {
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
Final);
@@ -492,10 +495,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
// has a depth of 0.
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl))
HandleDefaultTempArgIntoTempTempParam(TTP, Result);
- CurDecl = DC ? Decl::castFromDeclContext(DC)
- : Response::UseNextDecl(CurDecl).NextDecl;
- } else if (!CurDecl)
- CurDecl = Decl::castFromDeclContext(DC);
+ CurDecl = Response::UseNextDecl(CurDecl).NextDecl;
+ }
while (!CurDecl->isFileContextDecl()) {
Response R;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index d530ed0847ae86..4855e8a23689ce 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -12,7 +12,6 @@
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DependentDiagnostic.h"
@@ -5277,26 +5276,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
- NamedDecl *ND = Function;
- DeclContext *DC = ND->getLexicalDeclContext();
- std::optional<ArrayRef<TemplateArgument>> Innermost;
- if (auto *Primary = Function->getPrimaryTemplate();
- Primary &&
- !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function) &&
- Function->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization) {
- auto It = llvm::find_if(Primary->redecls(),
- [](const RedeclarableTemplateDecl *RTD) {
- return cast<FunctionTemplateDecl>(RTD)
- ->isCompatibleWithDefinition();
- });
- assert(It != Primary->redecls().end() &&
- "Should't get here without a definition");
- DC = (*It)->getLexicalDeclContext();
- Innermost.emplace(Function->getTemplateSpecializationArgs()->asArray());
- }
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
- Function, DC, /*Final=*/false, Innermost, false, PatternDecl);
+ Function, Function->getLexicalDeclContext(), /*Final=*/false,
+ /*Innermost=*/std::nullopt, false, PatternDecl);
// Substitute into the qualifier; we can get a substitution failure here
// through evil use of alias templates.
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 7a15e60d87d83a..8210eb2143acf5 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1064,7 +1064,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit());
FD->setIsMultiVersion(FunctionDeclBits.getNextBit());
FD->setLateTemplateParsed(FunctionDeclBits.getNextBit());
- FD->setInstantiatedFromMemberTemplate(FunctionDeclBits.getNextBit());
FD->setFriendConstraintRefersToEnclosingTemplate(
FunctionDeclBits.getNextBit());
FD->setUsesSEHTry(FunctionDeclBits.getNextBit());
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 6a79444bdb9892..fa2294da95de8d 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -679,7 +679,7 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
}
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
- static_assert(DeclContext::NumFunctionDeclBits == 45,
+ static_assert(DeclContext::NumFunctionDeclBits == 44,
"You need to update the serializer after you change the "
"FunctionDeclBits");
@@ -785,7 +785,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
FunctionDeclBits.addBit(D->hasImplicitReturnZero());
FunctionDeclBits.addBit(D->isMultiVersion());
FunctionDeclBits.addBit(D->isLateTemplateParsed());
- FunctionDeclBits.addBit(D->isInstantiatedFromMemberTemplate());
FunctionDeclBits.addBit(D->FriendConstraintRefersToEnclosingTemplate());
FunctionDeclBits.addBit(D->usesSEHTry());
Record.push_back(FunctionDeclBits);
diff --git a/clang/test/SemaTemplate/GH55509.cpp b/clang/test/SemaTemplate/GH55509.cpp
deleted file mode 100644
index f95833fbed7b19..00000000000000
--- a/clang/test/SemaTemplate/GH55509.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s
-
-namespace t1 {
- template<int N> struct A {
- template<class C> friend auto cica(const A<N-1>&, C) {
- return N;
- }
- };
-
- template<> struct A<0> {
- template<class C> friend auto cica(const A<0>&, C);
- // expected-note at -1 {{declared here}}
- };
-
- void test() {
- cica(A<0>{}, 0);
- // expected-error at -1 {{function 'cica<int>' with deduced return type cannot be used before it is defined}}
-
- (void)A<1>{};
- cica(A<0>{}, 0);
- }
-} // namespace t1
-namespace t2 {
- template<int N> struct A {
- template<class C> friend auto cica(const A<N-1>&, C) {
- return N;
- }
- };
-
- template<> struct A<0> {
- template<class C> friend auto cica(const A<0>&, C);
- };
-
- template <int N, class = decltype(cica(A<N>{}, nullptr))>
- void MakeCica();
- // expected-note at -1 {{candidate function}}
-
- template <int N> void MakeCica(A<N+1> = {});
- // expected-note at -1 {{candidate function}}
-
- void test() {
- MakeCica<0>();
-
- MakeCica<0>();
- // expected-error at -1 {{call to 'MakeCica' is ambiguous}}
- }
-} // namespace t2
-namespace t3 {
- template<int N> struct A {
- template<class C> friend auto cica(const A<N-1>&, C) {
- return N-1;
- }
- };
-
- template<> struct A<0> {
- template<class C> friend auto cica(const A<0>&, C);
- };
-
- template <int N, class AT, class = decltype(cica(AT{}, nullptr))>
- static constexpr bool MakeCica(int);
-
- template <int N, class AT>
- static constexpr bool MakeCica(short, A<N+1> = {});
-
- template <int N, class AT = A<N>, class Val = decltype(MakeCica<N, AT>(0))>
- static constexpr bool has_cica = Val{};
-
- constexpr bool cica2 = has_cica<0> || has_cica<0>;
-} // namespace t3
-namespace t4 {
- template<int N> struct A {
- template<class C> friend auto cica(const A<N-1>&, C);
- };
-
- template<> struct A<0> {
- template<class C> friend auto cica(const A<0>&, C) {
- C a;
- }
- };
-
- template struct A<1>;
-
- void test() {
- cica(A<0>{}, 0);
- }
-} // namespace t4
-namespace regression1 {
- template <class> class A;
-
- template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>);
-
- template <class> struct A {
- friend void foo <>(A);
- };
-
- template struct A<int>;
-
- template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>) {}
-
- template void foo<int>(A<int>);
-} // namespace regression1
More information about the cfe-commits
mailing list