[clang] d49a2d2 - [Clang] disallow the use of asterisks preceding constructor and destructor names (#122621)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 16 13:00:45 PST 2025


Author: Oleksandr T.
Date: 2025-01-16T13:00:41-08:00
New Revision: d49a2d2bc9c65c787bfa04ac8ece614da48a8cd5

URL: https://github.com/llvm/llvm-project/commit/d49a2d2bc9c65c787bfa04ac8ece614da48a8cd5
DIFF: https://github.com/llvm/llvm-project/commit/d49a2d2bc9c65c787bfa04ac8ece614da48a8cd5.diff

LOG: [Clang] disallow the use of asterisks preceding constructor and destructor names (#122621)

Fixes #121706

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/test/SemaCXX/constructor.cpp
    clang/test/SemaCXX/conversion-function.cpp
    clang/test/SemaCXX/destructor.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 14fe920985d6a9..eb3a271fa59d02 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -787,6 +787,7 @@ Improvements to Clang's diagnostics
       scope.Unlock();
       require(scope); // Warning!  Requires mu1.
     }
+- Diagnose invalid declarators in the declaration of constructors and destructors (#GH121706).
 
 Improvements to Clang's time-trace
 ----------------------------------

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7fa5ea8ed7aa8e..db54312ad965e8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2204,6 +2204,8 @@ def err_invalid_qualified_constructor : Error<
   "'%0' qualifier is not allowed on a constructor">;
 def err_ref_qualifier_constructor : Error<
   "ref-qualifier '%select{&&|&}0' is not allowed on a constructor">;
+def err_invalid_ctor_dtor_decl : Error<
+  "invalid %select{constructor|destructor}0 declaration">;
 
 def err_constructor_return_type : Error<
   "constructor cannot have a return type">;

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 92b0a48ba5589a..a867ed73bd4033 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -10757,6 +10757,22 @@ static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) {
   }
 }
 
+static void diagnoseInvalidDeclaratorChunks(Sema &S, Declarator &D,
+                                            unsigned Kind) {
+  if (D.isInvalidType() || D.getNumTypeObjects() <= 1)
+    return;
+
+  DeclaratorChunk &Chunk = D.getTypeObject(D.getNumTypeObjects() - 1);
+  if (Chunk.Kind == DeclaratorChunk::Paren ||
+      Chunk.Kind == DeclaratorChunk::Function)
+    return;
+
+  SourceLocation PointerLoc = Chunk.getSourceRange().getBegin();
+  S.Diag(PointerLoc, diag::err_invalid_ctor_dtor_decl)
+      << Kind << Chunk.getSourceRange();
+  D.setInvalidType();
+}
+
 QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
                                           StorageClass &SC) {
   bool isVirtual = D.getDeclSpec().isVirtualSpecified();
@@ -10792,6 +10808,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
   }
 
   checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor);
+  diagnoseInvalidDeclaratorChunks(*this, D, /*constructor*/ 0);
 
   // C++0x [class.ctor]p4:
   //   A constructor shall not be declared with a ref-qualifier.
@@ -10958,6 +10975,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
   }
 
   checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor);
+  diagnoseInvalidDeclaratorChunks(*this, D, /*destructor*/ 1);
 
   // C++0x [class.dtor]p2:
   //   A destructor shall not be declared with a ref-qualifier.

diff  --git a/clang/test/SemaCXX/constructor.cpp b/clang/test/SemaCXX/constructor.cpp
index abd7dbe18a0e6a..b069d55118f567 100644
--- a/clang/test/SemaCXX/constructor.cpp
+++ b/clang/test/SemaCXX/constructor.cpp
@@ -96,3 +96,80 @@ namespace PR38286 {
   template<typename> struct C; // expected-note {{non-type declaration found}}
   template<typename T> C<T>::~C() {} // expected-error {{identifier 'C' after '~' in destructor name does not name a type}}
 }
