[clang] Revert "[clang] Track function template instantiation from definition (#110387)" (PR #111764)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 9 14:44:23 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Krystian Stasiowski (sdkrystian)
<details>
<summary>Changes</summary>
This reverts commit 4336f00f2156970cc0af2816331387a0a4039317.
---
Full diff: https://github.com/llvm/llvm-project/pull/111764.diff
12 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (-1)
- (modified) clang/include/clang/AST/Decl.h (-7)
- (modified) clang/include/clang/AST/DeclBase.h (+4-6)
- (modified) clang/include/clang/AST/DeclTemplate.h (-9)
- (modified) clang/include/clang/Sema/Sema.h (-6)
- (modified) clang/lib/AST/Decl.cpp (-1)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+16-1)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+3-14)
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+2-20)
- (modified) clang/lib/Serialization/ASTReaderDecl.cpp (-1)
- (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+1-2)
- (removed) clang/test/SemaTemplate/GH55509.cpp (-101)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a4bb303a2bc42b..29b9fe07f545f9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -468,7 +468,6 @@ Bug Fixes to C++ Support
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
-- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 6afc86710a8137..7ff35d73df5997 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2299,13 +2299,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 eb67dc03157e64..ee662ed73d7e0e 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1763,8 +1763,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)
@@ -1815,7 +1813,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
@@ -1826,12 +1824,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;
@@ -1845,7 +1843,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 2fb49ec1aea0d0..05739f39d2a496 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1008,15 +1008,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/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 86053bd7da1725..67a6dbeb520a89 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13017,12 +13017,6 @@ class Sema final : public SemaBase {
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
- void getTemplateInstantiationArgs(
- MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
- const DeclContext *DC = nullptr, bool Final = false,
- std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
- bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);
-
/// RAII object to handle the state changes required to synthesize
/// a function body.
class SynthesizedFunctionScope {
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 8f54b5f1589d4f..58d11a0312c505 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3067,7 +3067,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 dfae0d6cda0d9b..aa62cfa7dcbd17 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3928,7 +3928,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 261ef4edf17593..5b5e50f668b25d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -512,13 +512,13 @@ struct TemplateInstantiationArgumentCollecter
} // namespace
-void Sema::getTemplateInstantiationArgs(
- MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
- const DeclContext *DC, bool Final,
+MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
+ const NamedDecl *ND, const DeclContext *DC, bool Final,
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
bool ForConstraintInstantiation) {
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
// Accumulate the set of template argument lists in this structure.
+ MultiLevelTemplateArgumentList Result;
const Decl *CurDecl = ND;
if (!CurDecl)
@@ -529,17 +529,6 @@ void Sema::getTemplateInstantiationArgs(
do {
CurDecl = Collecter.Visit(const_cast<Decl *>(CurDecl));
} while (CurDecl);
-}
-
-MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
- const NamedDecl *ND, const DeclContext *DC, bool Final,
- std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
- bool ForConstraintInstantiation) {
- assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
- // Accumulate the set of template argument lists in this structure.
- MultiLevelTemplateArgumentList Result;
- getTemplateInstantiationArgs(Result, ND, DC, Final, Innermost,
- RelativeToPrimary, ForConstraintInstantiation);
return Result;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8cdf0b17d2dd2f..74f2152e441e18 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5224,26 +5224,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
RebuildTypeSourceInfoForDefaultSpecialMembers();
SetDeclDefaulted(Function, PatternDecl->getLocation());
} else {
- DeclContext *DC = Function;
- MultiLevelTemplateArgumentList TemplateArgs;
- if (auto *Primary = Function->getPrimaryTemplate();
- Primary &&
- !isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) {
- 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();
- if (Function->getTemplateSpecializationKind() !=
- TSK_ExplicitSpecialization)
- TemplateArgs.addOuterTemplateArguments(
- Function, Function->getTemplateSpecializationArgs()->asArray(),
- /*Final=*/false);
- }
- getTemplateInstantiationArgs(TemplateArgs, /*D=*/nullptr, DC);
+ MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+ Function, Function->getLexicalDeclContext());
// 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 a44df84a8bcef2..1ccc810f415eb4 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1087,7 +1087,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 dec93317dc7b37..f21cbd11b6ab89 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -626,7 +626,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");
@@ -732,7 +732,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
``````````
</details>
https://github.com/llvm/llvm-project/pull/111764
More information about the cfe-commits
mailing list