diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 31 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 4 | ||||
-rw-r--r-- | test/FixIt/fixit-cxx0x.cpp | 12 |
6 files changed, 50 insertions, 8 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 326b96e626..a3b03033d2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1536,6 +1536,8 @@ def warn_cxx98_compat_constexpr : Warning< 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">; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 5af3ea741a..4956c1095c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2166,8 +2166,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, 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; } @@ -2218,7 +2216,9 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, 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 : diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 60b67602c3..2c09c88b20 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9927,9 +9927,6 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, 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; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 448d083aaf..59d1e91f36 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1666,6 +1666,35 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, 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(); @@ -1720,7 +1749,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, 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) { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index 6820fc6cb8..2a12f92a8d 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -25,8 +25,10 @@ constexpr notlit nl1; // expected-error {{constexpr variable cannot have non-lit 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}} diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp index a173ce4bc2..3884c64516 100644 --- a/test/FixIt/fixit-cxx0x.cpp +++ b/test/FixIt/fixit-cxx0x.cpp @@ -120,3 +120,15 @@ namespace MissingSemi { 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; + } + }; +} |