From b4b1d69f19f32e8aeb2ce1e0239c6e20a7f9e952 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 25 Jan 2013 04:22:16 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173414 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 5 ++++- include/clang/Basic/DiagnosticSemaKinds.td | 7 +++--- lib/Sema/SemaDecl.cpp | 22 ++++++++++++------- .../class.static/class.static.data/p3.cpp | 2 +- test/CXX/class/class.union/p2-0x.cpp | 2 +- test/SemaCXX/cxx0x-class.cpp | 8 +++---- test/SemaCXX/warn-static-const-float.cpp | 20 +++++++++++++++++ 7 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 test/SemaCXX/warn-static-const-float.cpp diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c06bbf6e14..320300ad2e 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -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">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 748ec15938..2bcbea17a5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; -def note_in_class_initializer_float_type_constexpr : Note< - "use 'constexpr' specifier to silence this warning">; + InGroup; +def ext_in_class_initializer_float_type_cxx11 : ExtWarn< + "in-class initializer for static data member of type %0 requires " + "'constexpr' specifier">, InGroup, DefaultError; def err_in_class_initializer_literal_type : Error< "in-class initializer for static data member of type %0 requires " "'constexpr' specifier">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 538434db00..9efcb52d14 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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. diff --git a/test/CXX/class/class.static/class.static.data/p3.cpp b/test/CXX/class/class.static/class.static.data/p3.cpp index 117997ee28..0d104e037d 100644 --- a/test/CXX/class/class.static/class.static.data/p3.cpp +++ b/test/CXX/class/class.static/class.static.data/p3.cpp @@ -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}} }; diff --git a/test/CXX/class/class.union/p2-0x.cpp b/test/CXX/class/class.union/p2-0x.cpp index b5c410925c..19a3ea2e1b 100644 --- a/test/CXX/class/class.union/p2-0x.cpp +++ b/test/CXX/class/class.union/p2-0x.cpp @@ -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]; }; diff --git a/test/SemaCXX/cxx0x-class.cpp b/test/SemaCXX/cxx0x-class.cpp index 41b0a5ce95..5532bcea3e 100644 --- a/test/SemaCXX/cxx0x-class.cpp +++ b/test/SemaCXX/cxx0x-class.cpp @@ -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'}} }; diff --git a/test/SemaCXX/warn-static-const-float.cpp b/test/SemaCXX/warn-static-const-float.cpp new file mode 100644 index 0000000000..a669c85903 --- /dev/null +++ b/test/SemaCXX/warn-static-const-float.cpp @@ -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; +}; -- 2.40.0