Hello,another tiny bit for C++14 constexpr. I tested it on x86_64-linux-gnu together with another patch, so I'll retest it alone to be sure, but it passed. I added 'const' in addition to 'constexpr' for most testcases where it was needed, except for 2 where I explicitly check that const is implicit in C++11 but not C++14.
2014-10-09 Marc Glisse <marc.gli...@inria.fr> gcc/cp/ * decl.c (grokdeclarator): constexpr only implies const in C++11. gcc/testsuite/ * g++.dg/cpp0x/constexpr-52892-1.C: Error on missing const in C++14. * g++.dg/cpp0x/constexpr-array-ptr7.C: Likewise. * g++.dg/cpp0x/constexpr-diag1.C: Add const. * g++.dg/cpp0x/constexpr-diag3.C: Likewise. * g++.dg/cpp0x/constexpr-ex1.C: Likewise. * g++.dg/cpp0x/constexpr-ex2.C: Likewise. * g++.dg/cpp0x/constexpr-ex4.C: Likewise. * g++.dg/cpp0x/constexpr-initlist.C: Likewise. * g++.dg/cpp0x/constexpr-ptrmem.C: Likewise. * g++.dg/cpp0x/constexpr-ptrsub.C: Likewise. * g++.dg/cpp0x/constexpr-ref4.C: Likewise. * g++.dg/cpp0x/constexpr-static6.C: Likewise. -- Marc Glisse
Index: cp/decl.c =================================================================== --- cp/decl.c (revision 216007) +++ cp/decl.c (working copy) @@ -10532,21 +10532,22 @@ grokdeclarator (const cp_declarator *dec array_parameter_p = true; } else if (TREE_CODE (type) == FUNCTION_TYPE) type = build_pointer_type (type); } if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 && !NEW_DELETE_OPNAME_P (unqualified_id)) { cp_cv_quals real_quals = memfn_quals; - if (constexpr_p && sfk != sfk_constructor && sfk != sfk_destructor) + if (cxx_dialect < cxx14 && constexpr_p + && sfk != sfk_constructor && sfk != sfk_destructor) real_quals |= TYPE_QUAL_CONST; type = build_memfn_type (type, ctype, real_quals, rqual); } { tree decl; if (decl_context == PARM) { decl = cp_build_parm_decl (unqualified_id, type); Index: testsuite/g++.dg/cpp0x/constexpr-52892-1.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-52892-1.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-52892-1.C (working copy) @@ -17,12 +17,12 @@ struct Defer { } }; template <typename Function> constexpr Defer<Function> make_deferred(const Function f) { return Defer<Function>(f); } int main() { constexpr auto deferred = make_deferred(&fibonacci); - static_assert(deferred(25) == 75025, "Static fibonacci call failed"); + static_assert(deferred(25) == 75025, "Static fibonacci call failed"); // { dg-error "no match for call" "" { target c++14 } } } Index: testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C (working copy) @@ -10,11 +10,11 @@ struct S constexpr T S::foo () { return *(T *) (s1 + 10); } constexpr S s = { 0,1,2,3,4,5,6,7,8,9,10 }; #define SA(X) static_assert ((X), #X) -SA(s.foo() == 10); +SA(s.foo() == 10); // { dg-error "discards qualifiers" "" { target c++14 } } Index: testsuite/g++.dg/cpp0x/constexpr-diag1.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-diag1.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-diag1.C (working copy) @@ -1,18 +1,18 @@ // Test that we explain why a template instantiation isn't constexpr // { dg-do compile { target c++11 } } template <class T> struct A { T t; - constexpr int f() { return 42; } // { dg-error "enclosing class" } + constexpr int f() const { return 42; } // { dg-error "enclosing class" } }; struct B { B(); operator int(); }; constexpr A<int> ai = { 42 }; constexpr int i = ai.f(); constexpr int b = A<B>().f(); // { dg-error "non-constexpr function" } template <class T> Index: testsuite/g++.dg/cpp0x/constexpr-diag3.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-diag3.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-diag3.C (working copy) @@ -9,21 +9,21 @@ constexpr T g(T t) { return f(t); } // { int main() { constexpr int i = g(1); // { dg-error "g.T" } } // -------------------- struct complex // { dg-message "no constexpr constructor" } { complex(double r, double i) : re(r), im(i) { } - constexpr double real() { return re; } // { dg-error "not a literal type" } + constexpr double real() const { return re; } // { dg-error "not a literal type" } double imag() const { return im; } private: double re; double im; }; constexpr complex co1(0, 1); // { dg-error "not literal" } constexpr double dd2 = co1.real(); // { dg-error "non-constexpr function" } Index: testsuite/g++.dg/cpp0x/constexpr-ex1.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ex1.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ex1.C (working copy) @@ -5,27 +5,27 @@ // 4.1 constant-expression functions // 1 examples // 2 defined before first use // NOTE: this is only needed in contexts that require a constant-expression struct S { - constexpr int twice(); - constexpr int t(); // { dg-message "used but never defined" } + constexpr int twice() const; + constexpr int t() const; // { dg-message "used but never defined" } private: static constexpr int val = 7; // constexpr variable }; -constexpr int S::twice() { return val + val; } +constexpr int S::twice() const { return val + val; } constexpr S s = { }; int x1 = s.twice(); // ok int x2 = s.t(); // error: S::t() not defined constexpr int x2a = s.t(); // { dg-error "S::t" } error: S::t() not defined constexpr int ff(); // ok constexpr int gg(); // ok int x3 = ff(); // error: ff() not defined constexpr int x3a = ff(); // { dg-error "ff" } error: ff() not defined constexpr int ff() { return 1; } // too late constexpr int gg() { return 2; } @@ -37,22 +37,22 @@ int x4 = gg(); // ok // 2 // storage not allocated untill address taken constexpr double x = 9484.748; const double* p = &x; // the &x forces x into memory // 4.3 constant-expression constructors // 1 struct complex { constexpr complex(double r, double i) : re(r), im(i) { } - constexpr double real() { return re; } - constexpr double imag() { return im; } + constexpr double real() const { return re; } + constexpr double imag() const { return im; } private: double re; double im; }; constexpr complex I(0, 1); // OK -- literal complex // 2 invoked with non-const args double x5 = 1.0; // { dg-message "not declared .constexpr" } constexpr complex unit(x5, 0); // { dg-error "x5|argument" } error: x5 non-constant Index: testsuite/g++.dg/cpp0x/constexpr-ex2.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ex2.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ex2.C (working copy) @@ -1,21 +1,21 @@ // { dg-do compile { target c++11 } } // From N2235 // 4.5.3 constant expressions // p 4 struct A { constexpr A(int i) : val(i) { } - constexpr operator int() { return val; } - constexpr operator long() { return -1; } + constexpr operator int() const { return val; } + constexpr operator long() const { return -1; } private: int val; }; template<int I> struct X { static const int i = I; }; constexpr A a = 42; X<a> x; // OK: unique conversion to int int ar[X<a>::i]; // also OK int ary[a]; // { dg-error "ambiguous|conversion|array" } ambiguous conversion Index: testsuite/g++.dg/cpp0x/constexpr-ex4.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ex4.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ex4.C (working copy) @@ -1,16 +1,16 @@ // { dg-do compile { target c++11 } } struct A { constexpr A(int) { } - constexpr operator int() { return 1; }; + constexpr operator int() const { return 1; }; }; template <class T> struct B { static constexpr A a = A(1); int ar[a]; }; B<int> b; Index: testsuite/g++.dg/cpp0x/constexpr-initlist.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-initlist.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-initlist.C (working copy) @@ -16,25 +16,25 @@ public: typedef const E& const_reference; typedef size_t size_type; typedef const E* iterator; typedef const E* const_iterator; constexpr initializer_list() : sz(), start(nullptr) {} template<size_t N> constexpr initializer_list(const E(&array)[N]) : sz(N), start(array) {} - constexpr size_t size() { return sz; } + constexpr size_t size() const { return sz; } - constexpr const E* begin() { return start; } + constexpr const E* begin() const { return start; } - constexpr const E* end() { return start + sz; } + constexpr const E* end() const { return start + sz; } }; template<class E, size_t N> constexpr initializer_list<E> make_list(const E(&array)[N]) { return initializer_list<E>(array); } template<class E> E min(initializer_list<E> list) { Index: testsuite/g++.dg/cpp0x/constexpr-ptrmem.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ptrmem.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ptrmem.C (working copy) @@ -1,17 +1,17 @@ // { dg-do compile { target c++11 } } struct C { // literal type int m; int n; constexpr C(int m) : m(m), n(-m) {} - constexpr bool is_neg() { return m < 0; } + constexpr bool is_neg() const { return m < 0; } }; constexpr bool check1(const C& c, int C:: *pm) { return c.*pm < 0; } // #1 constexpr bool check2(const C* pc, bool (C::*pm)() const) { return (pc->*pm)(); } // #2 constexpr C c(-1); static_assert(!check1(c, &C::n), "Error"); Index: testsuite/g++.dg/cpp0x/constexpr-ptrsub.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ptrsub.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ptrsub.C (working copy) @@ -1,14 +1,14 @@ // PR c++/51489 // DR 1313 // { dg-do compile { target c++11 } } struct array { constexpr array() :x(0) {} - constexpr int const* begin() { return &x; } + constexpr int const* begin() const { return &x; } int x; }; constexpr array aa; constexpr auto b = aa.begin(); static_assert(b-b == 0, "compiles just fine"); static_assert(aa.begin()-aa.begin() == 0, "compiler thinks it's not a constant expression"); Index: testsuite/g++.dg/cpp0x/constexpr-ref4.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-ref4.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-ref4.C (working copy) @@ -1,18 +1,18 @@ // PR c++/54777 // { dg-do compile { target c++11 } } struct S { int s[1]; - constexpr const int &foo (unsigned i) { return (i < 1 ? 0 : throw 1), s[i]; } - constexpr const int &bar (unsigned i) { return i < 1 ? s[i] : (throw 0, s[i]); } + constexpr const int &foo (unsigned i) const { return (i < 1 ? 0 : throw 1), s[i]; } + constexpr const int &bar (unsigned i) const { return i < 1 ? s[i] : (throw 0, s[i]); } }; int main () { constexpr S a {}; constexpr int i = a.foo (0); constexpr int j = a.bar (0); static_assert (i == j, "Ouch"); } Index: testsuite/g++.dg/cpp0x/constexpr-static6.C =================================================================== --- testsuite/g++.dg/cpp0x/constexpr-static6.C (revision 216007) +++ testsuite/g++.dg/cpp0x/constexpr-static6.C (working copy) @@ -1,15 +1,15 @@ // { dg-do compile { target c++11 } } struct B { - constexpr operator int() { return 4; } + constexpr operator int() const { return 4; } }; template <int I> struct C; template<> struct C<4> { typedef int TP; }; template <class T> struct A