Skip to content
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ Improvements to Clang's diagnostics
scope.Unlock();
require(scope); // Warning! Requires mu1.
}
- Clang now disallows the use of asterisks preceding constructor and destructor names (#GH121706).

Improvements to Clang's time-trace
----------------------------------
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,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_constructor_decl : Error<
"invalid constructor declaration">;

def err_constructor_return_type : Error<
"constructor cannot have a return type">;
Expand All @@ -2223,6 +2225,8 @@ def err_destructor_not_member : Error<
def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">;
def err_invalid_qualified_destructor : Error<
"'%0' qualifier is not allowed on a destructor">;
def err_invalid_destructor_decl : Error<
"invalid destructor declaration">;
def err_ref_qualifier_destructor : Error<
"ref-qualifier '%select{&&|&}0' is not allowed on a destructor">;
def err_destructor_return_type : Error<"destructor cannot have a return type">;
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10757,6 +10757,21 @@ static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) {
}
}

static void diagnoseInvalidDeclaratorChunks(Sema &S, Declarator &D,
unsigned DiagID) {
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, DiagID) << Chunk.getSourceRange();
D.setInvalidType();
}

QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
StorageClass &SC) {
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
Expand Down Expand Up @@ -10792,6 +10807,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
}

checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor);
diagnoseInvalidDeclaratorChunks(*this, D, diag::err_invalid_constructor_decl);

// C++0x [class.ctor]p4:
// A constructor shall not be declared with a ref-qualifier.
Expand Down Expand Up @@ -10958,6 +10974,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
}

checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor);
diagnoseInvalidDeclaratorChunks(*this, D, diag::err_invalid_destructor_decl);

// C++0x [class.dtor]p2:
// A destructor shall not be declared with a ref-qualifier.
Expand Down
46 changes: 46 additions & 0 deletions clang/test/SemaCXX/constructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,49 @@ 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}}
};
}
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
Loading