r173873 - Provide a fixit for constexpr non-static data members.

David Blaikie dblaikie at gmail.com
Tue Jan 29 17:44:45 PST 2013


On Tue, Jan 29, 2013 at 5:38 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> 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$}}

Ah, right - thought I'd vaguely remembered there being such
functionality, but I couldn't find it at a glance.

Fixed in r173880.

Thanks,
- David

>
>>  };
>>  // 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