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