forked from OSchip/llvm-project
constexpr: static data members declared constexpr are required to have an
initializer; all other constexpr variables are merely required to be initialized. In particular, a user-provided constexpr default constructor can be used for such initialization. llvm-svn: 144028
This commit is contained in:
parent
5139dadd50
commit
eda3c84698
|
@ -1250,8 +1250,8 @@ 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_static_mem_var_requires_init : Error<
|
||||
"declaration of constexpr static data member %0 requires an initializer">;
|
||||
def err_constexpr_var_requires_const_init : Error<
|
||||
"constexpr variable %0 must be initialized by a constant expression">;
|
||||
def err_constexpr_redecl_mismatch : Error<
|
||||
|
|
|
@ -6191,17 +6191,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
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.
|
||||
VDecl->setInit(Init);
|
||||
|
@ -6266,16 +6255,12 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
|
|||
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.
|
||||
//
|
||||
// A static data member's definition may inherit an initializer from an
|
||||
// in-class declaration.
|
||||
if (Var->isConstexpr() && !Var->getAnyInitializer()) {
|
||||
Diag(Var->getLocation(), diag::err_constexpr_var_requires_init)
|
||||
if (Var->isConstexpr() && Var->isStaticDataMember() &&
|
||||
!Var->isThisDeclarationADefinition()) {
|
||||
Diag(Var->getLocation(), diag::err_constexpr_static_mem_var_requires_init)
|
||||
<< Var->getDeclName();
|
||||
Var->setInvalidDecl();
|
||||
return;
|
||||
|
@ -6533,15 +6518,21 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
|
|||
}
|
||||
}
|
||||
|
||||
// Check for global constructors.
|
||||
Expr *Init = var->getInit();
|
||||
bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal();
|
||||
|
||||
if (!var->getDeclContext()->isDependentContext() &&
|
||||
var->hasGlobalStorage() &&
|
||||
!var->isStaticLocal() &&
|
||||
var->getInit() &&
|
||||
!var->getInit()->isConstantInitializer(Context,
|
||||
baseType->isReferenceType()))
|
||||
Diag(var->getLocation(), diag::warn_global_constructor)
|
||||
<< var->getInit()->getSourceRange();
|
||||
(var->isConstexpr() || IsGlobal) && Init &&
|
||||
!Init->isConstantInitializer(Context, baseType->isReferenceType())) {
|
||||
// FIXME: Improve this diagnostic to explain why the initializer is not
|
||||
// a constant expression.
|
||||
if (var->isConstexpr())
|
||||
Diag(var->getLocation(), diag::err_constexpr_var_requires_const_init)
|
||||
<< var << Init->getSourceRange();
|
||||
if (IsGlobal)
|
||||
Diag(var->getLocation(), diag::warn_global_constructor)
|
||||
<< Init->getSourceRange();
|
||||
}
|
||||
|
||||
// Require the destructor.
|
||||
if (const RecordType *recordType = baseType->getAs<RecordType>())
|
||||
|
|
|
@ -8972,16 +8972,6 @@ void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl,
|
|||
|
||||
Expr *Init = Result.get();
|
||||
CheckImplicitConversions(Init, LParenLoc);
|
||||
|
||||
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);
|
||||
|
|
|
@ -6,7 +6,7 @@ struct 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 b; // expected-error {{declaration of constexpr static data member 'b' requires an initializer}}
|
||||
|
||||
static constexpr int c = 0;
|
||||
static const int d;
|
||||
|
|
|
@ -20,7 +20,7 @@ constexpr int s1::mi2 = 0;
|
|||
// not a definition of an object
|
||||
constexpr extern int i2; // expected-error {{constexpr variable declaration must be a definition}}
|
||||
// not a literal type
|
||||
constexpr notlit nl1; // expected-error {{declaration of constexpr variable 'nl1' requires an initializer}}
|
||||
constexpr notlit nl1; // expected-error {{constexpr variable 'nl1' must be initialized by a constant expression}}
|
||||
// function parameters
|
||||
void f2(constexpr int i) {} // expected-error {{function parameter cannot be constexpr}}
|
||||
// non-static member
|
||||
|
|
|
@ -17,9 +17,9 @@ 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 ni1; // expected-error {{default initialization of an object of const type 'const int'}}
|
||||
constexpr struct C { C(); } ni2; // expected-error {{constexpr variable 'ni2' must be initialized by a constant expression}}
|
||||
constexpr double &ni3; // expected-error {{declaration of reference 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}}
|
||||
|
@ -34,4 +34,4 @@ struct pixel {
|
|||
int x, y;
|
||||
};
|
||||
constexpr pixel ur = { 1294, 1024 }; // ok
|
||||
constexpr pixel origin; // expected-error {{requires an initializer}}
|
||||
constexpr pixel origin; // expected-error {{default initialization of an object of const type 'const pixel' requires a user-provided default constructor}}
|
||||
|
|
Loading…
Reference in New Issue