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@-1 {{declared here}} - }; - - void test() { - cica(A<0>{}, 0); - // expected-error@-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@-1 {{candidate function}} - - template <int N> void MakeCica(A<N+1> = {}); - // expected-note@-1 {{candidate function}} - - void test() { - MakeCica<0>(); - - MakeCica<0>(); - // expected-error@-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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits