<div class="gmail_quote">On Thu, Sep 29, 2011 at 12:11 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Author: rsmith<br>
Date: Thu Sep 29 14:11:37 2011<br>
New Revision: 140801<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=140801&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=140801&view=rev</a><br>
Log:<br>
constexpr: semantic checking for constexpr variables.<br>
<br>
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).<br>

<br>
Added:<br>
    cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp<br>
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp<br>
    cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp<br>
    cfe/trunk/test/FixIt/fixit-cxx0x.cpp<br>
    cfe/trunk/test/SemaCXX/class.cpp<br>
    cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Thu Sep 29 14:11:37 2011<br>
@@ -303,9 +303,7 @@<br>
<br>
 // A warning group for warnings about using C++0x features as extensions in<br>
 // earlier C++ versions.<br>
-def CXX0xStaticNonIntegralInitializer :<br>
-  DiagGroup<"c++0x-static-nonintegral-init">;<br>
-def CXX0x : DiagGroup<"c++0x-extensions", [CXX0xStaticNonIntegralInitializer]>;<br>
+def CXX0x : DiagGroup<"c++0x-extensions">;<br></blockquote><div><br></div><div>This could really use a better name than 'CXX0x'...</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

 def DelegatingCtorCycles :<br>
   DiagGroup<"delegating-ctor-cycles">;<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 29 14:11:37 2011<br>
@@ -1186,7 +1186,15 @@<br>
 def err_constexpr_dtor : Error<"destructor cannot be marked constexpr">;<br>
 def err_constexpr_no_declarators : Error<<br>
   "constexpr can only be used in variable and function declarations">;<br>
-<br>
+def err_invalid_constexpr_var_decl : Error<<br>
+  "constexpr variable declaration must be a definition">;<br>
+def err_constexpr_var_requires_init : Error<<br>
+  "declaration of constexpr variable %0 requires an initializer">;<br>
+def err_constexpr_initialized_static_member : Error<<br>
+  "definition of initialized static data member %0 cannot be marked constexpr">;<br>
+def err_constexpr_var_requires_const_init : Error<<br>
+  "constexpr variable %0 must be initialized by a constant expression">;<br>
+<br>
 // Objective-C++<br>
 def err_objc_decls_may_only_appear_in_global_scope : Error<<br>
   "Objective-C declarations may only appear in global scope">;<br>
@@ -4072,8 +4080,12 @@<br>
 def err_in_class_initializer_bad_type : Error<<br>
   "static data member of type %0 must be initialized out of line">;<br>
 def ext_in_class_initializer_float_type : ExtWarn<<br>
-  "in-class initializer for static data member of type %0 "<br>
-  "is a C++0x extension">, InGroup<CXX0xStaticNonIntegralInitializer>;<br>
+  "in-class initializer for static data member of type %0 not allowed, "<br>
+  "accepted as an extension">, InGroup<DiagGroup<"static-member-init">>;<br>
+def ext_in_class_initializer_literal_type : ExtWarn<<br>
+  "in-class initializer for static data member of type %0 requires "<br>
+  "'constexpr' specifier, accepted as an extension">,<br>
+  InGroup<DiagGroup<"static-member-init">>;<br>
 def err_in_class_initializer_non_constant : Error<<br>
   "in-class initializer is not a constant expression">;<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 29 14:11:37 2011<br>
@@ -3833,8 +3833,36 @@<br>
     }<br>
