]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Improve location information in constant evaluation
authorNathaniel Shead <nathanieloshead@gmail.com>
Sat, 22 Jul 2023 15:13:43 +0000 (01:13 +1000)
committerJason Merrill <jason@redhat.com>
Wed, 26 Jul 2023 01:45:10 +0000 (21:45 -0400)
This patch updates 'input_location' during constant evaluation to ensure
that errors in subexpressions that lack location information still
provide accurate diagnostics.

By itself this change causes some small regressions in diagnostic
quality for circumstances where errors used 'input_location' but the
location of the parent subexpression doesn't make sense, so this patch
also includes a small diagnostic improvement to fix the most egregious
case.

gcc/cp/ChangeLog:

* constexpr.cc (modifying_const_object_error): Find the source
location of the const object's declaration.
(cxx_eval_constant_expression): Update input_location to the
location of the currently evaluated expression, if possible.

libstdc++-v3/ChangeLog:

* testsuite/25_algorithms/equal/constexpr_neg.cc: Update diagnostic
locations.
* testsuite/26_numerics/gcd/105844.cc: Likewise.
* testsuite/26_numerics/lcm/105844.cc: Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-48089.C: Update diagnostic locations.
* g++.dg/cpp0x/constexpr-70323.C: Likewise.
* g++.dg/cpp0x/constexpr-70323a.C: Likewise.
* g++.dg/cpp0x/constexpr-delete2.C: Likewise.
* g++.dg/cpp0x/constexpr-diag3.C: Likewise.
* g++.dg/cpp0x/constexpr-ice20.C: Likewise.
* g++.dg/cpp0x/constexpr-mutable3.C: Likewise.
* g++.dg/cpp0x/constexpr-recursion.C: Likewise.
* g++.dg/cpp0x/overflow1.C: Likewise.
* g++.dg/cpp1y/constexpr-89285.C: Likewise.
* g++.dg/cpp1y/constexpr-89481.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const14.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const16.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const18.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const19.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const21.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const22.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const3.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const4.C: Likewise.
* g++.dg/cpp1y/constexpr-tracking-const7.C: Likewise.
* g++.dg/cpp1y/constexpr-union5.C: Likewise.
* g++.dg/cpp1y/pr68180.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda6.C: Likewise.
* g++.dg/cpp1z/constexpr-lambda8.C: Likewise.
* g++.dg/cpp2a/bit-cast11.C: Likewise.
* g++.dg/cpp2a/bit-cast12.C: Likewise.
* g++.dg/cpp2a/bit-cast14.C: Likewise.
* g++.dg/cpp2a/constexpr-98122.C: Likewise.
* g++.dg/cpp2a/constexpr-dynamic17.C: Likewise.
* g++.dg/cpp2a/constexpr-init1.C: Likewise.
* g++.dg/cpp2a/constexpr-new12.C: Likewise.
* g++.dg/cpp2a/constexpr-new3.C: Likewise.
* g++.dg/cpp2a/constinit10.C: Likewise.
* g++.dg/cpp2a/is-corresponding-member4.C: Likewise.
* g++.dg/ext/constexpr-vla2.C: Likewise.
* g++.dg/ext/constexpr-vla3.C: Likewise.
* g++.dg/ubsan/pr63956.C: Likewise.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
41 files changed:
gcc/cp/constexpr.cc
gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
gcc/testsuite/g++.dg/cpp0x/constexpr-70323.C
gcc/testsuite/g++.dg/cpp0x/constexpr-70323a.C
gcc/testsuite/g++.dg/cpp0x/constexpr-delete2.C
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ice20.C
gcc/testsuite/g++.dg/cpp0x/constexpr-mutable3.C
gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C
gcc/testsuite/g++.dg/cpp0x/overflow1.C
gcc/testsuite/g++.dg/cpp1y/constexpr-89285.C
gcc/testsuite/g++.dg/cpp1y/constexpr-89481.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const14.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const16.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const18.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const19.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const21.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const22.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const3.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const4.C
gcc/testsuite/g++.dg/cpp1y/constexpr-tracking-const7.C
gcc/testsuite/g++.dg/cpp1y/constexpr-union5.C
gcc/testsuite/g++.dg/cpp1y/pr68180.C
gcc/testsuite/g++.dg/cpp1z/constexpr-lambda6.C
gcc/testsuite/g++.dg/cpp1z/constexpr-lambda8.C
gcc/testsuite/g++.dg/cpp2a/bit-cast11.C
gcc/testsuite/g++.dg/cpp2a/bit-cast12.C
gcc/testsuite/g++.dg/cpp2a/bit-cast14.C
gcc/testsuite/g++.dg/cpp2a/constexpr-98122.C
gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C
gcc/testsuite/g++.dg/cpp2a/constexpr-init1.C
gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C
gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C
gcc/testsuite/g++.dg/cpp2a/constinit10.C
gcc/testsuite/g++.dg/cpp2a/is-corresponding-member4.C
gcc/testsuite/g++.dg/ext/constexpr-vla2.C
gcc/testsuite/g++.dg/ext/constexpr-vla3.C
gcc/testsuite/g++.dg/ubsan/pr63956.C
libstdc++-v3/testsuite/25_algorithms/equal/constexpr_neg.cc
libstdc++-v3/testsuite/26_numerics/gcd/105844.cc
libstdc++-v3/testsuite/26_numerics/lcm/105844.cc

index 5e0fe93ebc02c9e44f9a6ae7c0ecbb963d86a986..03a49c59933f4d126e31b3c69d294ccf647d2871 100644 (file)
@@ -2160,7 +2160,33 @@ modifying_const_object_error (tree expr, tree obj)
   auto_diagnostic_group d;
   error_at (loc, "modifying a const object %qE is not allowed in "
            "a constant expression", TREE_OPERAND (expr, 0));
