[clang] 68786f0 - [Sema] Fix friend destructor declarations after D130936

Roy Jacobson via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 16 12:28:27 PDT 2022


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}}
+};
+
 }


        


More information about the cfe-commits mailing list