<br>
     if (D.getDeclSpec().isConstexprSpecified()) {<br>
-      // FIXME: check this is a valid use of constexpr.<br>
-      NewVD->setConstexpr(true);<br>
+      // FIXME: once we know whether there's an initializer, apply this to<br>
+      // static data members too.<br>
+      if (!NewVD->isStaticDataMember() &&<br>
+          !NewVD->isThisDeclarationADefinition()) {<br>
+        // 'constexpr' is redundant and ill-formed on a non-defining declaration<br>
+        // of a variable. Suggest replacing it with 'const' if appropriate.<br>
+        SourceLocation ConstexprLoc = D.getDeclSpec().getConstexprSpecLoc();<br>
+        SourceRange ConstexprRange(ConstexprLoc, ConstexprLoc);<br>
+        // If the declarator is complex, we need to move the keyword to the<br>
+        // innermost chunk as we switch it from 'constexpr' to 'const'.<br>
+        int Kind = DeclaratorChunk::Paren;<br>
+        for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {<br>
+          Kind = D.getTypeObject(I).Kind;<br>
+          if (Kind != DeclaratorChunk::Paren)<br>
+            break;<br>
+        }<br>
+        if ((D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) ||<br>
+            Kind == DeclaratorChunk::Reference)<br>
+          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)<br>
+            << FixItHint::CreateRemoval(ConstexprRange);<br>
+        else if (Kind == DeclaratorChunk::Paren)<br>
+          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)<br>
+            << FixItHint::CreateReplacement(ConstexprRange, "const");<br>
+        else<br>
+          Diag(ConstexprLoc, diag::err_invalid_constexpr_var_decl)<br>
+            << FixItHint::CreateRemoval(ConstexprRange)<br>
+            << FixItHint::CreateInsertion(D.getIdentifierLoc(), "const ");<br>
+      } else {<br>
+        NewVD->setConstexpr(true);<br>
+      }<br>
     }<br>
   }<br>
<br>
@@ -5796,11 +5824,26 @@<br>
     //   A member-declarator can contain a constant-initializer only<br>
     //   if it declares a static member (9.4) of const integral or<br>
     //   const enumeration type, see 9.4.2.<br>
+    //<br>
+    // C++0x [class.static.data]p3:<br>
+    //   If a non-volatile const static data member is of integral or<br>
+    //   enumeration type, its declaration in the class definition can<br>
+    //   specify a brace-or-equal-initializer in which every initalizer-clause<br>
+    //   that is an assignment-expression is a constant expression. A static<br>
+    //   data member of literal type can be declared in the class definition<br>
+    //   with the constexpr specifier; if so, its declaration shall specify a<br>
+    //   brace-or-equal-initializer in which every initializer-clause that is<br>
+    //   an assignment-expression is a constant expression.<br>
     QualType T = VDecl->getType();<br>
<br>
     // Do nothing on dependent types.<br>
     if (T->isDependentType()) {<br>
<br>
+    // Allow any 'static constexpr' members, whether or not they are of literal<br>
+    // type. We separately check that the initializer is a constant expression,<br>
+    // which implicitly requires the member to be of literal type.<br>
+    } else if (VDecl->isConstexpr()) {<br>
+<br>
     // Require constness.<br>
     } else if (!T.isConstQualified()) {<br>
       Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)<br>
@@ -5809,6 +5852,9 @@<br>
<br>
     // We allow integer constant expressions in all cases.<br>
     } else if (T->isIntegralOrEnumerationType()) {<br>
+      // FIXME: In C++0x, a non-constexpr const static data member with an<br>
+      // in-class initializer cannot be volatile.<br>
+<br>
       // Check whether the expression is a constant expression.<br>
       SourceLocation Loc;<br>
       if (Init->isValueDependent())<br>
@@ -5828,31 +5874,28 @@<br>
         VDecl->setInvalidDecl();<br>
       }<br>