-  inform (location_of (obj), "originally declared %<const%> here");
+
+  /* Find the underlying object that was declared as const.  */
+  location_t decl_loc = UNKNOWN_LOCATION;
+  for (tree probe = obj; decl_loc == UNKNOWN_LOCATION; )
+    switch (TREE_CODE (probe))
+      {
+      case BIT_FIELD_REF:
+      case COMPONENT_REF:
+       {
+         tree elt = TREE_OPERAND (probe, 1);
+         if (CP_TYPE_CONST_P (TREE_TYPE (elt)))
+           decl_loc = DECL_SOURCE_LOCATION (elt);
+         probe = TREE_OPERAND (probe, 0);
+       }
+       break;
+
+      case ARRAY_REF:
+      case REALPART_EXPR:
+      case IMAGPART_EXPR:
+       probe = TREE_OPERAND (probe, 0);
+       break;
+
+      default:
+       decl_loc = location_of (probe);
+       break;
+      }
+  inform (decl_loc, "originally declared %<const%> here");
 }
 
 /* Return true if FNDECL is a replaceable global allocation function that
@@ -6959,7 +6985,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       return t;
     }
 
+  /* Change the input location to the currently processed expression for
+     better error messages when a subexpression has no location.  */
   location_t loc = cp_expr_loc_or_input_loc (t);
+  iloc_sentinel sentinel (loc);
 
   STRIP_ANY_LOCATION_WRAPPER (t);
 
index 4574eb83ff765ebb632b226239240a45527cad12..11630f26ffee9a3af65aea95cebb4d0728f4c118 100644 (file)
 // R() is well-formed because i is initialized before j.
 
 struct s {
-  constexpr s() : v(v) { }
+  constexpr s() : v(v) { } // { dg-error "accessing uninitialized member" }
   int v;
 };
 
