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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits