[cfe-commits] r140801 - in /cfe/trunk: include/clang/Basic/DiagnosticGroups.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/class/class.static/class.static.data/p3.cpp test/CXX/dcl.dcl/dcl.spe
Chandler Carruth
chandlerc at google.com
Thu Sep 29 13:35:58 PDT 2011
On Thu, Sep 29, 2011 at 12:11 PM, Richard Smith
<richard-llvm at metafoo.co.uk>wrote:
> Author: rsmith
> Date: Thu Sep 29 14:11:37 2011
> New Revision: 140801
>
> URL: http://llvm.org/viewvc/llvm-project?rev=140801&view=rev
> Log:
> constexpr: semantic checking for constexpr variables.
>
> We had an extension which allowed const static class members of
> floating-point type to have in-class initializers, 'as a C++0x extension'.
> However, C++0x does not allow this. The extension has been kept, and
> extended to all literal types in C++0x mode (with a fixit to add the
> 'constexpr' specifier).
>
> Added:
> cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> 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/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
> cfe/trunk/test/FixIt/fixit-cxx0x.cpp
> cfe/trunk/test/SemaCXX/class.cpp
> cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Sep 29 14:11:37
> 2011
> @@ -303,9 +303,7 @@
>
> // A warning group for warnings about using C++0x features as extensions
> in
> // earlier C++ versions.
> -def CXX0xStaticNonIntegralInitializer :
> - DiagGroup<"c++0x-static-nonintegral-init">;
> -def CXX0x : DiagGroup<"c++0x-extensions",
> [CXX0xStaticNonIntegralInitializer]>;
> +def CXX0x : DiagGroup<"c++0x-extensions">;
>
This could really use a better name than 'CXX0x'...
> def DelegatingCtorCycles :
> DiagGroup<"delegating-ctor-cycles">;
>
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 29
> 14:11:37 2011
> @@ -1186,7 +1186,15 @@
> def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;
> def err_constexpr_no_declarators : Error<
> "constexpr can only be used in variable and function declarations">;
> -
> +def err_invalid_constexpr_var_decl : Error<
> + "constexpr variable declaration must be a definition">;
> +def err_constexpr_var_requires_init : Error<
> + "declaration of constexpr variable %0 requires an initializer">;
> +def err_constexpr_initialized_static_member : Error<
> + "definition of initialized static data member %0 cannot be marked
> constexpr">;
> +def err_constexpr_var_requires_const_init : Error<
> + "constexpr variable %0 must be initialized by a constant expression">;
> +
> // Objective-C++
> def err_objc_decls_may_only_appear_in_global_scope : Error<
> "Objective-C declarations may only appear in global scope">;
> @@ -4072,8 +4080,12 @@
> def err_in_class_initializer_bad_type : Error<
> "static data member of type %0 must be initialized out of line">;
> def ext_in_class_initializer_float_type : ExtWarn<
> - "in-class initializer for static data member of type %0 "
> - "is a C++0x extension">, InGroup<CXX0xStaticNonIntegralInitializer>;
> + "in-class initializer for static data member of type %0 not allowed, "
> + "accepted as an extension">, InGroup<DiagGroup<"static-member-init">>;
> +def ext_in_class_initializer_literal_type : ExtWarn<
> + "in-class initializer for static data member of type %0 requires "
> + "'constexpr' specifier, accepted as an extension">,
> + InGroup<DiagGroup<"static-member-init">>;
> def err_in_class_initializer_non_constant : Error<
> "in-class initializer is not a constant expression">;
>
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 29 14:11:37 2011
> @@ -3833,8 +3833,36 @@
> }
>
> if (D.getDeclSpec().isConstexprSpecified()) {
> - // FIXME: check this is a valid use of constexpr.
> - NewVD->setConstexpr(true);
> + // FIXME: once we know whether there's an initializer, apply this to
> + // static data members too.
> + if (!NewVD->isStaticDataMember() &&
> + !NewVD->isThisDeclarationADefinition()) {
> + // 'constexpr' is redundant and ill-formed on a non-defining
> declaration
> + // of a variable. Suggest replacing it with 'const' if
> appropriate.
> + SourceLocation ConstexprLoc =
> D.getDeclSpec().getConstexprSpecLoc();
> + SourceRange ConstexprRange(ConstexprLoc, ConstexprLoc);
> + // If the declarator is complex, we need to move the keyword to
> the
> + // innermost chunk as we switch it from 'constexpr' to 'const'.
> + int Kind = DeclaratorChunk::Paren;
> + for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
> + Kind = D.getTypeObject(I).Kind;
> + if (Kind != DeclaratorChunk::Paren)
> + break;
> + }
> + if ((D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) ||
> + Kind == DeclaratorChunk::Reference)
> + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
> + << FixItHint::CreateRemoval(ConstexprRange);
> + else if (Kind == DeclaratorChunk::Paren)
> + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
> + << FixItHint::CreateReplacement(ConstexprRange, "const");
> + else
> + Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)
> + << FixItHint::CreateRemoval(ConstexprRange)
> + << FixItHint::CreateInsertion(D.getIdentifierLoc(), "const ");
> + } else {
> + NewVD->setConstexpr(true);
> + }
> }
> }
>
> @@ -5796,11 +5824,26 @@
> // A member-declarator can contain a constant-initializer only
> // if it declares a static member (9.4) of const integral or
> // const enumeration type, see 9.4.2.
> + //
> + // C++0x [class.static.data]p3:
> + // If a non-volatile const static data member is of integral or
> + // enumeration type, its declaration in the class definition can
> + // specify a brace-or-equal-initializer in which every
> initalizer-clause
> + // that is an assignment-expression is a constant expression. A
> static
> + // data member of literal type can be declared in the class
> definition
> + // with the constexpr specifier; if so, its declaration shall
> specify a
> + // brace-or-equal-initializer in which every initializer-clause that
> is
> + // an assignment-expression is a constant expression.
> QualType T = VDecl->getType();
>
> // Do nothing on dependent types.
> if (T->isDependentType()) {
>
> + // Allow any 'static constexpr' members, whether or not they are of
> literal
> + // type. We separately check that the initializer is a constant
> expression,
> + // which implicitly requires the member to be of literal type.
> + } else if (VDecl->isConstexpr()) {
> +
> // Require constness.
> } else if (!T.isConstQualified()) {
> Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
> @@ -5809,6 +5852,9 @@
>
> // We allow integer constant expressions in all cases.
> } else if (T->isIntegralOrEnumerationType()) {
> + // FIXME: In C++0x, a non-constexpr const static data member with an
> + // in-class initializer cannot be volatile.
> +
> // Check whether the expression is a constant expression.
> SourceLocation Loc;
> if (Init->isValueDependent())
> @@ -5828,31 +5874,28 @@
> VDecl->setInvalidDecl();
> }
>
> - // We allow floating-point constants as an extension in C++03, and
> - // C++0x has far more complicated rules that we don't really
> - // implement fully.
> - } else {
> - bool Allowed = false;
> - if (getLangOptions().CPlusPlus0x) {
> - Allowed = T->isLiteralType();
> - } else if (T->isFloatingType()) { // also permits complex, which is
> ok
> - Diag(VDecl->getLocation(),
> diag::ext_in_class_initializer_float_type)
> - << T << Init->getSourceRange();
> - Allowed = true;
> - }
> + // Suggest adding 'constexpr' in C++0x for literal types.
> + } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) {
> + Diag(VDecl->getLocation(),
> diag::ext_in_class_initializer_literal_type)
> + << T << Init->getSourceRange()
> + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
>
This FixItHint needs to be on a note, rather than the ext-warn; we don't
recover here by parsing this *as* a constexpr (nor would that be entirely
appropriate I suspect)...
> + VDecl->setConstexpr(true);
> +
> + // We allow floating-point constants as an extension.
> + } else if (T->isFloatingType()) { // also permits complex, which is ok
> + Diag(VDecl->getLocation(),
> diag::ext_in_class_initializer_float_type)
> + << T << Init->getSourceRange();
>
> - if (!Allowed) {
> - Diag(VDecl->getLocation(),
> diag::err_in_class_initializer_bad_type)
> - << T << Init->getSourceRange();
> - VDecl->setInvalidDecl();
> -
> - // TODO: there are probably expressions that pass here that
> shouldn't.
> - } else if (!Init->isValueDependent() &&
> - !Init->isConstantInitializer(Context, false)) {
> + if (!Init->isValueDependent() &&
> + !Init->isConstantInitializer(Context, false)) {
> Diag(Init->getExprLoc(),
> diag::err_in_class_initializer_non_constant)
> << Init->getSourceRange();
> VDecl->setInvalidDecl();
> }
> + } else {
> + Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)
> + << T << Init->getSourceRange();
> + VDecl->setInvalidDecl();
> }
> } else if (VDecl->isFileVarDecl()) {
> if (VDecl->getStorageClassAsWritten() == SC_Extern &&
> @@ -5893,6 +5936,17 @@
>
> if (!VDecl->isInvalidDecl())
> checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);
> +
> + if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() &&
> + !VDecl->getType()->isDependentType() &&
> + !Init->isTypeDependent() && !Init->isValueDependent() &&
> + !Init->isConstantInitializer(Context,
> + VDecl->getType()->isReferenceType())) {
> + // FIXME: Improve this diagnostic to explain why the initializer is
> not
> + // a constant expression.
> + Diag(VDecl->getLocation(),
> diag::err_constexpr_var_requires_const_init)
> + << VDecl << Init->getSourceRange();
> + }
>
> Init = MaybeCreateExprWithCleanups(Init);
> // Attach the initializer to the decl.
> @@ -5958,6 +6012,24 @@
> return;
> }
>
> + // C++0x [dcl.constexpr]p9: An object or reference declared constexpr
> must
> + // have an initializer.
> + // C++0x [class.static.data]p3: A static data member can be declared
> with
> + // the constexpr specifier; if so, its declaration shall specify
> + // a brace-or-equal-initializer.
> + if (Var->isConstexpr()) {
> + // FIXME: Provide fix-its to convert the constexpr to const.
> + if (Var->isStaticDataMember() && Var->getAnyInitializer()) {
> + Diag(Var->getLocation(),
> diag::err_constexpr_initialized_static_member)
> + << Var->getDeclName();
> + } else {
> + Diag(Var->getLocation(), diag::err_constexpr_var_requires_init)
> + << Var->getDeclName();
> + }
> + Var->setInvalidDecl();
> + return;
> + }
> +
> switch (Var->isThisDeclarationADefinition()) {
> case VarDecl::Definition:
> if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
> @@ -6151,9 +6223,8 @@
> case SC_OpenCLWorkGroupLocal:
> llvm_unreachable("Unexpected storage class");
> }
> - // FIXME: constexpr isn't allowed here.
> - //if (DS.isConstexprSpecified())
> - // Error = 5;
> + if (VD->isConstexpr())
> + Error = 5;
> if (Error != -1) {
> Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)
> << VD->getDeclName() << Error;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 29 14:11:37 2011
> @@ -1239,14 +1239,8 @@
> if (Init)
> AddInitializerToDecl(Member, Init, false,
> DS.getTypeSpecType() == DeclSpec::TST_auto);
> - else if (DS.getTypeSpecType() == DeclSpec::TST_auto &&
> - DS.getStorageClassSpec() == DeclSpec::SCS_static) {
> - // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a
> static
> - // data member if a brace-or-equal-initializer is provided.
> - Diag(Loc, diag::err_auto_var_requires_init)
> - << Name << cast<ValueDecl>(Member)->getType();
> - Member->setInvalidDecl();
> - }
> + else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)
> + ActOnUninitializedDecl(Member, DS.getTypeSpecType() ==
> DeclSpec::TST_auto);
>
> FinalizeDeclaration(Member);
>
> @@ -8727,10 +8721,21 @@
> return;
> }
>
> - CheckImplicitConversions(Result.get(), LParenLoc);
> + Expr *Init = Result.get();
> + CheckImplicitConversions(Init, LParenLoc);
>
> - Result = MaybeCreateExprWithCleanups(Result);
> - VDecl->setInit(Result.takeAs<Expr>());
> + if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() &&
> + !Init->isValueDependent() &&
> + !Init->isConstantInitializer(Context,
> + VDecl->getType()->isReferenceType())) {
> + // FIXME: Improve this diagnostic to explain why the initializer is
> not
> + // a constant expression.
> + Diag(VDecl->getLocation(),
> diag::err_constexpr_var_requires_const_init)
> + << VDecl << Init->getSourceRange();
> + }
> +
> + Init = MaybeCreateExprWithCleanups(Init);
> + VDecl->setInit(Init);
> VDecl->setCXXDirectInitializer(true);
>
> CheckCompleteVariableDeclaration(VDecl);
>
> Added: cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp?rev=140801&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp (added)
> +++ cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp Thu Sep
> 29 14:11:37 2011
> @@ -0,0 +1,24 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
> +
> +struct NonLit {
> + NonLit();
> +};
> +
> +struct S {
> + static constexpr int a = 0;
> + static constexpr int b; // expected-error {{declaration of constexpr
> variable 'b' requires an initializer}}
> +
> + static constexpr int c = 0;
> + static const int d;
> +
> + static constexpr double e = 0.0; // ok
> + static const double f = 0.0; // expected-warning {{accepted as an
> extension}}
> + static char *const g = 0; // expected-warning {{accepted as an
> extension}}
> + static const NonLit h = NonLit(); // expected-error {{must be
> initialized out of line}}
> +};
> +
> +constexpr int S::a; // expected-error {{definition of initialized static
> data member 'a' cannot be marked constexpr}}
> +constexpr int S::b = 0;
> +
> +const int S::c;
> +constexpr int S::d = 0;
>
> 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=140801&r1=140800&r2=140801&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 Thu Sep 29
> 14:11:37 2011
> @@ -11,19 +11,22 @@
> constexpr int i1 = 0;
> constexpr int f1() { return 0; }
> struct s1 {
> - constexpr static int mi = 0;
> + constexpr static int mi1 = 0;
> + const static int mi2;
> };
> +constexpr int s1::mi2 = 0;
>
> // invalid declarations
> // not a definition of an object
> -constexpr extern int i2; // x
> +constexpr extern int i2; // expected-error {{constexpr variable
> declaration must be a definition}}
> // not a literal type
> -constexpr notlit nl1; // x
> +constexpr notlit nl1; // expected-error {{declaration of constexpr
> variable 'nl1' requires an initializer}}
> // function parameters
> void f2(constexpr int i) {} // expected-error {{function parameter cannot
> be constexpr}}
> // non-static member
> struct s2 {
> - constexpr int mi; // expected-error {{non-static data member cannot be
> constexpr}}
> + constexpr int mi1; // expected-error {{non-static data member cannot be
> constexpr}}
> + static constexpr int mi2; // expected-error {{requires an initializer}}
> };
> // typedef
> typedef constexpr int CI; // expected-error {{typedef cannot be
> constexpr}}
> @@ -63,7 +66,8 @@
> template <>
> notlit ft(notlit nl) { return nl; }
>
> -constexpr int i3 = ft(1);
> +// FIXME: The initializer is a constant expression.
> +constexpr int i3 = ft(1); // unexpected-error {{must be initialized by a
> constant expression}}
>
> void test() {
> // ignore constexpr when instantiating with non-literal
> @@ -85,17 +89,17 @@
> : x(square(a)), y(square(a))
> { }
>
> -constexpr pixel small(2); // x (no definition of square(int) yet, so can't
> - // constexpr-eval pixel(int))
> +constexpr pixel small(2); // expected-error {{must be initialized by a
> constant expression}}
>
> constexpr int square(int x) {
> return x * x;
> }
>
> -constexpr pixel large(4); // now valid
> +// FIXME: The initializer is a constant expression.
> +constexpr pixel large(4); // unexpected-error {{must be initialized by a
> constant expression}}
>
> int next(constexpr int x) { // expected-error {{function parameter cannot
> be constexpr}}
> return x + 1;
> }
>
> -extern constexpr int memsz; // x
> +extern constexpr int memsz; // expected-error {{constexpr variable
> declaration must be a definition}}
>
> Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp?rev=140801&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp (added)
> +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp Thu Sep 29
> 14:11:37 2011
> @@ -0,0 +1,37 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
> +
> +// A constexpr specifier used in an object declaration declares the object
> as
> +// const.
> +constexpr int a = 0;
> +extern const int a;
> +
> +int i;
> +constexpr int *b = &i;
> +extern int *const b;
> +
> +constexpr int &c = i;
> +extern int &c;
> +
> +constexpr int (*d)(int) = 0;
> +extern int (*const d)(int);
> +
> +// A variable declaration which uses the constexpr specifier shall have an
> +// initializer and shall be initialized by a constant expression.
> +constexpr int ni1; // expected-error {{declaration of constexpr variable
> 'ni1' requires an initializer}}
> +constexpr struct C { C(); } ni2; // expected-error {{declaration of
> constexpr variable 'ni2' requires an initializer}}
> +constexpr double &ni3; // expected-error {{declaration of constexpr
> variable 'ni3' requires an initializer}}
> +
> +constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must
> be initialized by a constant expression}}
> +constexpr C nc2 = C(); // expected-error {{constexpr variable 'nc2' must
> be initialized by a constant expression}}
> +int &f();
> +constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3'
> must be initialized by a constant expression}}
> +constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be
> initialized by a constant expression}}
> +constexpr C nc5((C())); // expected-error {{constexpr variable 'nc5' must
> be initialized by a constant expression}}
> +int &f();
> +constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must
> be initialized by a constant expression}}
> +
> +struct pixel {
> + int x, y;
> +};
> +constexpr pixel ur = { 1294, 1024 }; // ok
> +constexpr pixel origin; // expected-error {{requires an
> initializer}}
>
> Modified: cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp (original)
> +++ cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp Thu Sep 29
> 14:11:37 2011
> @@ -100,8 +100,7 @@
> for (extern int a : A()) {} // expected-error {{loop variable 'a' may not
> be declared 'extern'}}
> for (static int a : A()) {} // expected-error {{loop variable 'a' may not
> be declared 'static'}}
> for (register int a : A()) {} // expected-error {{loop variable 'a' may
> not be declared 'register'}}
> - // FIXME: when clang supports constexpr, this should be rejected.
> - for (constexpr int a : A()) {} // desired-error {{loop variable 'a' may
> not be declared 'constexpr'}}
> + for (constexpr int a : A()) {} // expected-error {{loop variable 'a' may
> not be declared 'constexpr'}}
>
> struct NoBeginADL {
> null_t alt_end();
>
> Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)
> +++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Thu Sep 29 14:11:37 2011
> @@ -1,6 +1,6 @@
> // RUN: %clang_cc1 -verify -std=c++0x %s
> // RUN: cp %s %t
> -// RUN: not %clang_cc1 -x c++ -std=c++0x -fixit %t
> +// RUN: not %clang_cc1 -x c++ -std=c++0x -Werror -fixit %t
> // RUN: %clang_cc1 -Wall -pedantic -x c++ -std=c++0x %t
>
> /* This is a test of the various code modification hints that only
> @@ -17,3 +17,45 @@
> using ::T = void; // expected-error {{name defined in alias declaration
> must be an identifier}}
> using typename U = void; // expected-error {{name defined in alias
> declaration must be an identifier}}
> using typename ::V = void; // expected-error {{name defined in alias
> declaration must be an identifier}}
> +
> +namespace Constexpr {
> + extern constexpr int a; // expected-error {{must be a definition}}
> + // -> extern const int a;
> +
> + extern constexpr int *b; // expected-error {{must be a definition}}
> + // -> extern int *const b;
> +
> + extern constexpr int &c; // expected-error {{must be a definition}}
> + // -> extern int &b;
> +
> + extern constexpr const int d; // expected-error {{must be a definition}}
> + // -> extern const int d;
> +
> + int z;
> + constexpr int a = 0;
> + constexpr int *b = &z;
> + constexpr int &c = z;
> + constexpr int d = a;
> +
> + // FIXME: Provide FixIts for static data members too.
> +#if 0
> + struct S {
> + static constexpr int a = 0;
> +
> + static constexpr int b; // xpected-error {{requires an initializer}}
> + // -> const int b;
> + };
> +
> + constexpr int S::a; // xpected-error {{requires an initializer}}
> + // -> const int S::a;
> +
> + constexpr int S::b = 0;
> +#endif
> +
> + struct S {
> + static const double d = 0.0; // expected-warning {{accepted as an
> extension}}
> + // -> constexpr static const double d = 0.0;
> + static char *const p = 0; // expected-warning {{accepted as an
> extension}}
> + // -> constexpr static char *const p = 0;
> + };
> +}
>
> Modified: cfe/trunk/test/SemaCXX/class.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/class.cpp (original)
> +++ cfe/trunk/test/SemaCXX/class.cpp Thu Sep 29 14:11:37 2011
> @@ -172,8 +172,8 @@
> float foo();
>
> struct A {
> - static const float x = 5.0f; // expected-warning {{in-class
> initializer for static data member of type 'const float' is a C++0x
> extension}}
> - static const float y = foo(); // expected-warning {{in-class
> initializer for static data member of type 'const float' is a C++0x
> extension}} expected-error {{in-class initializer is not a constant
> expression}}
> + static const float x = 5.0f; // expected-warning {{in-class
> initializer for static data member of type 'const float' not allowed}}
> + static const float y = foo(); // expected-warning {{in-class
> initializer for static data member of type 'const float' not allowed}}
> expected-error {{in-class initializer is not a constant expression}}
> };
> }
>
>
> Modified: cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=140801&r1=140800&r2=140801&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp Thu Sep 29
> 14:11:37 2011
> @@ -11,7 +11,7 @@
>
> template<typename T>
> class Y {
> - static const T value = 0; // expected-warning{{in-class initializer for
> static data member of type 'const float' is a C++0x extension}}
> + static const T value = 0; // expected-warning{{in-class initializer for
> static data member of type 'const float' not allowed, accepted as an
> extension}}
> };
>
> Y<float> fy; // expected-note{{in instantiation of template class
> 'Y<float>' requested here}}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110929/c10d9efe/attachment.html>
More information about the cfe-commits
mailing list