[cfe-commits] r113663 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaCXX/class.cpp test/SemaTemplate/instantiate-static-var.cpp
John McCall
rjmccall at apple.com
Fri Sep 10 16:21:23 PDT 2010
Author: rjmccall
Date: Fri Sep 10 18:21:22 2010
New Revision: 113663
URL: http://llvm.org/viewvc/llvm-project?rev=113663&view=rev
Log:
Support in-class initialization of static const floating-point data members.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/class.cpp
cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=113663&r1=113662&r2=113663&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 10 18:21:22 2010
@@ -619,7 +619,7 @@
def err_not_integral_type_anon_bitfield : Error<
"anonymous bit-field has non-integral type %0">;
def err_member_initialization : Error<
- "%0 can only be initialized if it is a static const integral data member">;
+ "fields can only be initialized in constructors">;
def err_member_function_initialization : Error<
"initializer on function does not look like a pure-specifier">;
def err_non_virtual_pure : Error<
@@ -2826,10 +2826,15 @@
def err_not_direct_base_or_virtual : Error<
"type %0 is not a direct or virtual base of %1">;
-def err_in_class_initializer_non_integral_type : Error<
- "in-class initializer has non-integral, non-enumeration type %0">;
+def err_in_class_initializer_non_const : Error<
+ "non-const static data member must be initialized out of line">;
+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">;
def err_in_class_initializer_non_constant : Error<
- "in-class initializer is not an integral constant expression">;
+ "in-class initializer is not a constant expression">;
// C++ anonymous unions and GNU anonymous structs/unions
def ext_anonymous_union : Extension<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=113663&r1=113662&r2=113663&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 10 18:21:22 2010
@@ -4115,8 +4115,7 @@
if (getLangOptions().CPlusPlus &&
RealDecl->getLexicalDeclContext()->isRecord() &&
isa<NamedDecl>(RealDecl))
- Diag(RealDecl->getLocation(), diag::err_member_initialization)
- << cast<NamedDecl>(RealDecl)->getDeclName();
+ Diag(RealDecl->getLocation(), diag::err_member_initialization);
else
Diag(RealDecl->getLocation(), diag::err_illegal_initializer);
RealDecl->setInvalidDecl();
@@ -4220,34 +4219,38 @@
// static const int value = 17;
// };
- // Attach the initializer
- VDecl->setInit(Init);
+ // Try to perform the initialization regardless.
+ if (!VDecl->isInvalidDecl()) {
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, &Init, 1),
+ &DclT);
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ }
// C++ [class.mem]p4:
// 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.
QualType T = VDecl->getType();
- if (!T->isDependentType() &&
- (!Context.getCanonicalType(T).isConstQualified() ||
- !T->isIntegralOrEnumerationType())) {
- Diag(VDecl->getLocation(), diag::err_member_initialization)
- << VDecl->getDeclName() << Init->getSourceRange();
+
+ // Do nothing on dependent types.
+ if (T->isDependentType()) {
+
+ // Require constness.
+ } else if (!T.isConstQualified()) {
+ Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const)
+ << Init->getSourceRange();
VDecl->setInvalidDecl();
- } else {
- // C++ [class.static.data]p4:
- // If a static data member is of const integral or const
- // enumeration type, its declaration in the class definition
- // can specify a constant-initializer which shall be an
- // integral constant expression (5.19).
- if (!Init->isTypeDependent() &&
- !Init->getType()->isIntegralOrEnumerationType()) {
- // We have a non-dependent, non-integral or enumeration type.
- Diag(Init->getSourceRange().getBegin(),
- diag::err_in_class_initializer_non_integral_type)
- << Init->getType() << Init->getSourceRange();
- VDecl->setInvalidDecl();
- } else if (!Init->isTypeDependent() && !Init->isValueDependent()) {
+
+ // We allow integer constant expressions in all cases.
+ } else if (T->isIntegralOrEnumerationType()) {
+ if (!Init->isValueDependent()) {
// Check whether the expression is a constant expression.
llvm::APSInt Value;
SourceLocation Loc;
@@ -4255,8 +4258,33 @@
Diag(Loc, diag::err_in_class_initializer_non_constant)
<< Init->getSourceRange();
VDecl->setInvalidDecl();
- } else if (!VDecl->getType()->isDependentType())
- ImpCastExprToType(Init, VDecl->getType(), CK_IntegralCast);
+ }
+ }
+
+ // 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;
+ }
+
+ 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)) {
+ Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
+ << Init->getSourceRange();
+ VDecl->setInvalidDecl();
}
}
} else if (VDecl->isFileVarDecl()) {
Modified: cfe/trunk/test/SemaCXX/class.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=113663&r1=113662&r2=113663&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/class.cpp (original)
+++ cfe/trunk/test/SemaCXX/class.cpp Fri Sep 10 18:21:22 2010
@@ -12,16 +12,18 @@
}
class NestedC {
+ public:
+ NestedC(int);
void m() {
sx = 0;
- x = 0; // expected-error {{error: invalid use of nonstatic data member 'x'}}
+ x = 0; // expected-error {{invalid use of nonstatic data member 'x'}}
}
};
int b : 1, w : 2;
int : 1, : 2;
typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}}
- static int sb : 1; // expected-error {{error: static member 'sb' cannot be a bit-field}}
+ static int sb : 1; // expected-error {{static member 'sb' cannot be a bit-field}}
static int vs;
typedef int func();
@@ -32,10 +34,10 @@
enum E1 { en1, en2 };
- int i = 0; // expected-error {{error: 'i' can only be initialized if it is a static const integral data member}}
- static int si = 0; // expected-error {{error: 'si' can only be initialized if it is a static const integral data member}}
- static const NestedC ci = 0; // expected-error {{error: 'ci' can only be initialized if it is a static const integral data member}}
- static const int nci = vs; // expected-error {{in-class initializer is not an integral constant expression}}
+ int i = 0; // expected-error {{fields can only be initialized in constructors}}
+ static int si = 0; // expected-error {{non-const static data member must be initialized out of line}}
+ static const NestedC ci = 0; // expected-error {{static data member of type 'const C::NestedC' must be initialized out of line}}
+ static const int nci = vs; // expected-error {{in-class initializer is not a constant expression}}
static const int vi = 0;
static const E evi = 0;
@@ -165,3 +167,12 @@
C() {}
} // expected-error{{expected ';' after class}}
}
+
+namespace rdar8367341 {
+ 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}}
+ };
+}
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=113663&r1=113662&r2=113663&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-static-var.cpp Fri Sep 10 18:21:22 2010
@@ -2,7 +2,7 @@
template<typename T, T Divisor>
class X {
public:
- static const T value = 10 / Divisor; // expected-error{{in-class initializer is not an integral constant expression}}
+ static const T value = 10 / Divisor; // expected-error{{in-class initializer is not a constant expression}}
};
int array1[X<int, 2>::value == 5? 1 : -1];
@@ -11,7 +11,7 @@
template<typename T>
class Y {
- static const T value = 0; // expected-error{{'value' can only be initialized if it is a static const integral data member}}
+ static const T value = 0; // expected-warning{{in-class initializer for static data member of type 'float const' is a C++0x extension}}
};
Y<float> fy; // expected-note{{in instantiation of template class 'Y<float>' requested here}}
More information about the cfe-commits
mailing list