]> granicus.if.org Git - clang/commitdiff
Fix constexpr handling to allow 'extern constexpr' variable declarations. We no
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 25 Dec 2011 21:17:58 +0000 (21:17 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sun, 25 Dec 2011 21:17:58 +0000 (21:17 +0000)
longer have access to the source locations we need to produce the
'replace constexpr with const' fixits, so they're gone for now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147273 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/FixIt/fixit-cxx0x.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index d9d7f0a99df7f981937afd47dea5e8c21fff790d..00c6b9fcf093933492586021f84e162b1231bf41 100644 (file)
@@ -3948,38 +3948,8 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                                            TemplateParamLists.release());
     }
 
-    if (D.getDeclSpec().isConstexprSpecified()) {
-      // 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);
-      }
-    }
+    if (D.getDeclSpec().isConstexprSpecified())
+      NewVD->setConstexpr(true);
   }
 
   // Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -6244,7 +6214,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
   if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
     QualType Type = Var->getType();
 
-    // C++0x [dcl.spec.auto]p3
+    // C++11 [dcl.spec.auto]p3
     if (TypeMayContainAuto && Type->getContainedAutoType()) {
       Diag(Var->getLocation(), diag::err_auto_var_requires_init)
         << Var->getDeclName() << Type;
@@ -6252,13 +6222,19 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
       return;
     }
 
-    // C++0x [class.static.data]p3: A static data member can be declared with
+    // C++11 [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() && Var->isStaticDataMember() &&
-        !Var->isThisDeclarationADefinition()) {
-      Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init)
-        << Var->getDeclName();
+    // C++11 [dcl.constexpr]p1: The constexpr specifier shall be applied only to
+    // the definition of a variable [...] or the declaration of a static data
+    // member.
+    if (Var->isConstexpr() && !Var->isThisDeclarationADefinition()) {
+      if (Var->isStaticDataMember())
+        Diag(Var->getLocation(),
+             diag::err_constexpr_static_mem_var_requires_init)
+          << Var->getDeclName();
+      else
+        Diag(Var->getLocation(), diag::err_invalid_constexpr_var_decl);
       Var->setInvalidDecl();
       return;
     }
index 9fb647d03fcd6ba7cc19db5781bbc4d028df8fb4..b2b69b6f4b7302e3f10e44798565fb8871bbc237 100644 (file)
@@ -18,41 +18,6 @@ using ::T = void; // expected-error {{name defined in alias declaration must be
 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 b; // xpected-error {{requires an initializer}}
-    // -> const int b;
-  };
-
-  constexpr int S::b = 0;
-#endif
-
-  struct S {
-    static char *const p = 0; // expected-error {{requires 'constexpr' specifier}}
-    // -> constexpr static char *const p = 0;
-  };
-}
-
 namespace SemiCommaTypo {
   int m {},
   n [[]], // expected-error {{expected ';' at end of declaration}}
index 0993a982d8e13413f4ce4b6e40fe278f3ae877d4..d78c16cca62608959e4cf003db7f71dfb056d74f 100644 (file)
@@ -961,3 +961,13 @@ struct S {
 };
 
 }
+
+namespace ExternConstexpr {
+  extern constexpr int n = 0;
+  extern constexpr int m; // expected-error {{constexpr variable declaration must be a definition}}
+  void f() {
+    extern constexpr int i; // expected-error {{constexpr variable declaration must be a definition}}
+    constexpr int j = 0;
+    constexpr int k; // expected-error {{default initialization of an object of const type}}
+  }
+}