On Wed, Apr 18, 2018 at 03:14:19PM +0200, Jakub Jelinek wrote:
> On Wed, Apr 18, 2018 at 02:59:34PM +0200, Jakub Jelinek wrote:
> > On Wed, Apr 18, 2018 at 05:07:33AM +0000, Jason Merrill wrote:
> > > I wonder if it would work to use CONVERT_EXPR for reinterpret_cast.
> 
> As for reinterpret_cast, we e.g. accept
> constexpr int a = reinterpret_cast<int> (1);
> which clang++ rejects, shouldn't we simply in build_reinterpret_cast_1
> when not returning error_mark_node wrap the return value inside some new
> FE tree (or reuse REINTERPRET_CAST_EXPR) and remove it only during
> genericization, so that we can reliably reject those in constexpr handling,
> perhaps only if not !ctx->quiet?

So, I've tried that approach, and while it fixed some issues (e.g. PR49171),
even after changing various testcases (double checked with clang++ if it
indeed is invalid and should be rejected etc.), there are still some extra
FAILs with the patch, see below.  I think the addressof1.C are right,
pr55081.C is unfortunate optimization regression, while reinterpret_cast is
pedantically not a constant expression, if we are just trying to get a
constant value if possible it would be nice to get it.  Wonder if for
ctx->quiet we just could pretend the REINTERPRET_CAST_EXPR isn't in there.

Also, I've added removal of the REINTERPRET_CAST_EXPR trees (replacement
with their operand) into the gimplification langhook, so that we get 3
errors on:
constexpr int a = reinterpret_cast<int> (1);
constexpr int foo (int x) { return reinterpret_cast<int> (x); }
template <int N>
constexpr int bar (int x) { return reinterpret_cast<int> (x); }
constexpr int b = foo (1);
constexpr int c = bar <1> (1);
but nothing then removes it from static initializers.  I've added code
to do that into cp_fold if !current_function_decl, unfortunately
cp_fully_fold/cp_fold doesn't really walk all trees (e.g. it doesn't handle
COMPONENT_REF), so the cp_fully_fold called from store_init_value wasn't
enough; thus the patch does another call with cp_fold_r recursion.

In any case, this reinterpret_cast constexpr pedantic stuff looks too
large/risky at this point to me, I wonder if we accept-invalid even the
simple constexpr int a = reinterpret_cast<int> (1); whether it is not ok for
GCC8 to not error out on reinterpret_cast from PTRMEM_CSTs too, essentially
just use Alex's patch for expr.c and the first hunk from this patch from
constexpr.c, plus the new testcases and deal with the rest for stage1. 
Thoughts on this?

