[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