diff mbox

constexpr and const qual in C++14

Message ID alpine.DEB.2.02.1410082212580.7687@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Oct. 8, 2014, 8:28 p.m. UTC
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.glisse@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.

Comments

Jason Merrill Oct. 9, 2014, 1:28 p.m. UTC | #1
OK, thanks.

Jason
diff mbox

Patch

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