royjacobson updated this revision to Diff 451376.
royjacobson added a comment.

Don't regress on invalid (non-dependent) friend destructor declarations.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131541/new/

https://reviews.llvm.org/D131541

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaCXX/member-class-11.cpp


Index: clang/test/SemaCXX/member-class-11.cpp
===================================================================
--- clang/test/SemaCXX/member-class-11.cpp
+++ clang/test/SemaCXX/member-class-11.cpp
@@ -26,4 +26,35 @@
   ~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;
+};
+
+// FIXME: We should diagnose here.
+template <typename T>
+struct E {
+  friend T::S::~V();
+};
+
+struct Q {
+  struct S { ~S(); };
+};
+
+Q::S::~S() {
+  void foo(int);
+  foo(D<Q>::secret);
+}
+
+struct X {
+  ~X();
+};
+struct Y;
+
+struct Z {
+  friend X::~Y(); // expected-error {{expected the class name after '~' to 
name the enclosing class}}
+};
+
 }
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -11514,16 +11514,21 @@
     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)) {
+      // FIXME: We still don't diagnose on this case
+      // template <class T>
+      // struct A { friend T::S::~V(); };
+      if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None ||
+          !NewFD->isDependentContext()) {
+        QualType ClassType = Destructor->getThisObjectType();
+
+        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())


Index: clang/test/SemaCXX/member-class-11.cpp
===================================================================
--- clang/test/SemaCXX/member-class-11.cpp
+++ clang/test/SemaCXX/member-class-11.cpp
@@ -26,4 +26,35 @@
   ~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;
+};
+
+// FIXME: We should diagnose here.
+template <typename T>
+struct E {
+  friend T::S::~V();
+};
+
+struct Q {
+  struct S { ~S(); };
+};
+
+Q::S::~S() {
+  void foo(int);
+  foo(D<Q>::secret);
+}
+
+struct X {
+  ~X();
+};
+struct Y;
+
+struct Z {
+  friend X::~Y(); // expected-error {{expected the class name after '~' to name the enclosing class}}
+};
+
 }
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -11514,16 +11514,21 @@
     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)) {
+      // FIXME: We still don't diagnose on this case
+      // template <class T>
+      // struct A { friend T::S::~V(); };
+      if (NewFD->getFriendObjectKind() == Decl::FriendObjectKind::FOK_None ||
+          !NewFD->isDependentContext()) {
+        QualType ClassType = Destructor->getThisObjectType();
+
+        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())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to