Author: Roy Jacobson Date: 2022-08-16T22:28:19+03:00 New Revision: 68786f06327519b30ab3ee2ba27451ec051bbb6f
URL: https://github.com/llvm/llvm-project/commit/68786f06327519b30ab3ee2ba27451ec051bbb6f DIFF: https://github.com/llvm/llvm-project/commit/68786f06327519b30ab3ee2ba27451ec051bbb6f.diff LOG: [Sema] Fix friend destructor declarations after D130936 I accidentally broke friend destructor declarations in D130936. Modify it to skip performing the destructor name check if we have a dependent friend declaration. Reviewed By: hubert.reinterpretcast Differential Revision: https://reviews.llvm.org/D131541 Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/test/SemaCXX/member-class-11.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 94009d33fa94e..7e7433d13d002 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11514,16 +11514,25 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { CheckConstructor(Constructor); } else if (CXXDestructorDecl *Destructor = - dyn_cast<CXXDestructorDecl>(NewFD)) { - CXXRecordDecl *Record = Destructor->getParent(); - QualType ClassType = Context.getTypeDeclType(Record); - - DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( - Context.getCanonicalType(ClassType)); - if (NewFD->getDeclName() != Name) { - Diag(NewFD->getLocation(), diag::err_destructor_name); - NewFD->setInvalidDecl(); - return Redeclaration; + dyn_cast<CXXDestructorDecl>(NewFD)) { + // We check here for invalid destructor names. + // If we have a friend destructor declaration that is dependent, we can't + // diagnose right away because cases like this are still valid: + // template <class T> struct A { friend T::X::~Y(); }; + // struct B { struct Y { ~Y(); }; using X = Y; }; + // template struct A<B>; + if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None || + !Destructor->getThisType()->isDependentType()) { + CXXRecordDecl *Record = Destructor->getParent(); + QualType ClassType = Context.getTypeDeclType(Record); + + DeclarationName Name = Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(ClassType)); + if (NewFD->getDeclName() != Name) { + Diag(NewFD->getLocation(), diag::err_destructor_name); + NewFD->setInvalidDecl(); + return Redeclaration; + } } } else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) { if (auto *TD = Guide->getDescribedFunctionTemplate()) diff --git a/clang/test/SemaCXX/member-class-11.cpp b/clang/test/SemaCXX/member-class-11.cpp index 68873ebad9d1d..20d6bce954f19 100644 --- a/clang/test/SemaCXX/member-class-11.cpp +++ b/clang/test/SemaCXX/member-class-11.cpp @@ -26,4 +26,56 @@ struct C { ~B(); // expected-error {{expected the class name after '~' to name the enclosing class}} }; +template <typename T> +struct D { + friend T::S::~S(); +private: + static constexpr int secret = 42; +}; + +template <typename T> +struct E { + friend T::S::~V(); +}; + +struct BadInstantiation { + struct S { + struct V {}; + }; +}; + +struct GoodInstantiation { + struct V { + ~V(); + }; + using S = V; +}; + +// FIXME: We should diagnose this while instantiating. +E<BadInstantiation> x; +E<GoodInstantiation> y; + +struct Q { + struct S { ~S(); }; +}; + +Q::S::~S() { + void foo(int); + foo(D<Q>::secret); +} + +struct X { + ~X(); +}; +struct Y; + +struct Z1 { + friend X::~Y(); // expected-error {{expected the class name after '~' to name the enclosing class}} +}; + +template <class T> +struct Z2 { + friend X::~Y(); // expected-error {{expected the class name after '~' to name the enclosing class}} +}; + } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits