[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