[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