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