FAIL: g++.dg/cpp0x/addressof1.C  -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/addressof1.C  -std=c++14 (test for excess errors)
FAIL: g++.dg/cpp0x/addressof1.C  -std=c++17 (test for excess errors)
FAIL: g++.dg/cpp0x/addressof1.C  -std=c++2a (test for excess errors)
FAIL: g++.dg/cpp0x/addressof1.C  -std=c++17 -fconcepts (test for excess errors)
FAIL: g++.dg/opt/pr55081.C  -std=c++98  scan-assembler-not _ZGVZ3foovE5array
FAIL: g++.dg/opt/pr55081.C  -std=c++11  scan-assembler-not _ZGVZ3foovE5array
FAIL: g++.dg/opt/pr55081.C  -std=c++14  scan-assembler-not _ZGVZ3foovE5array
FAIL: g++.dg/opt/pr55081.C  -std=c++17  scan-assembler-not _ZGVZ3foovE5array
FAIL: g++.dg/opt/pr55081.C  -std=c++2a  scan-assembler-not _ZGVZ3foovE5array
FAIL: g++.dg/opt/pr55081.C  -std=c++17 -fconcepts  scan-assembler-not 
_ZGVZ3foovE5array
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++98  (test for warnings, line 
128)
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++11  (test for warnings, line 
128)
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++14  (test for warnings, line 
128)
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++17  (test for warnings, line 
128)
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++2a  (test for warnings, line 
128)
FAIL: g++.dg/warn/Wplacement-new-size.C  -std=gnu++17 -fconcepts  (test for 
warnings, line 128)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++11  (test for bogus messages, line 
12)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++11 (test for excess errors)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++14  (test for bogus messages, line 
12)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++14 (test for excess errors)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++17  (test for bogus messages, line 
12)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++17 (test for excess errors)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++2a  (test for bogus messages, line 
12)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++2a (test for excess errors)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++17 -fconcepts  (test for bogus 
messages, line 12)
FAIL: c-c++-common/Waddress-1.c  -std=gnu++17 -fconcepts (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++98 (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++11 (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++14 (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++17 (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++2a (test for excess 
errors)
FAIL: c-c++-common/Wsizeof-pointer-memaccess2.c  -std=gnu++17 -fconcepts (test 
for excess errors)
FAIL: g++.dg/torture/Wsizeof-pointer-memaccess1.C   -O0  (test for excess 
errors)
FAIL: g++.dg/torture/Wsizeof-pointer-memaccess1.C   -O2  (test for excess 
errors)
FAIL: g++.dg/torture/Wsizeof-pointer-memaccess2.C   -O0  (test for excess 
errors)
FAIL: g++.dg/torture/Wsizeof-pointer-memaccess2.C   -O2  (test for excess 
errors)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++11  (test for errors, line 26)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++11  (test for errors, line 27)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++14  (test for errors, line 26)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++14  (test for errors, line 27)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++17  (test for errors, line 26)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++17  (test for errors, line 27)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++2a  (test for errors, line 26)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++2a  (test for errors, line 27)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++17 -fconcepts  (test for errors, 
line 26)
FAIL: g++.old-deja/g++.pt/ptrmem6.C  -std=c++17 -fconcepts  (test for errors, 
line 27)

--- gcc/cp/typeck2.c.jj 2018-04-05 20:34:31.547020700 +0200
+++ gcc/cp/typeck2.c    2018-04-18 17:15:39.743824283 +0200
@@ -846,6 +846,8 @@ store_init_value (tree decl, tree init,
        TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
     }
   value = cp_fully_fold (value);
+  if (!processing_template_decl)
+    value = cp_fold_init (value);
 
   /* Handle aggregate NSDMI in non-constant initializers, too.  */
   value = replace_placeholders (value, decl);
--- gcc/cp/constexpr.c.jj       2018-04-13 10:33:03.078658240 +0200
+++ gcc/cp/constexpr.c  2018-04-18 15:53:07.936504106 +0200
@@ -4596,20 +4596,7 @@ cxx_eval_constant_expression (const cons
            && !TYPE_PTRMEM_P (type))
          op = cplus_expand_constant (op);
        if (TREE_CODE (op) == PTRMEM_CST && tcode == NOP_EXPR)
-         {
-           if (same_type_ignoring_top_level_qualifiers_p (type,
-                                                          TREE_TYPE (op))
-               || can_convert_qual (type, op))
-             return cp_fold_convert (type, op);
-           else
-             {
-               if (!ctx->quiet)
-                 error_at (EXPR_LOC_OR_LOC (t, input_location),
-                           "a reinterpret_cast is not a constant expression");
-               *non_constant_p = true;
-               return t;
-             }
-         }
+         return cp_fold_convert (type, op);
 
        if (POINTER_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST)
          {
@@ -4669,6 +4656,13 @@ cxx_eval_constant_expression (const cons
       }
       break;
 
+    case REINTERPRET_CAST_EXPR:
+      if (!ctx->quiet)
+        error_at (EXPR_LOC_OR_LOC (t, input_location),
+                 "a %<reinterpret_cast%> is not a constant expression");
+      *non_constant_p = true;
+      return t;
+
     case EMPTY_CLASS_EXPR:
       /* This is good enough for a function argument that might not get
         used, and they can't do anything with it, so just return it.  */
--- gcc/cp/typeck.c.jj  2018-04-18 08:57:09.555612419 +0200
+++ gcc/cp/typeck.c     2018-04-18 18:57:02.422847534 +0200
@@ -7281,7 +7281,7 @@ convert_member_func_to_ptr (tree type, t
    indicate whether or not reinterpret_cast was valid.  */
 
 static tree
-build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
+build_reinterpret_cast_2 (tree type, tree expr, bool c_cast_p,
                          bool *valid_p, tsubst_flags_t complain)
 {
   tree intype;
@@ -7334,9 +7334,8 @@ build_reinterpret_cast_1 (tree type, tre
        strict_aliasing_warning (EXPR_LOCATION (expr), type, expr);
 
       if (expr != error_mark_node)
-       expr = build_reinterpret_cast_1
-         (build_pointer_type (TREE_TYPE (type)), expr, c_cast_p,
-          valid_p, complain);
+       expr = build_reinterpret_cast_2 (build_pointer_type (TREE_TYPE (type)),
+                                        expr, c_cast_p, valid_p, complain);
       if (expr != error_mark_node)
        /* cp_build_indirect_ref isn't right for rvalue refs.  */
        expr = convert_from_reference (fold_convert (type, expr));
@@ -7476,6 +7475,20 @@ build_reinterpret_cast_1 (tree type, tre
   return cp_convert (type, expr, complain);
 }
 
+static tree
+build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
+                         bool *valid_p, tsubst_flags_t complain)
+{
+  tree ret = build_reinterpret_cast_2 (type, expr, c_cast_p, valid_p,
+                                      complain);
+  if (error_operand_p (ret))
+    return ret;
+  ret = build1_loc (EXPR_LOC_OR_LOC (ret, input_location),
+                   REINTERPRET_CAST_EXPR, TREE_TYPE (ret), ret);
+  REINTERPRET_CAST_EXPR_NONCONST_P (ret) = 1;
+  return ret;
+}
+
 tree
 build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain)
 {
--- gcc/cp/cp-tree.h.jj 2018-04-18 08:48:40.650853869 +0200
+++ gcc/cp/cp-tree.h    2018-04-18 18:23:55.383829396 +0200
@@ -372,6 +372,7 @@ extern GTY(()) tree cp_global_trees[CPTI
       TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM)
       DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL)
       SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT)
+      REINTERPRET_CAST_EXPR_NONCONST_P (in REINTERPRET_CAST_EXPR)
    1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -4954,6 +4955,11 @@ more_aggr_init_expr_args_p (const aggr_i
 #define SIZEOF_EXPR_TYPE_P(NODE) \
   TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE))
 
+/* True if REINTERPRET_CAST_EXPR is added just for constexpr handling
+   purposes.  */
+#define REINTERPRET_CAST_EXPR_NONCONST_P(NODE) \
+  TREE_LANG_FLAG_0 (REINTERPRET_CAST_EXPR_CHECK (NODE))
+
 /* An enumeration of the kind of tags that C++ accepts.  */
 enum tag_types {
   none_type = 0, /* Not a tag type.  */
@@ -7402,6 +7408,7 @@ extern void cxx_omp_finish_clause         (tree
 extern bool cxx_omp_privatize_by_reference     (const_tree);
 extern bool cxx_omp_disregard_value_expr       (tree, bool);
 extern void cp_fold_function                   (tree);
+extern tree cp_fold_init                       (tree);
 extern tree cp_fully_fold                      (tree);
 extern void clear_fold_cache                   (void);
 
--- gcc/cp/cp-gimplify.c.jj     2018-04-18 08:57:09.556612418 +0200
+++ gcc/cp/cp-gimplify.c        2018-04-18 16:55:59.771231237 +0200
@@ -740,6 +740,11 @@ cp_gimplify_expr (tree *expr_p, gimple_s
       ret = GS_OK;
       break;
 
+    case REINTERPRET_CAST_EXPR:
+      *expr_p = TREE_OPERAND (*expr_p, 0);
+      ret = GS_OK;
+      break;
+
     case UNARY_PLUS_EXPR:
       {
        tree arg = TREE_OPERAND (*expr_p, 0);
@@ -1038,6 +1043,16 @@ cp_fold_function (tree fndecl)
   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &pset, NULL);
 }
 
+/* Similarly, but for initializer expression.  */
+
+tree
+cp_fold_init (tree init)
+{
+  hash_set<tree> pset;
+  cp_walk_tree (&init, cp_fold_r, &pset, NULL);
+  return init;
+}
+
 /* Perform any pre-gimplification lowering of C++ front end trees to
    GENERIC.  */
 
@@ -2205,6 +2224,12 @@ cp_fold (tree x)
 
       break;
 
+    case REINTERPRET_CAST_EXPR:
+      if (TREE_TYPE (x) == NULL_TREE || current_function_decl)
+       return x;
+      /* Remove REINTERPRET_CAST_EXPRs outside of functions.  */
+      return cp_fold (TREE_OPERAND (x, 0));
+
     case INDIRECT_REF:
       /* We don't need the decltype(auto) obfuscation anymore.  */
       if (REF_PARENTHESIZED_P (x))
--- gcc/cp/tree.c.jj    2018-04-11 09:16:20.076859100 +0200
+++ gcc/cp/tree.c       2018-04-18 18:25:58.107895003 +0200
@@ -96,6 +96,16 @@ lvalue_kind (const_tree ref)
     case IMAGPART_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
+    case REINTERPRET_CAST_EXPR:
+      if (REINTERPRET_CAST_EXPR_NONCONST_P (ref))
+        return lvalue_kind (TREE_OPERAND (ref, 0));
+      if (!TREE_TYPE (ref))
+       return clk_none;
+      if (CLASS_TYPE_P (TREE_TYPE (ref))
+         || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
+       return clk_class;
+      break;
+
     case MEMBER_REF:
     case DOTSTAR_EXPR:
       if (TREE_CODE (ref) == MEMBER_REF)
--- gcc/cp/expr.c.jj    2018-03-09 23:22:23.682236182 +0100
+++ gcc/cp/expr.c       2018-04-18 14:24:52.692310448 +0200
@@ -50,11 +50,36 @@ cplus_expand_constant (tree cst)
            while (!same_type_p (DECL_CONTEXT (member),
                                 TYPE_PTRMEM_CLASS_TYPE (type)))
              {
+               tree t1 = TYPE_MAIN_VARIANT (DECL_CONTEXT (member));
+               tree t2 = TYPE_MAIN_VARIANT (TYPE_PTRMEM_CLASS_TYPE (type));
+
+               if (can_convert (t2, t1, 0))
+                 {
+                   base_kind kind;
+                   tree binfo = lookup_base (t1, t2, ba_unique, &kind, 0);
+                   if (binfo != error_mark_node
+                       && kind != bk_via_virtual)
+                     cst = size_binop (MINUS_EXPR, cst, BINFO_OFFSET (binfo));
+                   break;
+                 }
+
+               if (can_convert (t1, t2, 0))
+                 {
+                   base_kind kind;
+                   tree binfo = lookup_base (t2, t1, ba_unique, &kind, 0);
+                   if (binfo != error_mark_node
+                       && kind != bk_via_virtual)
+                     cst = size_binop (PLUS_EXPR, cst, BINFO_OFFSET (binfo));
+                   break;
+                 }
+
                /* The MEMBER must have been nestled within an
                   anonymous aggregate contained in TYPE.  Find the
                   anonymous aggregate.  */
                member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
                                            DECL_CONTEXT (member));
+               if (!member)
+                 break;
                cst = size_binop (PLUS_EXPR, cst, byte_position (member));
              }
            cst = fold (build_nop (type, cst));
--- gcc/testsuite/g++.dg/template/pr79650.C.jj  2017-12-14 09:16:03.000000000 
+0100
+++ gcc/testsuite/g++.dg/template/pr79650.C     2018-04-18 18:55:00.215787515 
+0200
@@ -11,10 +11,10 @@ foo ()
   static int a, b;
 lab1:
 lab2:
-  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c;     // { dg-error "not a 
constant integer" }
-  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d;
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c;     // { dg-error "is not a 
constant expression" }
+  A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d;     // { dg-error "is not a 
constant expression" }
   A<(intptr_t)&a - (intptr_t)&b> e;                    // { dg-error "is not a 
constant expression" }
-  A<(intptr_t)&a - (intptr_t)&a> f;
-  A<(intptr_t)sizeof(a) + (intptr_t)&a> g;             // { dg-error "not a 
constant integer" }
-  A<(intptr_t)&a> h;                                   // { dg-error 
"conversion from pointer type" }
+  A<(intptr_t)&a - (intptr_t)&a> f;                    // { dg-error "is not a 
constant expression" }
+  A<(intptr_t)sizeof(a) + (intptr_t)&a> g;             // { dg-error "is not a 
constant expression" }
+  A<(intptr_t)&a> h;                                   // { dg-error "is not a 
constant expression" }
 }
--- gcc/testsuite/g++.dg/template/arg9.C.jj     2013-07-03 22:19:53.000000000 
+0200
+++ gcc/testsuite/g++.dg/template/arg9.C        2018-04-18 17:50:04.116741326 
+0200
@@ -5,4 +5,4 @@ template <int N>
 struct S {};
 
 S <static_cast <int> (4>>2)> s1;
-S <reinterpret_cast <int> (4>>2)> s2;
+S <reinterpret_cast <int> (4>>2)> s2;  // { dg-error "not a constant 
expression" }
--- gcc/testsuite/g++.dg/other/vararg-2.C.jj    2008-09-05 12:55:01.000000000 
+0200
+++ gcc/testsuite/g++.dg/other/vararg-2.C       2018-04-18 18:50:03.687641434 
+0200
@@ -5,7 +5,7 @@ typedef __gnuc_va_list va_list;
  QString & sprintf(QString &s,const QString &szFmt,...)
  {
   va_list list;
-  __builtin_va_start(list,((const char *)(&(szFmt))));
+  __builtin_va_start(list,((const QString *)(&(szFmt))));
   __builtin_va_end(list);
   return s;
  }
--- gcc/testsuite/g++.dg/ubsan/vptr-4.C.jj      2015-01-15 23:57:07.634969888 
+0100
+++ gcc/testsuite/g++.dg/ubsan/vptr-4.C 2018-04-18 20:07:27.912955144 +0200
@@ -15,11 +15,11 @@ struct T : S {
   int b;
   int g() { return 0; }
   virtual int v() { return 1; }
-  constexpr const T *foo() { return (const T *) reinterpret_cast<const S *> 
(this); }
+  constexpr const T *foo() { return (const T *) reinterpret_cast<const S *> 
(this); } // { dg-error "not a constant" }
 };
 
 constexpr T t;
-constexpr const T *p = t.foo ();
+constexpr const T *p = t.foo ();       // { dg-message "in .constexpr. 
expansion" }
 
 template <typename U>
 struct V {
@@ -35,19 +35,19 @@ struct W : V<U> {
   int b;
   int g() { return 0; }
   virtual int v() { return 1; }
-  constexpr const W<U> *foo() { return (const W<U> *) reinterpret_cast<const 
V<U> *> (this); }
+  constexpr const W<U> *foo() { return (const W<U> *) reinterpret_cast<const 
V<U> *> (this); } // { dg-error "not a constant" }
 };
 
 constexpr W<int> w;
-constexpr const W<int> *s = w.foo ();
+constexpr const W<int> *s = w.foo ();  // { dg-message "in .constexpr. 
expansion" }
 
 template <typename U>
 int foo (void)
 {
   static constexpr T t;
-  static constexpr const T *p = t.foo ();
+  static constexpr const T *p = t.foo ();      // { dg-message "in .constexpr. 
expansion" }
   static constexpr W<U> w;
-  static constexpr const W<U> *s = w.foo ();
+  static constexpr const W<U> *s = w.foo ();   // { dg-message "in .constexpr. 
expansion" }
   return t.b + w.b;
 }
 
--- gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C.jj    2017-11-21 
20:22:59.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C       2018-04-18 
17:54:39.633875863 +0200
@@ -6,4 +6,4 @@ constexpr __PTRDIFF_TYPE__ bar (int a)
   return ((__PTRDIFF_TYPE__) &p) << a; // { dg-error "is not a constant 
expression" }
 }
 constexpr __PTRDIFF_TYPE__ r = bar (2); // { dg-message "in .constexpr. 
expansion of" }
-constexpr __PTRDIFF_TYPE__ s = bar (0); // { dg-error "conversion from 
pointer" }
+constexpr __PTRDIFF_TYPE__ s = bar (0); // { dg-message "in .constexpr. 
expansion of" }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C.jj 2018-04-18 
08:57:09.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C    2018-04-18 
19:07:24.750136620 +0200
@@ -99,9 +99,7 @@ constexpr const volatile void* pv3 = p0;
 constexpr void* pv4 = static_cast<void*>(p0);
 constexpr const void* pv5 = static_cast<const void*>(p0);
 
-// The following should be rejected but isn't because of bug c++/49171
-// - [C++0x][constexpr] Constant expressions support reinterpret_cast
-constexpr void* pv6 = reinterpret_cast<void*>(p0);   // { dg-error "" "bug 
c++/49171" { xfail *-*-* } }
+constexpr void* pv6 = reinterpret_cast<void*>(p0);   // { dg-error "not a 
constant" }
 
 // Adding or subtracting zero from a null pointer is valid in C++.
 constexpr int* p1 = p0 + 0;
--- gcc/testsuite/g++.dg/cpp0x/pr85437.C.jj     2018-04-18 14:25:50.655332890 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437.C        2018-04-18 14:28:34.234396893 
+0200
@@ -0,0 +1,17 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { int a; constexpr A() : a(0) {} };
+struct B : A { int x; constexpr B() : x(0) {} };
+struct X { int z; constexpr X() : z(0) {} };
+struct C : X, B {};
+constexpr int C::*cbx = &B::x;
+constexpr int B::*bx = &B::x;
+constexpr int A::*abx = static_cast<int(A::*)>(&B::x); // { dg-bogus "not a 
constant expression" }
+
+constexpr const C y;
+constexpr const B& yb = y;
+constexpr const A& ya = y;
+constexpr int const *pcbx = &(y.*cbx);
+constexpr int const *pbx = &(y.*bx);
+constexpr int const *pabx = &(ya.*abx);
--- gcc/testsuite/g++.dg/cpp0x/constexpr-union.C.jj     2014-03-10 
10:50:13.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-union.C        2018-04-18 
18:44:16.139470221 +0200
@@ -13,4 +13,4 @@ constexpr float f = u.f;
 constexpr unsigned char c = u.ca[0]; // { dg-error "U::ca" }
 
 constexpr double d = 1.0;
-constexpr unsigned char c2 = (unsigned char&)d; // { dg-error "char. glvalue" }
+constexpr unsigned char c2 = (unsigned char&)d; // { dg-error "char. 
glvalue|not a constant expression" }
--- gcc/testsuite/g++.dg/cpp0x/pr85437-3.C.jj   2018-04-18 14:25:50.655332890 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-3.C      2018-04-18 14:29:57.691429562 
+0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { int y; };
+struct B { int x; };
+struct C : A, B {};
+constexpr int C::*pci = &B::x;
+constexpr int A::*pai = static_cast<int A::*>(static_cast<int C::*>(&B::x)); 
// { dg-bogus "not a constant expression" }
--- gcc/testsuite/g++.dg/cpp0x/pr85437-2.C.jj   2018-04-18 14:25:50.654332889 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-2.C      2018-04-18 14:28:45.613401350 
+0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B : A { int x; };
+
+constexpr int A::*abx
+= reinterpret_cast<int(A::*)>(&B::x); // { dg-error "reinterpret.*constant" }
--- gcc/testsuite/g++.dg/cpp0x/pr85437-4.C.jj   2018-04-18 14:29:29.028418341 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/pr85437-4.C      2018-04-18 14:29:39.829422569 
+0200
@@ -0,0 +1,8 @@
+// PR c++/85437
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B { int x; };
+struct C : A, B {};
+constexpr int C::*pci = &B::x;
+constexpr int A::*pai = static_cast<int A::*>(pci);    // { dg-bogus "not a 
constant expression" }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C.jj      2018-01-30 
12:30:26.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C 2018-04-18 
18:51:34.156686004 +0200
@@ -17,8 +17,8 @@ public:
   constexpr static Inner & getInner()
   /* I am surprised this is considered a constexpr */
   {
-    return *((Inner *)4); // { dg-error "reinterpret_cast" }
-  }
+    return *((Inner *)4);
+  } // { dg-error "reinterpret_cast" }
 };
 
 B B::instance;
--- gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C.jj      2014-03-10 
10:50:13.134984620 +0100
+++ gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C 2018-04-18 17:36:11.261363805 
+0200
@@ -4,7 +4,7 @@ void f(int &);
 void f(int &&ir) { ir = 42; }
 int main()
 {
-  int x;
+  int x = 6;
   f(reinterpret_cast<int&&>(x));
   return (x != 42);
 }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C.jj      2017-11-21 
20:22:57.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C 2018-04-18 19:13:28.837305748 
+0200
@@ -4,20 +4,19 @@
 
 int i;
 
-// The following is accepted due to bug 49171.
-constexpr void *q = reinterpret_cast<void*>(&i);    // { dg-error "" "bug 
c++/49171" { xfail *-*-* } }
+constexpr void *q = reinterpret_cast<void*>(&i);    // { dg-error 
".reinterpret_cast. is not a constant expression" }
 
 constexpr void *r0 = reinterpret_cast<void*>(1);    // { dg-error "not a 
constant expression|reinterpret_cast from integer to pointer" }
-constexpr void *r1 = reinterpret_cast<void*>(sizeof 'x');  // { dg-error 
".reinterpret_cast<void\\*>\\(1\[ul\]\*\\). is not a constant expression" }
+constexpr void *r1 = reinterpret_cast<void*>(sizeof 'x');  // { dg-error 
".reinterpret_cast. is not a constant expression" }
 
 template <class T>
 constexpr bool f ()
 {
 #if __cplusplus > 201103L
-  T *p = reinterpret_cast<T*>(sizeof (T));
+  T *p = reinterpret_cast<T*>(sizeof (T));     // { dg-error "not a constant 
expression" "" { target c++14 } }
   return p;
 #else
-  return *reinterpret_cast<T*>(sizeof (T));
+  return *reinterpret_cast<T*>(sizeof (T));    // { dg-error "not a constant 
expression" "" { target c++11_only } }
 #endif
 }
 
--- gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C.jj      2014-03-10 
10:49:46.000000000 +0100
+++ gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C 2018-04-18 20:10:20.627042624 
+0200
@@ -23,10 +23,10 @@ int main() {
   h<&A::i>();
   g<&B::f>(); // { dg-error "" } 
   h<&B::j>(); // { dg-error "" } 
-  g<(void (A::*)()) &A::f>(); // { dg-error "" "" { xfail c++11 } }
-  h<(int A::*) &A::i>(); // { dg-error "" "" { xfail c++11 } }
+  g<(void (A::*)()) &A::f>(); // { dg-error "" }
+  h<(int A::*) &A::i>(); // { dg-error "" }
   g<(void (A::*)()) &B::f>(); // { dg-error "" "" { xfail { c++11 && { 
aarch64*-*-* arm*-*-* mips*-*-* } } } }
-  h<(int A::*) &B::j>(); // { dg-error "" } 
+  h<(int A::*) &B::j>(); // { dg-error "" "" { xfail { c++17 } } } 
   g<(void (A::*)()) 0>(); // { dg-error "" "" { target { ! c++11 } } }
   h<(int A::*) 0>(); // { dg-error "" "" { target { ! c++11 } } }
 

        Jakub

Reply via email to