<br>
-    // We allow floating-point constants as an extension in C++03, and<br>
-    // C++0x has far more complicated rules that we don't really<br>
-    // implement fully.<br>
-    } else {<br>
-      bool Allowed = false;<br>
-      if (getLangOptions().CPlusPlus0x) {<br>
-        Allowed = T->isLiteralType();<br>
-      } else if (T->isFloatingType()) { // also permits complex, which is ok<br>
-        Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)<br>
-          << T << Init->getSourceRange();<br>
-        Allowed = true;<br>
-      }<br>
+    // Suggest adding 'constexpr' in C++0x for literal types.<br>
+    } else if (getLangOptions().CPlusPlus0x && T->isLiteralType()) {<br>
+      Diag(VDecl->getLocation(), diag::ext_in_class_initializer_literal_type)<br>
+        << T << Init->getSourceRange()<br>
+        << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");<br></blockquote><div><br></div><div>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)...</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
+      VDecl->setConstexpr(true);<br>
+<br>
+    // We allow floating-point constants as an extension.<br>
+    } else if (T->isFloatingType()) { // also permits complex, which is ok<br>
+      Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)<br>
+        << T << Init->getSourceRange();<br>
<br>
-      if (!Allowed) {<br>
-        Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)<br>
-          << T << Init->getSourceRange();<br>
-        VDecl->setInvalidDecl();<br>
-<br>
-      // TODO: there are probably expressions that pass here that shouldn't.<br>
-      } else if (!Init->isValueDependent() &&<br>
-                 !Init->isConstantInitializer(Context, false)) {<br>
+      if (!Init->isValueDependent() &&<br>
+          !Init->isConstantInitializer(Context, false)) {<br>
         Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)<br>
           << Init->getSourceRange();<br>
         VDecl->setInvalidDecl();<br>
       }<br>
+    } else {<br>
+      Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type)<br>
+        << T << Init->getSourceRange();<br>
+      VDecl->setInvalidDecl();<br>
     }<br>
   } else if (VDecl->isFileVarDecl()) {<br>
     if (VDecl->getStorageClassAsWritten() == SC_Extern &&<br>
@@ -5893,6 +5936,17 @@<br>
<br>
   if (!VDecl->isInvalidDecl())<br>
     checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init);<br>
+<br>
+  if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() &&<br>
+      !VDecl->getType()->isDependentType() &&<br>
+      !Init->isTypeDependent() && !Init->isValueDependent() &&<br>
+      !Init->isConstantInitializer(Context,<br>
+                                   VDecl->getType()->isReferenceType())) {<br>
+    // FIXME: Improve this diagnostic to explain why the initializer is not<br>
+    // a constant expression.<br>
+    Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init)<br>
+      << VDecl << Init->getSourceRange();<br>
+  }<br>
<br>
   Init = MaybeCreateExprWithCleanups(Init);<br>
   // Attach the initializer to the decl.<br>
@@ -5958,6 +6012,24 @@<br>
       return;<br>
     }<br>
<br>
+    // C++0x [dcl.constexpr]p9: An object or reference declared constexpr must<br>
+    // have an initializer.<br>
+    // C++0x [class.static.data]p3: A static data member can be declared with<br>
+    // the constexpr specifier; if so, its declaration shall specify<br>
+    // a brace-or-equal-initializer.<br>
+    if (Var->isConstexpr()) {<br>
+      // FIXME: Provide fix-its to convert the constexpr to const.<br>
+      if (Var->isStaticDataMember() && Var->getAnyInitializer()) {<br>
+        Diag(Var->getLocation(), diag::err_constexpr_initialized_static_member)<br>
+          << Var->getDeclName();<br>
+      } else {<br>
+        Diag(Var->getLocation(), diag::err_constexpr_var_requires_init)<br>
+          << Var->getDeclName();<br>
+      }<br>
+      Var->setInvalidDecl();<br>
+      return;<br>
+    }<br>
+<br>
     switch (Var->isThisDeclarationADefinition()) {<br>
     case VarDecl::Definition:<br>
       if (!Var->isStaticDataMember() || !Var->getAnyInitializer())<br>
@@ -6151,9 +6223,8 @@<br>
   case SC_OpenCLWorkGroupLocal:<br>
     llvm_unreachable("Unexpected storage class");<br>
   }<br>
-  // FIXME: constexpr isn't allowed here.<br>
-  //if (DS.isConstexprSpecified())<br>
-  //  Error = 5;<br>
+  if (VD->isConstexpr())<br>
+    Error = 5;<br>
   if (Error != -1) {<br>
     Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class)<br>
       << VD->getDeclName() << Error;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 29 14:11:37 2011<br>