-constexpr s bang;              // { dg-error "|" }
+constexpr s bang;  // { dg-message "in .constexpr. expansion" }
 
 struct R {
   int i,j;
@@ -26,14 +26,14 @@ constexpr R r;                      // { dg-bogus "" }
 // Ill-formed (no diagnostic required)
 struct T {
   int i;
-  constexpr int f() { return i; }
+  constexpr int f() { return i; }  // { dg-error "accessing uninitialized member" }
   constexpr T(): i(0) { }
-  constexpr T(const T& t) : i(f()) { } // { dg-message "" }
+  constexpr T(const T& t) : i(f()) { }  // { dg-message "in .constexpr. expansion" }
 };
 
 constexpr T t1;
 // Ill-formed (diagnostic required)
-constexpr T t2(t1);            // { dg-message "" }
+constexpr T t2(t1);            // { dg-message "in .constexpr. expansion" }
 
 // Well-formed
 struct U {
index 272a225d967e1e73aa0f9d4d2307e2ad3a5abada..bfb185f2fb5d9fa3325aedf7bc0837f2a0469e77 100644 (file)
@@ -1,10 +1,10 @@
 // PR c++/70323
 // { dg-do compile { target c++11 } }
 
-constexpr int overflow_if_0 (int i) { return __INT_MAX__ + !i; }
-constexpr int overflow_if_1 (int i) { return __INT_MAX__ + i; }
+constexpr int overflow_if_0 (int i) { return __INT_MAX__ + !i; }  // { dg-error "overflow in constant expression" }
+constexpr int overflow_if_1 (int i) { return __INT_MAX__ + i; }   // { dg-error "overflow in constant expression" }
 
-constexpr bool i0_0 = overflow_if_0 (0);   // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr bool i0_0 = overflow_if_0 (0);   // { dg-message "in .constexpr. expansion of " }
 constexpr bool i0_1 = overflow_if_0 (1);
 constexpr bool i1_0 = overflow_if_1 (0);
-constexpr bool i1_1 = overflow_if_1 (1);   // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr bool i1_1 = overflow_if_1 (1);   // { dg-message "in .constexpr. expansion of " }
index 1990ab6be2d81f0cceb29090265a335822160417..b5ed581e1c85c7c4080b4cc0577930955c8067f6 100644 (file)
@@ -2,10 +2,10 @@
 // { dg-do compile { target c++11 } }
 // { dg-options "-Wall" }
 
-constexpr int overflow_if_0 (int i) { return __INT_MAX__ + !i; }
-constexpr int overflow_if_1 (int i) { return __INT_MAX__ + i; }
+constexpr int overflow_if_0 (int i) { return __INT_MAX__ + !i; }  // { dg-error "overflow in constant expression" }
+constexpr int overflow_if_1 (int i) { return __INT_MAX__ + i; }   // { dg-error "overflow in constant expression" }
 
-constexpr bool i0_0 = overflow_if_0 (0);   // { dg-error "overflow in constant expression|in .constexpr. expansion of" }
+constexpr bool i0_0 = overflow_if_0 (0);   // { dg-message "in .constexpr. expansion of" }
 constexpr bool i0_1 = overflow_if_0 (1);
 constexpr bool i1_0 = overflow_if_1 (0);
-constexpr bool i1_1 = overflow_if_1 (1);   // { dg-error "overflow in constant expression|in .constexpr. expansion of" }
+constexpr bool i1_1 = overflow_if_1 (1);   // { dg-message "in .constexpr. expansion of" }
index 999f9b7851ec9a8f46ff44209ee48091e146fa06..f2b6df2509c077a76c0d79096a6933cc7df074c7 100644 (file)
@@ -6,8 +6,9 @@ constexpr int f(int i) { return i; }
 constexpr int g(A* ap)
 {
   return f((delete[] ap, 42)); // { dg-message "" "" { target c++17_down } }
+                               // { dg-error "" "" { target c++2a } .-1 }
 }
 
 A a;
-constexpr int i = g(&a);       // { dg-error "" }
-                               // { dg-message "in 'constexpr' expansion of" "" { target c++2a } .-1 }
+constexpr int i = g(&a);  // { dg-error "" "" { target c++17_down } }
+                         // { dg-message "in 'constexpr' expansion of" "" { target c++2a } .-1 }
index 5eedf42ba36bd6c86062922abae58e2b3c0aafc9..50c676c56cd197f3d67552149c5a1f096857edef 100644 (file)
@@ -16,7 +16,7 @@ int main()
 struct complex                         // { dg-message "no .constexpr. constructor" "" { target { ! implicit_constexpr } } }
 {
   complex(double r, double i) : re(r), im(i) { }
-  constexpr double real() const { return re; } // { dg-error "not a literal type" "" { target c++11_only } }
+  constexpr double real() const { return re; } // { dg-error "not a literal type|not usable in a constant expression" "" { target { ! implicit_constexpr } } }
   double imag() const { return im; }
 
 private:
index e2d4853a28438feb6bcd6df1a4ef339bb88b49e0..43fa9a03c1449b8750ebd3cb7fa95617b0c47dc3 100644 (file)
@@ -3,5 +3,6 @@
 
 typedef bool (*Function)(int);
 constexpr bool check(int x, Function p) { return p(x); }  // { dg-message "in .constexpr. expansion of" }
+// { dg-error "not a constant expression" "" { target *-*-* } .-1 }
 
 static_assert(check(2, check), "");  // { dg-error "conversion|constant|in .constexpr. expansion of" }
index 51499fac520184a931f054dc5b2aed624523c788..bdb2677a350401deb728f86da5abc9e1fb14755a 100644 (file)
@@ -4,6 +4,7 @@
 struct A { mutable int m; };
 
 constexpr int f(A a) { return a.m; }
+// { dg-error "mutable" "" { target c++11_only } .-1 }
 
 static_assert(f({42}) == 42, "");
-// { dg-error "non-constant|mutable" "" { target c++11_only } .-1 }
+// { dg-error "non-constant" "" { target c++11_only } .-1 }
index 8c4201e1ec2e3d1b16279a2fd77e1dadf6c22d19..b00f8794d4cbc8d7a173e05abacd8dfabf28c9e9 100644 (file)
@@ -1,6 +1,6 @@
 // Test that we catch excessive recursion.
 // { dg-do compile { target c++11 } }
 // { dg-options "-fconstexpr-depth=5" }
-// { dg-prune-output "in constexpr expansion" }
-constexpr int f (int i) { return f (i-1); } // { dg-message "in .constexpr. expansion of " }
-constexpr int i = f(42);       // { dg-error ".constexpr. evaluation depth|in .constexpr. expansion of " }
+// { dg-prune-output "in .constexpr. expansion" }
+constexpr int f (int i) { return f (i-1); } // { dg-error ".constexpr. evaluation depth" }
+constexpr int i = f(42);       
index b8591b4af413e94a94ca4717c5d3e6c705ee44d0..e295355c88fbd8d10f89aebf656f91c1d7df8043 100644 (file)
@@ -4,7 +4,7 @@ template <long long i>
 struct Fib
 {
     static const long long value // { dg-error "overflow" }
-    = Fib<i-1>::value + Fib<i-2>::value;
+    = Fib<i-1>::value + Fib<i-2>::value; // { dg-error "overflow" }
 };
 
 template <>
index fe0b8570ca2261827782fd4a7635c2fcf6430511..efbf9bd15dde7aeebdb8a90fb0afd72693306ceb 100644 (file)
@@ -13,8 +13,9 @@ struct B {
     *c = reinterpret_cast<char *>(this) - reinterpret_cast<char *>(c); // { dg-error "reinterpret_cast" "" { target c++20_down } }
   }
 };
-struct C : A {
+struct C : A {  // { dg-error "" "" { target c++14_down } }
   B bar {this};
 };
 
-constexpr C foo {};            // { dg-message "" }
+// error path changes in C++17 due to `C` becoming an aggregate
+constexpr C foo {};  // { dg-error "" "" { target c++17 } }
index 8ac4ef0fd36ee8180c6612bbd34c2cc6b8e0807a..6f8f6a8038efefdb5a81cec4afb9279741fc5f94 100644 (file)
@@ -6,7 +6,7 @@ foo ()
 {
   union U { long long a; int b[2]; } u { 5LL };
   u.b[1] = 4;          // { dg-error "change of the active member of a union from" "" { target c++17_down } }
-  return u.b[0];
+  return u.b[0];       // { dg-error "accessing uninitialized array element" "" { target c++2a } }
 }
 
 constexpr int
@@ -19,6 +19,5 @@ bar ()
 
 static_assert (foo () == 0, "");       // { dg-error "non-constant condition for static assertion" }
                                        // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 }
-                                       // { dg-error "accessing uninitialized array element" "" { target c++2a } .-2 }
 static_assert (bar () == 4, "");       // { dg-error "non-constant condition for static assertion" "" { target c++17_down } }
                                        // { dg-message "in 'constexpr' expansion of" "" { target c++17_down } .-1 }
index 45c4fcf50be7a740dbdcb833e61f9e116061f7ac..0c77dd4934d630671e23b0387a8ebecba4a63eff 100644 (file)
@@ -14,7 +14,7 @@ struct C {
 
 struct A {
   int r;
-  const C c;
+  const C c; // { dg-message "originally declared" }
   constexpr A() : r(11) { r = 14; const_cast<C &>(c).n = 42; } // { dg-error "modifying a const object" }
 };
 
@@ -34,5 +34,4 @@ struct B {
 };
 
 constexpr B b(false); // { dg-message "in .constexpr. expansion of" }
-// { dg-message "originally declared" "" { target *-*-* } .-1 }
 static_assert(b.e.d.a.c.n == 2, ""); // { dg-error "non-constant condition" }
index 5a5b92bc8ccb0e359b18bfd5971b10ce496b8dfe..b5ccf3a4ea5a61acefcdee41f6006a2e607e3bd2 100644 (file)
@@ -7,7 +7,7 @@ constexpr int& impl(const int (&array)[10], int index) {
 
 struct A {
   constexpr int& operator[](int i) { return impl(elems, i); }
-  const int elems[10];
+  const int elems[10]; // { dg-message "originally declared" }
 };
 
 constexpr bool
@@ -19,4 +19,3 @@ f()
 }
 
 constexpr bool b = f(); // { dg-message "in .constexpr. expansion of " }
-// { dg-message "originally declared" "" { target *-*-* } .-1 }
index 11a680468c28a28f1ffbbe75e59eeacd6b83233f..278628c121b0f6a5d91a9389dbfa84c66ba1f560 100644 (file)
@@ -13,11 +13,11 @@ struct array
 template <typename T>
 struct S {
   using U = array<T, 4>;
-  const U m;
+  const U m; // { dg-message "originally declared" }
   constexpr S(int) : m{}
   {
     const_cast<int &>(const_cast<const U &>(m)[0]) = 42; // { dg-error "modifying a const object" }
   }
 };
 
-constexpr S<int> p = { 10 }; // { dg-message "originally declared" }
+constexpr S<int> p = { 10 };
index c31222ffcdd52a5cd4e3e70967869b4f0ad5bb14..2d18c94537b41bb849bb3e6bfa1022bcf18f9297 100644 (file)
@@ -7,7 +7,7 @@ template <typename E, size_t N>
 struct array
 {
   constexpr const E &operator[](size_t n) const noexcept { return elems[n]; }
-  const E elems[N];
+  const E elems[N]; // { dg-message "originally declared" }
 };
 
 template <typename T>
@@ -20,4 +20,4 @@ struct S {
   }
 };
 
-constexpr S<int> p = { 10 }; // { dg-message "originally declared" }
+constexpr S<int> p = { 10 };
index 0b16193398e6b36f1a07d2bbd9343b52ebf372c5..d3bbcb116a6d113af97428b1ca634925d915abce 100644 (file)
@@ -18,11 +18,11 @@ struct array2 {
 template <typename T>
 struct S {
   using U = array2<T, 4>;
-  const U m;
+  const U m; // { dg-message "originally declared" }
   constexpr S(int) : m{}
   {
     const_cast<int &>(m.a[0]) = 42; // { dg-error "modifying a const object" }
   }
 };
 
-constexpr S<int> p = { 10 }; // { dg-message "originally declared" }
+constexpr S<int> p = { 10 };
index 216cf1607a46acc1f6d9e86504c04b1ee11bd620..27522f86dbd687099f020a9f1d217709394f1545 100644 (file)
@@ -7,11 +7,11 @@ struct X {
 
 template <typename T>
 struct S {
-  const X x;
+  const X x; // { dg-message "originally declared" }
   constexpr S(int) : x{}
   {
     const_cast<X&>(x).i = 19; // { dg-error "modifying a const object" }
   }
 };
 
-constexpr S<int> p = { 10 }; // { dg-message "originally declared" }
+constexpr S<int> p = { 10 };
index 6853775c1e239971c5688d39fd8ecf1a958c7c72..fc88dd05eef67475b414cc19be6c2e2f2573b1ac 100644 (file)
@@ -7,7 +7,7 @@ struct A {
 };
 
 struct B {
-  const A a;
+  const A a; // { dg-message "originally declared" }
   constexpr B(bool b) {
     if (b)
       const_cast<A &>(a).n = 3; // { dg-error "modifying a const object" }
@@ -18,5 +18,4 @@ constexpr B b(false);
 static_assert(b.a.n == 2, "");
 
 constexpr B b2(true); // { dg-message "in .constexpr. expansion of " }
-// { dg-message "originally declared" "" { target *-*-* } .-1 } 
 static_assert((b2.a.n, 1), "");
index 8263a7cc5053d851a9197199d901677b2d457e33..27fede152c7c8e462e1c2e2be826e0029664cb56 100644 (file)
@@ -2,7 +2,7 @@
 // { dg-do compile { target c++14 } }
 
 struct A {
-  const int n;
+  const int n; // { dg-message "originally declared" }
   constexpr A() : n(1) { }
 };
 struct B {
@@ -13,5 +13,4 @@ struct B {
   }
 };
 constexpr B b; // { dg-message "in .constexpr. expansion of " }
-// { dg-message "originally declared" "" { target *-*-* } .-1 }
 static_assert((b.a.n, 1), "");
index 922e8ff126f7d0c83d993e2a819e2bab9c9eb749..bea14b056027dff70f39198144d87fb186cafbb9 100644 (file)
@@ -3,7 +3,7 @@
 
 struct D { int n; };
 
-struct C { const D d; };
+struct C { const D d; }; // { dg-message "originally declared" }
 
 struct A {
   C c;
@@ -19,5 +19,4 @@ struct B {
 };
 
 constexpr B b{}; // { dg-message "in .constexpr. expansion of " }
-// { dg-message "originally declared" "" { target *-*-* } .-1 }
 static_assert((b.a.c.d.n, 1), "");
index 55fe9fa2f0bfd75e9b45dddf716c1a072cbc7d29..3d76345d564d46165f5d30936a166b5a44e9a016 100644 (file)
@@ -8,8 +8,8 @@ union U {
 };
 
 constexpr int foo(U *up) {
-  up->a++;
+  up->a++; // { dg-error "accessing uninitialized member" }
   return {42};
 }
 
-extern constexpr U u = {}; // { dg-error "accessing uninitialized member" }
+extern constexpr U u = {}; // { dg-message "in .constexpr. expansion" }
index 9e6e5e984f9977ff53b4f7456a7823ee0cc5fb5e..8de1ef3936b5a60d5fc251d15f92a0cf03bb8e64 100644 (file)
@@ -6,11 +6,11 @@ typedef float __attribute__( ( vector_size( 16 ) ) ) float32x4_t;
 constexpr float32x4_t fill(float x) {
   float32x4_t v{0};
   constexpr auto vs = sizeof(v)/sizeof(v[0]);
-  for (auto i=0U; i<vs; ++i) v[i]=i;
+  for (auto i=0U; i<vs; ++i) v[i]=i; // { dg-error "not a constant" }
   return v+x;
 }
 
 float32x4_t foo(float32x4_t x) {
-  constexpr float32x4_t v = fill(1.f); // { dg-error "not a constant||in .constexpr. expansion of " }
+  constexpr float32x4_t v = fill(1.f); // { dg-message "in .constexpr. expansion of " }
   return x+v;
 }
index 214d3821299e216b2b287e5b6118798811da622a..c46c2d4c7fed36a8b996376c8ea6dc7fdaccdb6e 100644 (file)
@@ -1,7 +1,7 @@
 // Testcase from P0170R1
 // { dg-do compile { target c++17 } }
 
-auto monoid = [](auto v) { return [=] { return v; }; };
+auto monoid = [](auto v) { return [=] { return v; }; };  // { dg-error "not usable in a constant expression" }
 auto add = [](auto m1) constexpr {
   auto ret = m1();
   return [=](auto m2) mutable {
@@ -22,7 +22,7 @@ int main()
   // member function call operator can not perform an lvalue-to-rvalue conversion
   // on one of its subobjects (that represents its capture) in a constant
   // expression.
-  auto two = monoid(2);
+  auto two = monoid(2);  // { dg-message "not declared .constexpr." }
   if (!(two() == 2)) __builtin_abort(); // OK, not a constant expression.
   static_assert(add(one)(one)() == two()); // { dg-error "|in .constexpr. expansion of " } two() is not a constant expression
   static_assert(add(one)(one)() == monoid(2)()); // OK
index 84be68ab7f042177b181c75f62b3212dc234c09f..82351ff0c54bdf51c1b2cd66088dbfa44ea0ecd1 100644 (file)
@@ -4,11 +4,14 @@
 auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
 auto C = [](auto a) { return a; };
 static_assert( Fwd(C ,3) == 3); // OK
+
 // No specialization of the function call operator template can be constexpr
 // (because of the local static).
 auto NC = [](auto a) { static int s; return a; }; // { dg-error "static" }
-// { dg-message "operator int" "" { target *-*-* } .+1 }
+// { dg-error "called in a constant expression" "" { target *-*-* } .-1 }
+
 static_assert( Fwd(NC ,3) == 3); // { dg-error "" }
+// { dg-message "operator int" "" { target *-*-* } .-1 }
 
 // We look for the string "operator int" to check that we aren't trying to do
 // template pretty-printing in an expression; that gets incredibly unwieldy
index a3eb31bc6c7ba15d38127f7fbf5a021baa6317d7..760c9ca40b4f1b31946ee1a40e3e14eca11a6c45 100644 (file)
@@ -28,7 +28,7 @@ f3 ()
 {
   T t = { 1, 2 };
   S s = __builtin_bit_cast (S, t);
-  return s.a[1] == 0;
+  return s.a[1] == 0;          // { dg-error "accessing uninitialized array element" }
 }
 
 constexpr bool
@@ -52,12 +52,12 @@ f6 ()
 {
   W t = { 1, 2 };
   V s = __builtin_bit_cast (V, t);
-  return s.b.a[1] == 1;
+  return s.b.a[1] == 1;                // { dg-error "accessing uninitialized array element" }
 }
 
 constexpr bool a = f1 ();
 constexpr bool b = f2 ();
-constexpr bool c = f3 ();      // { dg-error "accessing uninitialized array element" }
-constexpr bool d = f4 ();
+constexpr bool c = f3 ();      // { dg-message "in .constexpr. expansion" }
+constexpr bool d = f4 ();      // { dg-message "in .constexpr. expansion" }
 constexpr bool e = f5 ();
-constexpr bool f = f6 ();      // { dg-error "accessing uninitialized array element" }
+constexpr bool f = f6 ();      // { dg-message "in .constexpr. expansion" }
index 9c699dd55f08262c4d4e1dc6a447a4a481714c82..e205bc6a8c195f627ed86568eb4595d2cac201c0 100644 (file)
@@ -33,7 +33,7 @@ f3 ()
 {
   T t = { 1, 2 };
   S s = __builtin_bit_cast (S, t);
-  return s.a[1] == 0;
+  return s.a[1] == 0;          // { dg-error "accessing uninitialized array element" }
 }
 
 constexpr bool
@@ -57,12 +57,12 @@ f6 ()
 {
   W t = { 1, 2 };
   V s = __builtin_bit_cast (V, t);
-  return s.b.a[1] == 1;
+  return s.b.a[1] == 1;                // { dg-error "accessing uninitialized array element" }
 }
 
 constexpr bool a = f1 ();
 constexpr bool b = f2 ();
-constexpr bool c = f3 ();      // { dg-error "accessing uninitialized array element" }
-constexpr bool d = f4 ();
+constexpr bool c = f3 ();      // { dg-message "in .constexpr. expansion" }
+constexpr bool d = f4 ();      // { dg-message "in .constexpr. expansion" }
 constexpr bool e = f5 ();
-constexpr bool f = f6 ();      // { dg-error "accessing uninitialized array element" }
+constexpr bool f = f6 ();      // { dg-message "in .constexpr. expansion" }
index 5e185919be42dae16699292ff13515069b28175d..e0cc9a3970270a8a1b79fe8d00aa44902bb1fe12 100644 (file)
@@ -44,7 +44,7 @@ f5 ()
 {
   T1 t = { 0, 0, 0, 0, 0, 0, 0 };
   S s = __builtin_bit_cast (S, t);
-  unsigned char a = s.a;
+  unsigned char a = s.a;               // { dg-error "accessing uninitialized member" }
   return true;
 }
 
@@ -53,7 +53,7 @@ f6 ()
 {
   T2 t = { 0, 0, 0, 0, 0, 0, 0 };
   S s = __builtin_bit_cast (S, t);
-  unsigned char b = s.b;
+  unsigned char b = s.b;               // { dg-error "accessing uninitialized member" }
   return true;
 }
 
@@ -62,14 +62,14 @@ f7 ()
 {
   T3 t = { 0, 0, 0, 0, 0, 0, 0 };
   S s = __builtin_bit_cast (S, t);
-  unsigned char c = s.c;
+  unsigned char c = s.c;               // { dg-error "accessing uninitialized member" }
   return true;
 }
 
 constexpr bool a = f1 ();
 constexpr bool b = f2 ();
 constexpr bool c = f3 ();
-constexpr bool d = f4 ();
-constexpr bool e = f5 ();      // { dg-error "accessing uninitialized member" }
-constexpr bool f = f6 ();      // { dg-error "accessing uninitialized member" }
-constexpr bool g = f7 ();      // { dg-error "accessing uninitialized member" }
+constexpr bool d = f4 ();      // { dg-message "in .constexpr. expansion" }
+constexpr bool e = f5 ();      // { dg-message "in .constexpr. expansion" }
+constexpr bool f = f6 ();      // { dg-message "in .constexpr. expansion" }
+constexpr bool g = f7 ();      // { dg-message "in .constexpr. expansion" }
index 01bdfa5bd4d2d7cdddc293fddfebe1bcce53d4ce..b0c91d5ef97ab72667669dabb5485a27c9aaeef8 100644 (file)
@@ -9,7 +9,7 @@ bar ()
 {
   V f { .b = 42 };
   constexpr auto m = &V::a;
-  return (f.*m) == 42;
+  return (f.*m) == 42;  // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" }
 }
 
 constexpr bool
@@ -21,5 +21,5 @@ baz ()
 }
 
 static_assert (bar (), "");    // { dg-error "non-constant condition for static assertion" }
-                               // { dg-error "accessing 'V::a' member instead of initialized 'V::b' member in constant expression" "" { target *-*-* } .-1 }
+                               // { dg-message "in .constexpr. expansion" "" { target *-*-* } .-1 }
 static_assert (baz (), "");
index a26678e6ed766dc5f8f2ffb3765e193a7321aa98..28facf192df794555d9b1f60d81112eaec35a5b9 100644 (file)
@@ -25,8 +25,7 @@ struct D : B, A {
 
 constexpr B::B(V* v, A* a)
 {
-  dynamic_cast<B*>(a);
+  dynamic_cast<B*>(a); // { dg-error "accessing uninitialized member" }
 }
 
-constexpr D d; // { dg-error "accessing uninitialized member" }
-// { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 }
+constexpr D d; // { dg-message "in 'constexpr' expansion of" }
index e56ecfed48adb93e260e8323235949935eb6c82a..b4e39b6f928812ff4ada38862cafed47b8b4c738 100644 (file)
@@ -52,11 +52,10 @@ constexpr int
 fn5 ()
 {
   struct S { int a = 9; int b; } s;
-  return s.b;
+  return s.b; // { dg-error "accessing uninitialized member" }
 }
 
-constexpr int b = fn5 (); // { dg-error "accessing uninitialized member" }
-// { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 }
+constexpr int b = fn5 (); // { dg-message "in .constexpr. expansion of" }
 
 constexpr int
 fn6 ()
index 5a3d06a5fab05153c36808b904575f143586223a..832782e1427fc8dbb4a1ff74cd56b2d1b9047570 100644 (file)
@@ -17,11 +17,11 @@ struct B : A {
 constexpr int
 foo ()
 {
-  A *a = new B ();
+  A *a = new B ();  // { dg-message "allocated here" }
   a->a = 4;
   delete a;
-  int r = a->foo ();
+  int r = a->foo ();  // { dg-error "constant expression" }
   return r;
 }
 
-constexpr auto a = foo ();     // { dg-error "constant expression" }
+constexpr auto a = foo ();  // { dg-message "in .constexpr. expansion" }
index 70b841208f8460b417559a11a6b8ee7436d69b18..3ba440fec534ef8825adcc246d0ba6298405fde7 100644 (file)
@@ -45,11 +45,10 @@ constexpr bool
 f5 ()
 {
   int *p = new int;            // { dg-message "allocated here" }
-  return *p == 1;
+  return *p == 1;              // { dg-error "the content of uninitialized storage is not usable in a constant expression" }
 }
 
-constexpr auto v5 = f5 ();     // { dg-error "the content of uninitialized storage is not usable in a constant expression" }
-                               // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1 }
+constexpr auto v5 = f5 ();     // { dg-message "in 'constexpr' expansion of" }
 
 constexpr bool
 f6 ()
@@ -57,11 +56,10 @@ f6 ()
   int *p = new int (2);                // { dg-message "allocated here" }
   int *q = p;
   delete p;
-  return *q == 2;
+  return *q == 2;              // { dg-error "use of allocated storage after deallocation in a constant expression" }
 }
 
-constexpr auto v6 = f6 ();     // { dg-error "use of allocated storage after deallocation in a constant expression" }
-                               // { dg-message "in 'constexpr' expansion of" "" { target *-*-* } .-1  }
+constexpr auto v6 = f6 ();     // { dg-message "in 'constexpr' expansion of" }
 
 constexpr int *
 f7 ()
index b678788541ecb3b0b8aa607820016a3600fb68de..d2c49c41f916a3f8aca1bcc36c9bc68a02b55f3e 100644 (file)
@@ -11,15 +11,14 @@ struct S1
 struct alignas(64) S2
 {
     constexpr S2 ()
-    : m_tabS1()
+    : m_tabS1() // { dg-error "used before its definition" }
     {}
 
     S1 m_tabS1[7];
 };
 
 constinit S2 objX; // { dg-error ".constinit. variable .objX. does not have a constant initializer" }
-// { dg-error "used before its definition" "" { target *-*-* } .-1 }
-// // { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-2 }
+// { dg-message "in .constexpr. expansion of" "" { target *-*-* } .-1 }
 
 constexpr S1::S1 ()
 : m_i(14)
index 6b74090306b301b530085abbca371c7615236b0f..241e9976e8c0a9860426ea7a377af1aea3e8cae2 100644 (file)
@@ -14,8 +14,8 @@ is_corresponding_member (M1 S1::*m1, M2 S2::*m2) noexcept
 struct A { int a; };
 struct B;
 constexpr int B::*n = nullptr;
-constexpr auto a = std::is_corresponding_member (&A::a, n);    // { dg-error "invalid use of incomplete type 'struct B'" }
-constexpr auto b = std::is_corresponding_member (n, &A::a);    // { dg-error "invalid use of incomplete type 'struct B'" }
+constexpr auto a = std::is_corresponding_member (&A::a, n);    // { dg-message "in .constexpr. expansion of" }
+constexpr auto b = std::is_corresponding_member (n, &A::a);    // { dg-message "in .constexpr. expansion of" }
 
 void
 foo (int B::*m)
index d4ea7c58c0d8d051adbbeca8b3545158ca26747e..e09a27af3de9e3923093c8ca7d76e639f910a580 100644 (file)
@@ -4,7 +4,7 @@
 constexpr int
 fn_bad (int n)
 {
-  __extension__ int a [n] = { 0 };
+  __extension__ int a [n] = { 0 };  // { dg-error "array subscript" }
   int z = a [0] + (n ? fn_bad (n - 1) : 0); // { dg-message "in .constexpr. expansion of " } 
   return z;
 }
@@ -18,4 +18,4 @@ fn_ok (int n)
 }
 
 constexpr int i1 = fn_ok (3);
-constexpr int i2 = fn_bad (3); // { dg-error "array subscript|in .constexpr. expansion of " }
+constexpr int i2 = fn_bad (3); // { dg-message "in .constexpr. expansion of " }
index 538b576a8255cf3bb84e94d7c4df89e20aa4e114..6f9daa1897fe38bc9927a599732f9bc34b0eeb34 100644 (file)
@@ -4,11 +4,11 @@
 constexpr int
 foo (int n)
 {
-  __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 };
+  __extension__ int a[n] = { 1, 2, 3, 4, 5, 6 }; // { dg-error "array subscript" }
   int z = 0;
   for (int i = 0; i <= n; ++i)
     z += a[i];
   return z;
 }
 
-constexpr int n = foo (3); // { dg-error "array subscript|in .constexpr. expansion of " }
+constexpr int n = foo (3); // { dg-message "in .constexpr. expansion of " }
index 3a1596e6e2e93d57c41ed181d1ee3b69850d0667..6fd0b4f893ec954c57c755fbe1f7ae72a21204c6 100644 (file)
@@ -56,12 +56,13 @@ fn3 (int a, int b)
 {
   if (b != 2)
     a = a / b; // { dg-error "..7 / 0.. is not a constant expression" }
+               // { dg-error "overflow in constant expression" "" { target *-*-* } .-1 }
   return a;
 }
 
 constexpr int k1 = fn3 (8, 4);
 constexpr int k2 = fn3 (7, 0); // { dg-message "in .constexpr. expansion" }
-constexpr int k3 = fn3 (INT_MIN, -1); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr int k3 = fn3 (INT_MIN, -1); // { dg-message "in .constexpr. expansion of " }
 
 SA (k1 == 2);
 
@@ -100,13 +101,13 @@ constexpr int
 fn7 (const int *a, int b)
 {
   if (b != 3)
-    return fn6 (*a, b);
+    return fn6 (*a, b); // { dg-error "null pointer" }
   return 7;
 }
 
 constexpr int n1 = 7;
 constexpr int n2 = fn7 (&n1, 5);
-constexpr int n3 = fn7 ((const int *) 0, 8);  // { dg-error "null pointer|in .constexpr. expansion of " }
+constexpr int n3 = fn7 ((const int *) 0, 8);  // { dg-message "in .constexpr. expansion of " }
 
 constexpr int
 fn8 (int i)
@@ -122,15 +123,15 @@ constexpr int
 fn9 (int a, int b)
 {
   if (b != 0)
-    return a + b;
+    return a + b; // { dg-error "overflow in constant expression" }
   return a;
 }
 
 constexpr int p1 = fn9 (42, 7);
-constexpr int p2 = fn9 (__INT_MAX__, 1); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr int p2 = fn9 (__INT_MAX__, 1); // { dg-message "in .constexpr. expansion of " }
 constexpr int p3 = fn9 (__INT_MAX__, -1);
 constexpr int p4 = fn9 (INT_MIN, 1);
-constexpr int p5 = fn9 (INT_MIN, -1); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr int p5 = fn9 (INT_MIN, -1); // { dg-message "in .constexpr. expansion of " }
 
 SA (p1 == 49);
 SA (p3 == __INT_MAX__ - 1);
@@ -140,13 +141,13 @@ constexpr int
 fn10 (int a, int b)
 {
   if (b != 0)
-    return a * b;
+    return a * b; // { dg-error "overflow in constant expression" }
   return a;
 }
 
 constexpr int q1 = fn10 (10, 10);
-constexpr int q2 = fn10 (__INT_MAX__, 2); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
-constexpr int q3 = fn10 (INT_MIN, 2); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr int q2 = fn10 (__INT_MAX__, 2); // { dg-message "in .constexpr. expansion of " }
+constexpr int q3 = fn10 (INT_MIN, 2); // { dg-message "in .constexpr. expansion of " }
 constexpr int q4 = fn10 (-1, -1);
 
 SA (q1 == 100);
@@ -155,14 +156,14 @@ SA (q4 == 1);
 constexpr int
 fn11 (double d)
 {
-  int i = d;
+  int i = d; // { dg-error "overflow in constant expression" }
   if (i != 0)
     return i;
   return i * 2;
 }
 
 constexpr int r1 = fn11 (3.4);
-constexpr int r2 = fn11 (__builtin_inf ()); // { dg-error "overflow in constant expression|in .constexpr. expansion of " }
+constexpr int r2 = fn11 (__builtin_inf ()); // { dg-message "in .constexpr. expansion of " }
 
 constexpr int
 fn12 (int i)
index 34ca5c4805ccce6eacfa151b9ec4063316c62d71..fd89ac0e166d33597aca31ed7538d92e610759dc 100644 (file)
@@ -32,7 +32,7 @@ test01()
   return outa;
 }
 
-static_assert(test01()); // { dg-error "outside the bounds" }
+static_assert(test01()); // { dg-error "non-constant condition" }
 
 constexpr bool
 test02()
@@ -44,7 +44,8 @@ test02()
   return outa;
 }
 
-static_assert(test02()); // { dg-error "outside the bounds" }
+static_assert(test02()); // { dg-error "non-constant condition" }
 
-// { dg-prune-output "non-constant condition" }
+// Errors occuring within <algorithm> internals:
+// { dg-error "outside the bounds of array" "" { target *-*-* } 0 }
 // { dg-prune-output "in 'constexpr'" }
index 5b6fea7b5601df0e5e9b29d63bfbe5ad8819e193..bc9b29bc39d13ad4891a9f99d1eb1c2c413606f9 100644 (file)
@@ -13,9 +13,11 @@ static_assert( std::gcd(LLONG_MIN, 2ull) == 2 );
 static_assert( std::gcd(2ull, LLONG_MIN) == 2 );
 
 // But |INT_MIN| cannot be represented in common_type<int, int> i.e. int.
-constexpr int a = std::gcd(INT_MIN, 1); // { dg-error "overflow" }
-constexpr int b = std::gcd(1, INT_MIN); // { dg-error "overflow" }
+constexpr int a = std::gcd(INT_MIN, 1); // { dg-error "in .constexpr." }
+constexpr int b = std::gcd(1, INT_MIN); // { dg-error "in .constexpr." }
 
 // And |LLONG_MIN| cannot be represented in long.
-constexpr long long c = std::gcd(LLONG_MIN, 1); // { dg-error "overflow" }
-constexpr long long d = std::gcd(1, LLONG_MIN); // { dg-error "overflow" }
+constexpr long long c = std::gcd(LLONG_MIN, 1); // { dg-error "in .constexpr." }
+constexpr long long d = std::gcd(1, LLONG_MIN); // { dg-error "in .constexpr." }
+
+// { dg-error "overflow" "" { target *-*-* } 0 }
index d0e032e03e0005c873a68f2c9d575b9af968e190..d853974f77e94e3df290d3c5b768a6f6c653876a 100644 (file)
@@ -9,14 +9,16 @@ static_assert( std::lcm(INT_MIN, 1u) == INT_MAX+1u );
 static_assert( std::lcm(1u, INT_MIN) == INT_MAX+1u );
 
 // But |INT_MIN| cannot be represented in common_type<int, int> i.e. int.
-constexpr int a = std::lcm(INT_MIN, 1); // { dg-error "overflow" }
-constexpr int b = std::lcm(1, INT_MIN); // { dg-error "overflow" }
+constexpr int a = std::lcm(INT_MIN, 1); // { dg-error "in .constexpr." }
+constexpr int b = std::lcm(1, INT_MIN); // { dg-error "in .constexpr." }
 
 // And the LCM of 50000 and 49999 cannot be represented in int.
-constexpr int c = std::lcm(50000, 49999); // { dg-error "overflow" }
-constexpr int d = std::lcm(49999, 50000); // { dg-error "overflow" }
+constexpr int c = std::lcm(50000, 49999); // { dg-error "in .constexpr." }
+constexpr int d = std::lcm(49999, 50000); // { dg-error "in .constexpr." }
 
 // Similarly for unsigned, but the diagnostic is a failed assertion instead.
-constexpr int e = std::lcm(500000u, 499999); // { dg-error "in 'constexpr'" }
-constexpr int f = std::lcm(499999u, 500000); // { dg-error "in 'constexpr'" }
+constexpr int e = std::lcm(500000u, 499999); // { dg-error "in .constexpr." }
+constexpr int f = std::lcm(499999u, 500000); // { dg-error "in .constexpr." }
+
+// { dg-error "overflow" "" { target *-*-* } 0 }
 // { dg-error "unreachable" "" { target *-*-* } 0 }