forked from OSchip/llvm-project
Sync 'in class initialization of static const double' extension up with GCC,
and split it out of -Wgnu into its own warning flag. * In C++11, this is now a hard error (GCC has no extension here in C++11 mode). The error can be disabled with -Wno-static-float-init, and has a fixit to add 'constexpr'. * In C++98, this is still an ExtWarn, but is now controlled by -Wstatic-float-init as well as -Wgnu. llvm-svn: 173414
This commit is contained in:
parent
44f750a3e5
commit
cf656385ea
|
@ -212,6 +212,8 @@ def : DiagGroup<"synth">;
|
|||
def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">;
|
||||
def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">;
|
||||
def StaticInInline : DiagGroup<"static-in-inline">;
|
||||
def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
|
||||
def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
|
||||
def StringPlusInt : DiagGroup<"string-plus-int">;
|
||||
def StrncatSize : DiagGroup<"strncat-size">;
|
||||
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
|
||||
|
@ -474,7 +476,8 @@ def C11 : DiagGroup<"c11-extensions">;
|
|||
def C99 : DiagGroup<"c99-extensions">;
|
||||
|
||||
// A warning group for warnings about GCC extensions.
|
||||
def GNU : DiagGroup<"gnu", [GNUDesignator, VLAExtension, ZeroLengthArray]>;
|
||||
def GNU : DiagGroup<"gnu", [GNUDesignator, VLAExtension,
|
||||
ZeroLengthArray, GNUStaticFloatInit]>;
|
||||
// A warning group for warnings about code that clang accepts but gcc doesn't.
|
||||
def GccCompat : DiagGroup<"gcc-compat">;
|
||||
|
||||
|
|
|
@ -5304,9 +5304,10 @@ 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 GNU extension">,
|
||||
InGroup<GNU>;
|
||||
def note_in_class_initializer_float_type_constexpr : Note<
|
||||
"use 'constexpr' specifier to silence this warning">;
|
||||
InGroup<GNUStaticFloatInit>;
|
||||
def ext_in_class_initializer_float_type_cxx11 : ExtWarn<
|
||||
"in-class initializer for static data member of type %0 requires "
|
||||
"'constexpr' specifier">, InGroup<StaticFloatInit>, DefaultError;
|
||||
def err_in_class_initializer_literal_type : Error<
|
||||
"in-class initializer for static data member of type %0 requires "
|
||||
"'constexpr' specifier">;
|
||||
|
|
|
@ -7128,17 +7128,23 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
|
||||
// We allow foldable floating-point constants as an extension.
|
||||
} else if (DclT->isFloatingType()) { // also permits complex, which is ok
|
||||
Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
|
||||
<< DclT << Init->getSourceRange();
|
||||
if (getLangOpts().CPlusPlus11)
|
||||
// In C++98, this is a GNU extension. In C++11, it is not, but we support
|
||||
// it anyway and provide a fixit to add the 'constexpr'.
|
||||
if (getLangOpts().CPlusPlus11) {
|
||||
Diag(VDecl->getLocation(),
|
||||
diag::note_in_class_initializer_float_type_constexpr)
|
||||
diag::ext_in_class_initializer_float_type_cxx11)
|
||||
<< DclT << Init->getSourceRange()
|
||||
<< FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr ");
|
||||
VDecl->setConstexpr(true);
|
||||
} else {
|
||||
Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type)
|
||||
<< DclT << Init->getSourceRange();
|
||||
|
||||
if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
|
||||
Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
|
||||
<< Init->getSourceRange();
|
||||
VDecl->setInvalidDecl();
|
||||
if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) {
|
||||
Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant)
|
||||
<< Init->getSourceRange();
|
||||
VDecl->setInvalidDecl();
|
||||
}
|
||||
}
|
||||
|
||||
// Suggest adding 'constexpr' in C++11 for literal types.
|
||||
|
|
|
@ -13,7 +13,7 @@ struct S {
|
|||
static const int d2 = 0;
|
||||
|
||||
static constexpr double e = 0.0; // ok
|
||||
static const double f = 0.0; // expected-warning {{extension}} expected-note {{use 'constexpr' specifier}}
|
||||
static const double f = 0.0; // expected-error {{requires 'constexpr' specifier}}
|
||||
static char *const g = 0; // expected-error {{requires 'constexpr' specifier}}
|
||||
static const NonLit h = NonLit(); // expected-error {{must be initialized out of line}}
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ union U1 {
|
|||
static const int k2 = k1;
|
||||
static int k3 = k2; // expected-error {{non-const static data member must be initialized out of line}}
|
||||
static constexpr double k4 = k2;
|
||||
static const double k5 = k4; // expected-warning {{GNU extension}} expected-note {{use 'constexpr'}}
|
||||
static const double k5 = k4; // expected-error {{requires 'constexpr' specifier}}
|
||||
int n[k1 + 3];
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-error=static-float-init %s
|
||||
|
||||
int vs = 0;
|
||||
|
||||
|
@ -17,11 +17,11 @@ public:
|
|||
};
|
||||
|
||||
namespace rdar8367341 {
|
||||
float foo(); // expected-note {{here}}
|
||||
float foo(); // expected-note 2{{here}}
|
||||
|
||||
struct A {
|
||||
static const float x = 5.0f; // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}}
|
||||
static const float y = foo(); // expected-warning {{GNU extension}} expected-note {{use 'constexpr' specifier to silence this warning}} expected-error {{in-class initializer for static data member is not a constant expression}}
|
||||
static const float x = 5.0f; // expected-warning {{requires 'constexpr'}}
|
||||
static const float y = foo(); // expected-warning {{requires 'constexpr'}} expected-error {{constexpr variable 'y' must be initialized by a constant expression}} expected-note {{non-constexpr function 'foo'}}
|
||||
static constexpr float x2 = 5.0f;
|
||||
static constexpr float y2 = foo(); // expected-error {{must be initialized by a constant expression}} expected-note {{non-constexpr function 'foo'}}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
// RUN: %clang_cc1 -verify %s -std=c++98 -DEXT
|
||||
// RUN: %clang_cc1 -verify %s -std=c++98 -Wno-gnu -DNONE
|
||||
// RUN: %clang_cc1 -verify %s -std=c++98 -Wno-static-float-init -DNONE
|
||||
// RUN: %clang_cc1 -verify %s -std=c++98 -Wno-gnu-static-float-init -DNONE
|
||||
// RUN: %clang_cc1 -verify %s -std=c++11 -DERR
|
||||
// RUN: %clang_cc1 -verify %s -std=c++11 -Wno-gnu -DERR
|
||||
// RUN: %clang_cc1 -verify %s -std=c++11 -Wno-static-float-init -DNONE
|
||||
// RUN: %clang_cc1 -verify %s -std=c++11 -Wno-gnu-static-float-init -DERR
|
||||
|
||||
#if NONE
|
||||
// expected-no-diagnostics
|
||||
#elif ERR
|
||||
// expected-error@19 {{in-class initializer for static data member of type 'const double' requires 'constexpr' specifier}}
|
||||
#elif EXT
|
||||
// expected-warning@19 {{in-class initializer for static data member of type 'const double' is a GNU extension}}
|
||||
#endif
|
||||
|
||||
struct X {
|
||||
static const double x = 0.0;
|
||||
};
|
Loading…
Reference in New Issue