@@ -1239,14 +1239,8 @@<br>
   if (Init)<br>
     AddInitializerToDecl(Member, Init, false,<br>
                          DS.getTypeSpecType() == DeclSpec::TST_auto);<br>
-  else if (DS.getTypeSpecType() == DeclSpec::TST_auto &&<br>
-           DS.getStorageClassSpec() == DeclSpec::SCS_static) {<br>
-    // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a static<br>
-    // data member if a brace-or-equal-initializer is provided.<br>
-    Diag(Loc, diag::err_auto_var_requires_init)<br>
-      << Name << cast<ValueDecl>(Member)->getType();<br>
-    Member->setInvalidDecl();<br>
-  }<br>
+  else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)<br>
+    ActOnUninitializedDecl(Member, DS.getTypeSpecType() == DeclSpec::TST_auto);<br>
<br>
   FinalizeDeclaration(Member);<br>
<br>
@@ -8727,10 +8721,21 @@<br>
     return;<br>
   }<br>
<br>
-  CheckImplicitConversions(Result.get(), LParenLoc);<br>
+  Expr *Init = Result.get();<br>
+  CheckImplicitConversions(Init, LParenLoc);<br>
<br>
-  Result = MaybeCreateExprWithCleanups(Result);<br>
-  VDecl->setInit(Result.takeAs<Expr>());<br>
+  if (VDecl->isConstexpr() && !VDecl->isInvalidDecl() &&<br>
+      !Init->isValueDependent() &&<br>
+      !Init->isConstantInitializer(Context,<br>
+                                   VDecl->getType()->isReferenceType())) {<br>
+    // FIXME: Improve this diagnostic to explain why the initializer is not<br>
+    // a constant expression.<br>
+    Diag(VDecl->getLocation(), diag::err_constexpr_var_requires_const_init)<br>
+      << VDecl << Init->getSourceRange();<br>
+  }<br>
+<br>
+  Init = MaybeCreateExprWithCleanups(Init);<br>
+  VDecl->setInit(Init);<br>
   VDecl->setCXXDirectInitializer(true);<br>
<br>
   CheckCompleteVariableDeclaration(VDecl);<br>
<br>
Added: cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp?rev=140801&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp?rev=140801&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp (added)<br>
+++ cfe/trunk/test/CXX/class/class.static/class.static.data/p3.cpp Thu Sep 29 14:11:37 2011<br>
@@ -0,0 +1,24 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s<br>
+<br>
+struct NonLit {<br>
+  NonLit();<br>
+};<br>
+<br>
+struct S {<br>
+  static constexpr int a = 0;<br>
+  static constexpr int b; // expected-error {{declaration of constexpr variable 'b' requires an initializer}}<br>
+<br>
+  static constexpr int c = 0;<br>
+  static const int d;<br>
+<br>
+  static constexpr double e = 0.0; // ok<br>
+  static const double f = 0.0; // expected-warning {{accepted as an extension}}<br>
+  static char *const g = 0; // expected-warning {{accepted as an extension}}<br>
+  static const NonLit h = NonLit(); // expected-error {{must be initialized out of line}}<br>
+};<br>
+<br>
+constexpr int S::a; // expected-error {{definition of initialized static data member 'a' cannot be marked constexpr}}<br>
+constexpr int S::b = 0;<br>
+<br>
+const int S::c;<br>
+constexpr int S::d = 0;<br>
<br>
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp<br>
URL: <a href="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" target="_blank">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</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original)<br>
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Thu Sep 29 14:11:37 2011<br>
@@ -11,19 +11,22 @@<br>
 constexpr int i1 = 0;<br>
 constexpr int f1() { return 0; }<br>
 struct s1 {<br>
-  constexpr static int mi = 0;<br>
+  constexpr static int mi1 = 0;<br>
+  const static int mi2;<br>
 };<br>
+constexpr int s1::mi2 = 0;<br>
<br>
 // invalid declarations<br>
 // not a definition of an object<br>
-constexpr extern int i2; // x<br>
+constexpr extern int i2; // expected-error {{constexpr variable declaration must be a definition}}<br>
 // not a literal type<br>
