[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