diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4e7ee7082eb..d901ad2dcb4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2017-05-31 Jason Merrill + PR c++/66297, DR 1684 - literal class and constexpr member fns + * constexpr.c (is_valid_constexpr_fn): Only complain about + non-literal enclosing class in C++11. + * class.c (finalize_literal_type_property): Likewise. + PR c++/80179 - ICE with initialized flexible array member. * constexpr.c (verify_ctor_sanity): Handle flexible array members. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 2b039fe628f..0edf42a4c0f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5758,7 +5758,9 @@ finalize_literal_type_property (tree t) && !TYPE_HAS_CONSTEXPR_CTOR (t)) CLASSTYPE_LITERAL_P (t) = false; - if (!CLASSTYPE_LITERAL_P (t)) + /* C++14 DR 1684 removed this restriction. */ + if (cxx_dialect < cxx14 + && !CLASSTYPE_LITERAL_P (t) && !LAMBDA_TYPE_P (t)) for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) if (DECL_DECLARED_CONSTEXPR_P (fn) && TREE_CODE (fn) != TEMPLATE_DECL @@ -5766,12 +5768,11 @@ finalize_literal_type_property (tree t) && !DECL_CONSTRUCTOR_P (fn)) { DECL_DECLARED_CONSTEXPR_P (fn) = false; - if (!DECL_GENERATED_P (fn) && !LAMBDA_TYPE_P (t)) - { - error ("enclosing class of constexpr non-static member " - "function %q+#D is not a literal type", fn); - explain_non_literal_class (t); - } + if (!DECL_GENERATED_P (fn) + && pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic, + "enclosing class of constexpr non-static member " + "function %q+#D is not a literal type", fn)) + explain_non_literal_class (t); } } diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 366d562a8a6..9cb769df592 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -209,16 +209,17 @@ is_valid_constexpr_fn (tree fun, bool complain) } } - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun) + /* C++14 DR 1684 removed this restriction. */ + if (cxx_dialect < cxx14 + && DECL_NONSTATIC_MEMBER_FUNCTION_P (fun) && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun))) { ret = false; - if (complain) - { - error ("enclosing class of constexpr non-static member " - "function %q+#D is not a literal type", fun); - explain_non_literal_class (DECL_CONTEXT (fun)); - } + if (complain + && pedwarn (DECL_SOURCE_LOCATION (fun), OPT_Wpedantic, + "enclosing class of constexpr non-static member " + "function %q+#D is not a literal type", fun)) + explain_non_literal_class (DECL_CONTEXT (fun)); } } else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun))) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C index f49c56a4ba1..9078533d732 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C @@ -36,7 +36,7 @@ class debug_flag { public: explicit debug_flag(bool); - constexpr bool is_on(); // { dg-error "enclosing class .* not a literal type" } + constexpr bool is_on(); // { dg-error "enclosing class .* not a literal type" "" { target c++11_only } } private: bool flag; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C index 6b908b6dff8..450a0b5f9d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C @@ -5,7 +5,7 @@ template struct A { T t; - constexpr int f() const { return 42; } // { dg-error "enclosing class" } + constexpr int f() const { return 42; } // { dg-error "enclosing class" "" { target c++11_only } } }; struct B { B(); operator int(); }; @@ -13,7 +13,7 @@ struct B { B(); operator int(); }; constexpr A ai = { 42 }; constexpr int i = ai.f(); -constexpr int b = A().f(); // { dg-error "non-constexpr function" } +constexpr int b = A().f(); // { dg-error "" } template constexpr int f (T t) { return 42; } // { dg-error "parameter" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C index 580fceb7282..27aad93e6c3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C @@ -16,7 +16,7 @@ int main() struct complex // { dg-message "no constexpr constructor" } { complex(double r, double i) : re(r), im(i) { } - constexpr double real() const { return re; } // { dg-error "not a literal type" } + constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } } double imag() const { return im; } private: @@ -25,7 +25,7 @@ private: }; constexpr complex co1(0, 1); // { dg-error "not literal" } -constexpr double dd2 = co1.real(); // { dg-error "non-constexpr function" } +constexpr double dd2 = co1.real(); // { dg-error "" } // -------------------- diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C index 775c103161a..d59f465715d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C @@ -13,6 +13,6 @@ constexpr X X::g(X x) { return x; } struct Y { Y() { } - constexpr Y f(Y y); // { dg-error "not a literal type" } + constexpr Y f(Y y) {} // { dg-error "constexpr" } static constexpr Y g(Y y) {} // { dg-error "constexpr" } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C index 58b5d32c37c..9c832b14cbc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C @@ -45,7 +45,7 @@ constexpr int g(int x, int n) { class debug_flag { public: explicit debug_flag(bool); - constexpr bool is_on(); // { dg-error "not a literal type" } debug_flag not literal type + constexpr bool is_on(); // { dg-error "not a literal type" "" { target c++11_only } } debug_flag not literal type private: bool flag; }; diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-dr1684.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-dr1684.C new file mode 100644 index 00000000000..04ffcfd8ebd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-dr1684.C @@ -0,0 +1,7 @@ +// DR 1684 +// { dg-do compile { target c++11 } } + +struct A { + A(int); + constexpr int foo() { return 0; } // { dg-error "literal" "" { target c++11_only } } +};