-constexpr notlit nl1; // x<br>
+constexpr notlit nl1; // expected-error {{declaration of constexpr variable 'nl1' requires an initializer}}<br>
 // function parameters<br>
 void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}}<br>
 // non-static member<br>
 struct s2 {<br>
-  constexpr int mi; // expected-error {{non-static data member cannot be constexpr}}<br>
+  constexpr int mi1; // expected-error {{non-static data member cannot be constexpr}}<br>
+  static constexpr int mi2; // expected-error {{requires an initializer}}<br>
 };<br>
 // typedef<br>
 typedef constexpr int CI; // expected-error {{typedef cannot be constexpr}}<br>
@@ -63,7 +66,8 @@<br>
 template <><br>
 notlit ft(notlit nl) { return nl; }<br>
<br>
-constexpr int i3 = ft(1);<br>
+// FIXME: The initializer is a constant expression.<br>
+constexpr int i3 = ft(1); // unexpected-error {{must be initialized by a constant expression}}<br>
<br>
 void test() {<br>
   // ignore constexpr when instantiating with non-literal<br>
@@ -85,17 +89,17 @@<br>
   : x(square(a)), y(square(a))<br>
   { }<br>
<br>
-constexpr pixel small(2); // x (no definition of square(int) yet, so can't<br>
-                          // constexpr-eval pixel(int))<br>
+constexpr pixel small(2); // expected-error {{must be initialized by a constant expression}}<br>
<br>
 constexpr int square(int x) {<br>
   return x * x;<br>
 }<br>
<br>
-constexpr pixel large(4); // now valid<br>
+// FIXME: The initializer is a constant expression.<br>
+constexpr pixel large(4); // unexpected-error {{must be initialized by a constant expression}}<br>
<br>
 int next(constexpr int x) { // expected-error {{function parameter cannot be constexpr}}<br>
       return x + 1;<br>
 }<br>
<br>
-extern constexpr int memsz; // x<br>
+extern constexpr int memsz; // expected-error {{constexpr variable declaration must be a definition}}<br>
<br>
Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp?rev=140801&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp?rev=140801&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp (added)<br>
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp Thu Sep 29 14:11:37 2011<br>
@@ -0,0 +1,37 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s<br>
+<br>
+// A constexpr specifier used in an object declaration declares the object as<br>
+// const.<br>
+constexpr int a = 0;<br>
+extern const int a;<br>
+<br>
+int i;<br>
+constexpr int *b = &i;<br>
+extern int *const b;<br>
+<br>
+constexpr int &c = i;<br>
+extern int &c;<br>
+<br>
+constexpr int (*d)(int) = 0;<br>
+extern int (*const d)(int);<br>
+<br>
+// A variable declaration which uses the constexpr specifier shall have an<br>
+// initializer and shall be initialized by a constant expression.<br>
+constexpr int ni1; // expected-error {{declaration of constexpr variable 'ni1' requires an initializer}}<br>
+constexpr struct C { C(); } ni2; // expected-error {{declaration of constexpr variable 'ni2' requires an initializer}}<br>
+constexpr double &ni3; // expected-error {{declaration of constexpr variable 'ni3' requires an initializer}}<br>
+<br>
+constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}}<br>
+constexpr C nc2 = C(); // expected-error {{constexpr variable 'nc2' must be initialized by a constant expression}}<br>
+int &f();<br>
+constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}}<br>
+constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}}<br>
+constexpr C nc5((C())); // expected-error {{constexpr variable 'nc5' must be initialized by a constant expression}}<br>
+int &f();<br>
+constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}}<br>
+<br>
+struct pixel {<br>
+  int x, y;<br>
+};<br>
+constexpr pixel ur = { 1294, 1024 }; // ok<br>
+constexpr pixel origin;              // expected-error {{requires an initializer}}<br>
<br>
Modified: cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp<br>
URL: <a href="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" target="_blank">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</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp (original)<br>
+++ cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp Thu Sep 29 14:11:37 2011<br>
@@ -100,8 +100,7 @@<br>
   for (extern int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'extern'}}<br>
   for (static int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'static'}}<br>
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'register'}}<br>
-  // FIXME: when clang supports constexpr, this should be rejected.<br>
-  for (constexpr int a : A()) {} // desired-error {{loop variable 'a' may not be declared 'constexpr'}}<br>
+  for (constexpr int a : A()) {} // expected-error {{loop variable 'a' may not be declared 'constexpr'}}<br>
<br>
   struct NoBeginADL {<br>
     null_t alt_end();<br>
<br>
Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)<br>
+++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Thu Sep 29 14:11:37 2011<br>
@@ -1,6 +1,6 @@<br>
 // RUN: %clang_cc1 -verify -std=c++0x %s<br>
 // RUN: cp %s %t<br>
