re PR c++/84463 (Supposedly-incompliant "error: '* key0' is not a constant expression")
authorJakub Jelinek <jakub@redhat.com>
Wed, 18 Apr 2018 06:57:45 +0000 (08:57 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 18 Apr 2018 06:57:45 +0000 (08:57 +0200)
PR c++/84463
* typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
tricks from here to ...
* cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here.  Only use it
if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.

* g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
* g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
in two cases.  Uncomment two other tests and add expected dg-error for
them.
* g++.dg/init/struct2.C: Cast to int rather than long to avoid
-Wnarrowing diagnostics on some targets for c++11.
* g++.dg/parse/array-size2.C: Remove xfail.
* g++.dg/cpp0x/constexpr-84463.C: New test.

From-SVN: r259458

gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C
gcc/testsuite/g++.dg/init/struct2.C
gcc/testsuite/g++.dg/parse/array-size2.C

index ff6f412..c80b281 100644 (file)
@@ -1,3 +1,11 @@
+2018-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/84463
+       * typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
+       tricks from here to ...
+       * cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here.  Only use it
+       if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.
+
 2018-04-18  Alexandre Oliva <aoliva@redhat.com>
 
        PR c++/80290
index fb0aea3..7449065 100644 (file)
@@ -2215,6 +2215,28 @@ cp_fold (tree x)
       goto unary;
 
     case ADDR_EXPR:
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), false);
+
+      /* Cope with user tricks that amount to offsetof.  */
+      if (op0 != error_mark_node
+         && TREE_CODE (TREE_TYPE (op0)) != FUNCTION_TYPE
+         && TREE_CODE (TREE_TYPE (op0)) != METHOD_TYPE)
+       {
+         tree val = get_base_address (op0);
+         if (val
+             && INDIRECT_REF_P (val)
+             && COMPLETE_TYPE_P (TREE_TYPE (val))
+             && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+           {
+             val = TREE_OPERAND (val, 0);
+             STRIP_NOPS (val);
+             if (TREE_CODE (val) == INTEGER_CST)
+               return fold_convert (TREE_TYPE (x), fold_offsetof_1 (op0));
+           }
+       }
+      goto finish_unary;
+
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       rval_ops = false;
@@ -2232,6 +2254,7 @@ cp_fold (tree x)
       loc = EXPR_LOCATION (x);
       op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
 
+    finish_unary:
       if (op0 != TREE_OPERAND (x, 0))
        {
          if (op0 == error_mark_node)
index b449b1f..f5081c1 100644 (file)
@@ -5893,19 +5893,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
       return arg;
     }
 
-  /* ??? Cope with user tricks that amount to offsetof.  */
-  if (TREE_CODE (argtype) != FUNCTION_TYPE
-      && TREE_CODE (argtype) != METHOD_TYPE
-      && argtype != unknown_type_node
-      && (val = get_base_address (arg))
-      && COMPLETE_TYPE_P (TREE_TYPE (val))
-      && INDIRECT_REF_P (val)
-      && TREE_CONSTANT (TREE_OPERAND (val, 0)))
-    {
-      tree type = build_pointer_type (argtype);
-      return fold_convert (type, fold_offsetof_1 (arg));
-    }
-
   /* Handle complex lvalues (when permitted)
      by reduction to simpler cases.  */
   val = unary_complex_lvalue (ADDR_EXPR, arg);
index 6dba141..658b52d 100644 (file)
@@ -1,3 +1,15 @@
+2018-04-18  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/84463
+       * g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
+       * g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
+       in two cases.  Uncomment two other tests and add expected dg-error for
+       them.
+       * g++.dg/init/struct2.C: Cast to int rather than long to avoid
+       -Wnarrowing diagnostics on some targets for c++11.
+       * g++.dg/parse/array-size2.C: Remove xfail.
+       * g++.dg/cpp0x/constexpr-84463.C: New test.
+
 2018-04-17  Bill Schmidt  <wschmidt@linux.ibm.com>
 
        * gcc.target/powerpc/undef-bool-2.c: Add -mvsx.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C
new file mode 100644 (file)
index 0000000..0743059
--- /dev/null
@@ -0,0 +1,22 @@
+// PR c++/84463
+// { dg-do compile { target c++11 } }
+
+struct S { int r; const unsigned char s[5]; };
+static constexpr S a[] = { { 0, "abcd" } };
+struct T { const unsigned char s[5]; };
+static constexpr T b[] = { { "abcd" } };
+
+constexpr int
+foo (const unsigned char *x)
+{
+  return x[0];
+}
+
+constexpr static const S *j = &a[0];
+constexpr static const int k = j->s[0];
+constexpr static int l = foo (a[0].s);
+constexpr static int m = foo (j->s);
+constexpr static const T *n = &b[0];
+constexpr static const int o = n->s[0];
+constexpr static int p = foo (b[0].s);
+constexpr static int q = foo (n->s);
index e2f7917..ed53fcd 100644 (file)
@@ -6,7 +6,7 @@
 // c++/67376 on gcc-patches for additional background.
 
 // { dg-do compile { target c++11 } }
-// { dg-options "-fdelete-null-pointer-checks -fdump-tree-optimized" }
+// { dg-options "-O1 -fdelete-null-pointer-checks -fdump-tree-optimized" }
 
 // Runtime assert.  Used for potentially invalid expressions.
 #define RA(e)  ((e) ? (void)0 : __builtin_abort ())
index aeea87c..3b3f01a 100644 (file)
@@ -192,12 +192,11 @@ constexpr bool b11 = ps >= (S*)0;
 constexpr S* ps1 = ps;
 constexpr S* ps2 = ps1;
 
-// The following aren't diagnosed due to a bug.
-// constexpr int* pi0 = &((S*)0)->i;
-// constexpr int* pi1 = &((S*)nullptr)->i;
+constexpr int* pi0 = &((S*)0)->i;      // { dg-error "null pointer|not a constant" }
+constexpr int* pi1 = &((S*)nullptr)->i;        // { dg-error "null pointer|not a constant" }
 
-constexpr int* pj0 = &((S*)0)->j;      // { dg-error "not a constant expression" }
-constexpr int* pj1 = &((S*)nullptr)->j;  // { dg-error "not a constant expression" }
+constexpr int* pj0 = &((S*)0)->j;      // { dg-error "null pointer|not a constant" }
+constexpr int* pj1 = &((S*)nullptr)->j;        // { dg-error "null pointer|not a constant" }
 
 constexpr int* psi = &ps->i;       // { dg-error "null pointer|not a constant" }
 constexpr int* psj = &ps->j;       // { dg-error "null pointer|not a constant" }
index 85aacc6..4396feb 100644 (file)
@@ -15,7 +15,7 @@ void saveOrLoad() {
     };    
 
     SaveLoadEntry trackEntries = {
-       ((long) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42,
+       ((int) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42,
         0, 1
     };
     saveLoadEntries(&trackEntries);
index 3c83347..d0bc47f 100644 (file)
@@ -15,6 +15,6 @@ void
 foo (void)
 {
   char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
-  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];              // { dg-error "constant" "" { xfail *-*-* } }
+  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];              // { dg-error "constant" }
   bar (g, h);
 }