r173873 - Provide a fixit for constexpr non-static data members.
Richard Smith
richard at metafoo.co.uk
Tue Jan 29 17:38:07 PST 2013
On Tue, Jan 29, 2013 at 5:22 PM, David Blaikie <dblaikie at gmail.com> wrote:
> Author: dblaikie
> Date: Tue Jan 29 19:22:18 2013
> New Revision: 173873
>
> URL: http://llvm.org/viewvc/llvm-project?rev=173873&view=rev
> Log:
> Provide a fixit for constexpr non-static data members.
>
> If the member has an initializer, assume it was probably intended to be static
> and suggest/recover with that.
>
> If the member doesn't have an initializer, assume it was probably intended to
> be const instead of constexpr and suggest that.
>
> (if the attempt to apply these changes fails, don't make any suggestion &
> produce the same diagnostic experience as before. The only case where this can
> come up that I know of is with a mutable constexpr with an initializer, since
> mutable is incompatible with static (but it's already incompatible with
> const anyway))
>
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
> cfe/trunk/test/FixIt/fixit-cxx0x.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jan 29 19:22:18 2013
> @@ -1536,6 +1536,8 @@ def warn_cxx98_compat_constexpr : Warnin
> 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">;
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Jan 29 19:22:18 2013
> @@ -2166,8 +2166,6 @@ void Parser::ParseCXXClassMemberDeclarat
> 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::ParseCXXClassMemberDeclarat
> 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 :
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jan 29 19:22:18 2013
> @@ -9927,9 +9927,6 @@ FieldDecl *Sema::HandleField(Scope *S, R
>
> 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;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jan 29 19:22:18 2013
> @@ -1666,6 +1666,35 @@ Sema::ActOnCXXMemberDeclarator(Scope *S,
> 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,
> 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) {
>
> Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Tue Jan 29 19:22:18 2013
> @@ -25,8 +25,10 @@ constexpr notlit nl1; // expected-error
> 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}}
expected-error-re {{cannot be constexpr$}}
> };
> // typedef
> typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}}
>
> Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=173873&r1=173872&r2=173873&view=diff
> ==============================================================================
> --- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)
> +++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Tue Jan 29 19:22:18 2013
> @@ -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;
> + }
> + };
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list