-// RUN: not %clang_cc1 -x c++ -std=c++0x -fixit %t<br>
+// RUN: not %clang_cc1 -x c++ -std=c++0x -Werror -fixit %t<br>
 // RUN: %clang_cc1 -Wall -pedantic -x c++ -std=c++0x %t<br>
<br>
 /* This is a test of the various code modification hints that only<br>
@@ -17,3 +17,45 @@<br>
 using ::T = void; // expected-error {{name defined in alias declaration must be an identifier}}<br>
 using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}}<br>
 using typename ::V = void; // expected-error {{name defined in alias declaration must be an identifier}}<br>
+<br>
+namespace Constexpr {<br>
+  extern constexpr int a; // expected-error {{must be a definition}}<br>
+  // -> extern const int a;<br>
+<br>
+  extern constexpr int *b; // expected-error {{must be a definition}}<br>
+  // -> extern int *const b;<br>
+<br>
+  extern constexpr int &c; // expected-error {{must be a definition}}<br>
+  // -> extern int &b;<br>
+<br>
+  extern constexpr const int d; // expected-error {{must be a definition}}<br>
+  // -> extern const int d;<br>
+<br>
+  int z;<br>
+  constexpr int a = 0;<br>
+  constexpr int *b = &z;<br>
+  constexpr int &c = z;<br>
+  constexpr int d = a;<br>
+<br>
+  // FIXME: Provide FixIts for static data members too.<br>
+#if 0<br>
+  struct S {<br>
+    static constexpr int a = 0;<br>
+<br>
+    static constexpr int b; // xpected-error {{requires an initializer}}<br>
+    // -> const int b;<br>
+  };<br>
+<br>
+  constexpr int S::a; // xpected-error {{requires an initializer}}<br>
+  // -> const int S::a;<br>
+<br>
+  constexpr int S::b = 0;<br>
+#endif<br>
+<br>
+  struct S {<br>
+    static const double d = 0.0; // expected-warning {{accepted as an extension}}<br>
+    // -> constexpr static const double d = 0.0;<br>
+    static char *const p = 0; // expected-warning {{accepted as an extension}}<br>
+    // -> constexpr static char *const p = 0;<br>
+  };<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/class.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/class.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/class.cpp Thu Sep 29 14:11:37 2011<br>
@@ -172,8 +172,8 @@<br>
   float foo();<br>
<br>
   struct A {<br>
-    static const float x = 5.0f; // expected-warning {{in-class initializer for static data member of type 'const float' is a C++0x extension}}<br>
-    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}}<br>

+    static const float x = 5.0f; // expected-warning {{in-class initializer for static data member of type 'const float' not allowed}}<br>
+    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}}<br>
   };<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=140801&r1=140800&r2=140801&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp?rev=140801&r1=140800&r2=140801&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)<br>
+++ cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp Thu Sep 29 14:11:37 2011<br>
@@ -11,7 +11,7 @@<br>
<br>
 template<typename T><br>
 class Y {<br>
-  static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'const float' is a C++0x extension}}<br>
+  static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'const float' not allowed, accepted as an extension}}<br>
 };<br>
<br>
 Y<float> fy; // expected-note{{in instantiation of template class 'Y<float>' requested here}}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br>