Skip to content

Commit d49a2d2

Browse files
authored
[Clang] disallow the use of asterisks preceding constructor and destructor names (llvm#122621)
Fixes llvm#121706
1 parent 9a6433f commit d49a2d2

File tree

6 files changed

+151
-0
lines changed

6 files changed

+151
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ Improvements to Clang's diagnostics
787787
scope.Unlock();
788788
require(scope); // Warning! Requires mu1.
789789
}
790+
- Diagnose invalid declarators in the declaration of constructors and destructors (#GH121706).
790791

791792
Improvements to Clang's time-trace
792793
----------------------------------

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,8 @@ def err_invalid_qualified_constructor : Error<
22042204
"'%0' qualifier is not allowed on a constructor">;
22052205
def err_ref_qualifier_constructor : Error<
22062206
"ref-qualifier '%select{&&|&}0' is not allowed on a constructor">;
2207+
def err_invalid_ctor_dtor_decl : Error<
2208+
"invalid %select{constructor|destructor}0 declaration">;
22072209

22082210
def err_constructor_return_type : Error<
22092211
"constructor cannot have a return type">;

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10757,6 +10757,22 @@ static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) {
1075710757
}
1075810758
}
1075910759

10760+
static void diagnoseInvalidDeclaratorChunks(Sema &S, Declarator &D,
10761+
unsigned Kind) {
10762+
if (D.isInvalidType() || D.getNumTypeObjects() <= 1)
10763+
return;
10764+
10765+
DeclaratorChunk &Chunk = D.getTypeObject(D.getNumTypeObjects() - 1);
10766+
if (Chunk.Kind == DeclaratorChunk::Paren ||
10767+
Chunk.Kind == DeclaratorChunk::Function)
10768+
return;
10769+
10770+
SourceLocation PointerLoc = Chunk.getSourceRange().getBegin();
10771+
S.Diag(PointerLoc, diag::err_invalid_ctor_dtor_decl)
10772+
<< Kind << Chunk.getSourceRange();
10773+
D.setInvalidType();
10774+
}
10775+
1076010776
QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
1076110777
StorageClass &SC) {
1076210778
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
@@ -10792,6 +10808,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
1079210808
}
1079310809

1079410810
checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor);
10811+
diagnoseInvalidDeclaratorChunks(*this, D, /*constructor*/ 0);
1079510812

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

1096010977
checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor);
10978+
diagnoseInvalidDeclaratorChunks(*this, D, /*destructor*/ 1);
1096110979

1096210980
// C++0x [class.dtor]p2:
1096310981
// A destructor shall not be declared with a ref-qualifier.

clang/test/SemaCXX/constructor.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,80 @@ namespace PR38286 {
9696
template<typename> struct C; // expected-note {{non-type declaration found}}
9797
template<typename T> C<T>::~C() {} // expected-error {{identifier 'C' after '~' in destructor name does not name a type}}
9898
}
99+
100+
namespace GH121706 {
101+
102+
struct A {
103+
*&A(); // expected-error {{invalid constructor declaration}}
104+
};
105+
106+
struct B {
107+
*&&B(); // expected-error {{invalid constructor declaration}}
108+
};
109+
110+
struct C {
111+
*const C(); // expected-error {{invalid constructor declaration}}
112+
};
113+
114+
struct D {
115+
*const *D(); // expected-error {{invalid constructor declaration}}
116+
};
117+
118+
struct E {
119+
*E::*E(); // expected-error {{invalid constructor declaration}}
120+
};
121+
122+
struct F {
123+
*F::*const F(); // expected-error {{invalid constructor declaration}}
124+
};
125+
126+
struct G {
127+
****G(); // expected-error {{invalid constructor declaration}}
128+
};
129+
130+
struct H {
131+
**H(const H &); // expected-error {{invalid constructor declaration}}
132+
};
133+
134+
struct I {
135+
*I(I &&); // expected-error {{invalid constructor declaration}}
136+
};
137+
138+
struct J {
139+
*&(J)(); // expected-error {{invalid constructor declaration}}
140+
};
141+
142+
struct K {
143+
**&&(K)(); // expected-error {{invalid constructor declaration}}
144+
};
145+
146+
struct L {
147+
*L(L&& other); // expected-error {{invalid constructor declaration}}
148+
};
149+
150+
struct M {
151+
*M(M& other); // expected-error {{invalid constructor declaration}}
152+
};
153+
154+
struct N {
155+
int N(); // expected-error {{constructor cannot have a return type}}
156+
};
157+
158+
struct O {
159+
static O(); // expected-error {{constructor cannot be declared 'static'}}
160+
};
161+
162+
struct P {
163+
explicit P();
164+
};
165+
166+
struct Q {
167+
constexpr Q();
168+
};
169+
170+
struct R {
171+
R();
172+
friend R::R();
173+
};
174+
175+
}

clang/test/SemaCXX/conversion-function.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,10 @@ using Result = B<int>::Lookup<int>;
494494
using Result = int (A2<int>::*)();
495495
}
496496
#endif
497+
498+
namespace GH121706 {
499+
struct S {
500+
*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'}}
501+
**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'}}
502+
};
503+
}

clang/test/SemaCXX/destructor.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,4 +586,50 @@ struct Y : X {} y1{ }; // expected-error {{call to implicitly-deleted default co
586586
// expected-note {{default constructor of 'Y' is implicitly deleted because base class 'X' has no destructor}}
587587
}
588588

589+
namespace GH121706 {
590+
struct A {
591+
*&~A(); // expected-error {{invalid destructor declaration}}
592+
};
593+
594+
struct B {
595+
*&&~B(); // expected-error {{invalid destructor declaration}}
596+
};
597+
598+
struct C {
599+
*const ~C(); // expected-error {{invalid destructor declaration}}
600+
};
601+
602+
struct D {
603+
*const * ~D(); // expected-error {{invalid destructor declaration}}
604+
};
605+
606+
struct E {
607+
*E::*~E(); // expected-error {{invalid destructor declaration}}
608+
};
609+
610+
struct F {
611+
*F::*const ~F(); // expected-error {{invalid destructor declaration}}
612+
};
613+
614+
struct G {
615+
****~G(); // expected-error {{invalid destructor declaration}}
616+
};
617+
618+
struct H {
619+
**~H(); // expected-error {{invalid destructor declaration}}
620+
};
621+
622+
struct I {
623+
*~I(); // expected-error {{invalid destructor declaration}}
624+
};
625+
626+
struct J {
627+
*&~J(); // expected-error {{invalid destructor declaration}}
628+
};
629+
630+
struct K {
631+
**&&~K(); // expected-error {{invalid destructor declaration}}
632+
};
633+
}
634+
589635
#endif // BE_THE_HEADER

0 commit comments

Comments
 (0)