diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 26 | ||||
-rw-r--r-- | test/SemaCXX/i-c-e-cxx.cpp | 13 |
3 files changed, 33 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d64817b4ee..c765deb8e6 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3542,6 +3542,9 @@ def ext_in_class_initializer_float_type : ExtWarn< def err_in_class_initializer_non_constant : Error< "in-class initializer is not a constant expression">; +def ext_in_class_initializer_non_constant : Extension< + "in-class initializer is not a constant expression, accepted as an extension">; + // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< "anonymous unions are a GNU extension in C">, InGroup<GNU>; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a308892c53..49e59c76aa 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5369,15 +5369,23 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 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; - if (!Init->isIntegerConstantExpr(Value, Context, &Loc)) { - Diag(Loc, diag::err_in_class_initializer_non_constant) - << Init->getSourceRange(); - VDecl->setInvalidDecl(); - } + // Check whether the expression is a constant expression. + SourceLocation Loc; + if (Init->isValueDependent()) + ; // Nothing to check. + else if (Init->isIntegerConstantExpr(Context, &Loc)) + ; // Ok, it's an ICE! + else if (Init->isEvaluatable(Context)) { + // If we can constant fold the initializer through heroics, accept it, + // but report this as a use of an extension for -pedantic. + Diag(Loc, diag::ext_in_class_initializer_non_constant) + << Init->getSourceRange(); + } else { + // Otherwise, this is some crazy unknown case. Report the issue at the + // location provided by the isIntegerConstantExpr failed check. + Diag(Loc, diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); } // We allow floating-point constants as an extension in C++03, and diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 2d08ea9a42..186e32126a 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -42,3 +42,16 @@ namespace pr6206 { void pr6373(const unsigned x = 0) { unsigned max = 80 / x; } + + +// rdar://9204520 +namespace rdar9204520 { + +struct A { + static const int B = int(0.75 * 1000 * 1000); +}; + +int foo() { return A::B; } +} + + |