+
+namespace GH121706 {
+
+struct A {
+  *&A(); // expected-error {{invalid constructor declaration}}
+};
+
+struct B {
+  *&&B(); // expected-error {{invalid constructor declaration}}
+};
+
+struct C {
+  *const C(); // expected-error {{invalid constructor declaration}}
+};
+
+struct D {
+  *const *D(); // expected-error {{invalid constructor declaration}}
+};
+
+struct E {
+  *E::*E(); // expected-error {{invalid constructor declaration}}
+};
+
+struct F {
+  *F::*const F(); // expected-error {{invalid constructor declaration}}
+};
+
+struct G {
+  ****G(); // expected-error {{invalid constructor declaration}}
+};
+
+struct H {
+  **H(const H &); // expected-error {{invalid constructor declaration}}
+};
+
+struct I {
+  *I(I &&); // expected-error {{invalid constructor declaration}}
+};
+
+struct J {
+  *&(J)(); // expected-error {{invalid constructor declaration}}
+};
+
+struct K {
+  **&&(K)(); // expected-error {{invalid constructor declaration}}
+};
+
+struct L {
+  *L(L&& other); // expected-error {{invalid constructor declaration}}
+};
+
+struct M {
+  *M(M& other); // expected-error {{invalid constructor declaration}}
+};
+
+struct N {
+  int N(); // expected-error {{constructor cannot have a return type}}
+};
+
+struct O {
+  static O(); // expected-error {{constructor cannot be declared 'static'}}
+};
+
+struct P {
+  explicit P();
+};
+
+struct Q {
+  constexpr Q();
+};
+
+struct R {
+  R();
+  friend R::R();
+};
+
+}

diff  --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp
index 749e2fc1b452b6..b653a3bf1a1d29 100644
--- a/clang/test/SemaCXX/conversion-function.cpp
+++ b/clang/test/SemaCXX/conversion-function.cpp
@@ -494,3 +494,10 @@ using Result = B<int>::Lookup<int>;
 using Result = int (A2<int>::*)();
 }
 #endif
+
+namespace GH121706 {
+struct S {
+  *operator int();   // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}}
+  **operator char(); // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}}
+};
+}

diff  --git a/clang/test/SemaCXX/destructor.cpp b/clang/test/SemaCXX/destructor.cpp
index dfcd1b033af5a2..589616ef8e437b 100644
--- a/clang/test/SemaCXX/destructor.cpp
+++ b/clang/test/SemaCXX/destructor.cpp
@@ -586,4 +586,50 @@ struct Y : X {} y1{ }; // expected-error {{call to implicitly-deleted default co
                        // expected-note {{default constructor of 'Y' is implicitly deleted because base class 'X' has no destructor}}
 }
 
+namespace GH121706 {
+struct A {
+  *&~A(); // expected-error {{invalid destructor declaration}}
+};
+
+struct B {
+  *&&~B(); // expected-error {{invalid destructor declaration}}
+};
+
+struct C {
+  *const ~C(); // expected-error {{invalid destructor declaration}}
+};
+
+struct D {
+  *const * ~D(); // expected-error {{invalid destructor declaration}}
+};
+
+struct E {
+  *E::*~E(); // expected-error {{invalid destructor declaration}}
+};
+
+struct F {
+  *F::*const ~F(); // expected-error {{invalid destructor declaration}}
+};
+
+struct G {
+  ****~G(); // expected-error {{invalid destructor declaration}}
+};
+
+struct H {
+  **~H(); // expected-error {{invalid destructor declaration}}
+};
+
+struct I {
+  *~I(); // expected-error {{invalid destructor declaration}}
+};
+
+struct J {
+  *&~J(); // expected-error {{invalid destructor declaration}}
+};
+
+struct K {
+  **&&~K(); // expected-error {{invalid destructor declaration}}
+};
+}
+
 #endif // BE_THE_HEADER


        


More information about the cfe-commits mailing list