aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDecl.cpp52
-rw-r--r--test/FixIt/fixit-cxx0x.cpp35
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp10
3 files changed, 24 insertions, 73 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index d9d7f0a99d..00c6b9fcf0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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;
}
diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp
index 9fb647d03f..b2b69b6f4b 100644
--- a/test/FixIt/fixit-cxx0x.cpp
+++ b/test/FixIt/fixit-cxx0x.cpp
@@ -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}}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index 0993a982d8..d78c16cca6 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -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}}
+ }
+}