Skip to content

Commit

Permalink
[Clang] disallow the use of asterisks preceding constructor and destr…
Browse files Browse the repository at this point in the history
…uctor names (llvm#122621)

Fixes llvm#121706
  • Loading branch information
a-tarasyuk authored and DKLoehr committed Jan 17, 2025
1 parent e0ba3bd commit 12781b6
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
----------------------------------
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
77 changes: 77 additions & 0 deletions clang/test/SemaCXX/constructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
};

}
7 changes: 7 additions & 0 deletions clang/test/SemaCXX/conversion-function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'}}
};
}
46 changes: 46 additions & 0 deletions clang/test/SemaCXX/destructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 12781b6

Please sign in to comment.