def err_invalid_constexpr : Error<
"%select{function parameter|typedef|non-static data member}0 "
"cannot be constexpr">;
+def err_invalid_constexpr_member : Error<"non-static data member cannot be "
+ "constexpr%select{; did you intend to make it %select{const|static}0?|}1">;
def err_constexpr_tag : Error<
"%select{class|struct|interface|union|enum}0 cannot be marked constexpr">;
def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
HasInitializer = true;
if (!DeclaratorInfo.isDeclarationOfFunction() &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_static &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef)
HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
}
LateParsedAttrs.clear();
// Handle the initializer.
- if (HasInClassInit != ICIS_NoInit) {
+ if (HasInClassInit != ICIS_NoInit &&
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
+ DeclSpec::SCS_static) {
// The initializer was deferred; parse it and cache the tokens.
Diag(Tok, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nonstatic_member_init :
if (D.getDeclSpec().isThreadSpecified())
Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread);
- if (D.getDeclSpec().isConstexprSpecified())
- Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr)
- << 2;
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = 0;
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc);
+ if (DS.isConstexprSpecified() && isInstField) {
+ SemaDiagnosticBuilder B =
+ Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
+ SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
+ if (InitStyle == ICIS_NoInit) {
+ B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const");
+ D.getMutableDeclSpec().ClearConstexprSpec();
+ const char *PrevSpec;
+ unsigned DiagID;
+ bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc,
+ PrevSpec, DiagID, getLangOpts());
+ assert(!Failed && "Making a constexpr member const shouldn't fail");
+ } else {
+ B << 1;
+ const char *PrevSpec;
+ unsigned DiagID;
+ DeclSpec::SCS PrevSCS = DS.getStorageClassSpec();
+ if (D.getMutableDeclSpec().SetStorageClassSpec(
+ *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) {
+ assert(PrevSCS == DeclSpec::SCS_mutable &&
+ "This is the only DeclSpec that should fail to be applied");
+ B << 1;
+ } else {
+ B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static ");
+ isInstField = false;
+ }
+ }
+ }
+
NamedDecl *Member;
if (isInstField) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
InitStyle, AS);
assert(Member && "HandleField never returns null");
} else {
- assert(InitStyle == ICIS_NoInit);
+ assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static);
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member) {
void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}}
// non-static member
struct s2 {
- constexpr int mi1; // expected-error {{non-static data member cannot be constexpr}}
+ constexpr int mi1; // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
static constexpr int mi2; // expected-error {{requires an initializer}}
+ // FIXME: verify that there's no extra suffix in this error. -verify doesn't support anything like that at the moment as far as I know
+ mutable constexpr int mi3; // expected-error {{non-static data member cannot be constexpr}} expected-error {{'mutable' and 'const' cannot be mixed}}
};
// typedef
typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}}
struct d // expected-error {{expected ';' after struct}}
}
}
+
+namespace NonStaticConstexpr {
+ struct foo {
+ constexpr int i; // expected-error {{non-static data member cannot be constexpr; did you intend to make it const?}}
+ constexpr int j = 7; // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
+ foo() : i(3) {
+ }
+ static int get_j() {
+ return j;
+ }
+ };
+}