public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/81073, constexpr and static var in statement-expression
@ 2017-06-19 17:42 Jason Merrill
  2017-06-20  9:40 ` Andreas Schwab
  0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2017-06-19 17:42 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 679 bytes --]

The testcase successfully compiles, but then fails to link because
we've optimized away the declaration of the variable.  We catch this
in potential_constant_expression_1, but this path wasn't calling it.

Fixed on trunk by always calling that function, not just in templates.
With that change, I needed to adjust pce1 to not require that a
variable be initialized yet, so that we can check it within the
initializer.  To avoid that causing some missed errors,
decl_maybe_constant_var_p now considers the initializer if it is
already known.

Fixed on 7 branch more simply, by calling p_c_e from
cxx_eval_constant_expression.

Tested x86_64-pc-linux-gnu, applying to trunk and 7.

[-- Attachment #2: 81073.diff --]
[-- Type: text/plain, Size: 5949 bytes --]

commit 46761de0ab74a6983c931c13bfb78c095ae4f651
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Jun 17 00:00:21 2017 -0400

            PR c++/81073 - constexpr and static var in statement-expression.
    
            * typeck2.c (store_init_value): Always call
            require_potential_constant_expression.
            * pt.c (convert_nontype_argument): Likewise.
            * constexpr.c (potential_constant_expression_1): Adjust message.
            Use decl_maybe_constant_var_p instead of decl_constant_var_p.
            * decl2.c (decl_maybe_constant_var_p): Consider initializer.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index ae24e40..569a247 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5212,10 +5212,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       if (want_rval
 	  && !var_in_maybe_constexpr_fn (t)
 	  && !type_dependent_expression_p (t)
-	  && !decl_constant_var_p (t)
+	  && !decl_maybe_constant_var_p (t)
 	  && (strict
 	      || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
-	      || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
+	      || (DECL_INITIAL (t)
+		  && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)))
 	  && COMPLETE_TYPE_P (TREE_TYPE (t))
 	  && !is_really_empty_class (TREE_TYPE (t)))
         {
@@ -5540,21 +5541,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
 	    {
 	      if (flags & tf_error)
 		error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
-			  "%<static%> in %<constexpr%> function", tmp);
+			  "%<static%> in %<constexpr%> context", tmp);
 	      return false;
 	    }
 	  else if (CP_DECL_THREAD_LOCAL_P (tmp))
 	    {
 	      if (flags & tf_error)
 		error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
-			  "%<thread_local%> in %<constexpr%> function", tmp);
+			  "%<thread_local%> in %<constexpr%> context", tmp);
 	      return false;
 	    }
 	  else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp))
 	    {
 	      if (flags & tf_error)
 		error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized "
-			  "variable %qD in %<constexpr%> function", tmp);
+			  "variable %qD in %<constexpr%> context", tmp);
 	      return false;
 	    }
 	}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 72239ec..a475146 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4145,10 +4145,19 @@ decl_maybe_constant_var_p (tree decl)
     /* A proxy isn't constant.  */
     return false;
   if (TREE_CODE (type) == REFERENCE_TYPE)
-    /* References can be constant.  */
+    /* References can be constant.  */;
+  else if (CP_TYPE_CONST_NON_VOLATILE_P (type)
+	   && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+    /* And const integers.  */;
+  else
+    return false;
+
+  if (DECL_INITIAL (decl)
+      && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+    /* We know the initializer, and it isn't constant.  */
+    return false;
+  else
     return true;
-  return (CP_TYPE_CONST_NON_VOLATILE_P (type)
-	  && INTEGRAL_OR_ENUMERATION_TYPE_P (type));
 }
 
 /* Complain that DECL uses a type with no linkage.  In C++98 mode this is
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e5238ad..69ca929 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6585,10 +6585,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 	  if (complain & tf_error)
 	    {
 	      int errs = errorcount, warns = warningcount + werrorcount;
-	      if (processing_template_decl
-		  && !require_potential_constant_expression (expr))
-		return NULL_TREE;
-	      expr = cxx_constant_value (expr);
+	      if (!require_potential_constant_expression (expr))
+		expr = error_mark_node;
+	      else
+		expr = cxx_constant_value (expr);
 	      if (errorcount > errs || warningcount + werrorcount > warns)
 		inform (loc, "in template argument for type %qT ", type);
 	      if (expr == error_mark_node)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 4623d6d..430ba30 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -821,8 +821,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
 	  || (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl)))
 	{
 	  /* Diagnose a non-constant initializer for constexpr.  */
-	  if (processing_template_decl
-	      && !require_potential_constant_expression (value))
+	  if (!require_potential_constant_expression (value))
 	    value = error_mark_node;
 	  else
 	    value = cxx_constant_value (value, decl);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
index 450a0b5..ccb8d81 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
@@ -16,5 +16,5 @@ constexpr int i = ai.f();
 constexpr int b = A<B>().f();	// { dg-error "" }
 
 template <class T>
-constexpr int f (T t) { return 42; } // { dg-error "parameter" }
-constexpr int x = f(B());	     // { dg-error "constexpr" }
+constexpr int f (T t) { return 42; }
+constexpr int x = f(B());	     // { dg-error "non-literal" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
index d241114..005f07b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
@@ -10,5 +10,5 @@ struct T
 
 int main()
 {
-    constexpr T t = (T{} = T{});
+    constexpr T t = (T{} = T{}); // { dg-error "" "" { target c++11_only } }
 }
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr19.C b/gcc/testsuite/g++.dg/ext/stmtexpr19.C
new file mode 100644
index 0000000..0c19a21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/stmtexpr19.C
@@ -0,0 +1,17 @@
+// PR c++/81073
+// { dg-options "" }
+// { dg-do compile { target c++11 } }
+
+struct test { const int *addr; };
+
+const test* setup()
+{
+  static constexpr test atest =
+    {
+      ({ static const int inner = 123; &inner; }) // { dg-error "static" }
+    };
+
+  return &atest;
+}
+
+int main(){}

[-- Attachment #3: 81073-7.diff --]
[-- Type: text/plain, Size: 1340 bytes --]

commit c477f412dd8521342ab5a5f702b00177512ad36e
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jun 19 12:28:11 2017 -0400

            PR c++/81073 - constexpr and static var in statement-expression.
    
            * constexpr.c (cxx_eval_constant_expression) [DECL_EXPR]: Check
            potential_constant_expression.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 244b8fd..a28bd02 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4021,6 +4021,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case DECL_EXPR:
+      if (!potential_constant_expression (t))
+	{
+	  if (!ctx->quiet)
+	    require_potential_constant_expression (t);
+	  *non_constant_p = true;
+	  break;
+	}
       {
 	r = DECL_EXPR_DECL (t);
 	if (AGGREGATE_TYPE_P (TREE_TYPE (r))
diff --git a/gcc/testsuite/g++.dg/ext/stmtexpr19.C b/gcc/testsuite/g++.dg/ext/stmtexpr19.C
new file mode 100644
index 0000000..0c19a21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/stmtexpr19.C
@@ -0,0 +1,17 @@
+// PR c++/81073
+// { dg-options "" }
+// { dg-do compile { target c++11 } }
+
+struct test { const int *addr; };
+
+const test* setup()
+{
+  static constexpr test atest =
+    {
+      ({ static const int inner = 123; &inner; }) // { dg-error "static" }
+    };
+
+  return &atest;
+}
+
+int main(){}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C++ PATCH for c++/81073, constexpr and static var in statement-expression
  2017-06-19 17:42 C++ PATCH for c++/81073, constexpr and static var in statement-expression Jason Merrill
@ 2017-06-20  9:40 ` Andreas Schwab
  2017-06-20 18:50   ` Jason Merrill
  0 siblings, 1 reply; 6+ messages in thread
From: Andreas Schwab @ 2017-06-20  9:40 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 10)
FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 (test for excess errors)
FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14  (test for errors, line 10)
FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14 (test for excess errors)

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C++ PATCH for c++/81073, constexpr and static var in statement-expression
  2017-06-20  9:40 ` Andreas Schwab
@ 2017-06-20 18:50   ` Jason Merrill
  2017-06-20 19:45     ` Andreas Schwab
  0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2017-06-20 18:50 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: gcc-patches List

On Tue, Jun 20, 2017 at 5:40 AM, Andreas Schwab <schwab@suse.de> wrote:
> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 10)
> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 (test for excess errors)
> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14  (test for errors, line 10)
> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14 (test for excess errors)

I'm not seeing this.  Can you give more detail?

Jason

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C++ PATCH for c++/81073, constexpr and static var in statement-expression
  2017-06-20 18:50   ` Jason Merrill
@ 2017-06-20 19:45     ` Andreas Schwab
  2017-06-21 10:32       ` Jakub Jelinek
  0 siblings, 1 reply; 6+ messages in thread
From: Andreas Schwab @ 2017-06-20 19:45 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Jun 20 2017, Jason Merrill <jason@redhat.com> wrote:

> On Tue, Jun 20, 2017 at 5:40 AM, Andreas Schwab <schwab@suse.de> wrote:
>> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 10)
>> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 (test for excess errors)
>> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14  (test for errors, line 10)
>> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14 (test for excess errors)
>
> I'm not seeing this.  Can you give more detail?

http://gcc.gnu.org/ml/gcc-testresults/2017-06/msg02172.html

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C++ PATCH for c++/81073, constexpr and static var in statement-expression
  2017-06-20 19:45     ` Andreas Schwab
@ 2017-06-21 10:32       ` Jakub Jelinek
  2017-06-21 14:52         ` Jason Merrill
  0 siblings, 1 reply; 6+ messages in thread
From: Jakub Jelinek @ 2017-06-21 10:32 UTC (permalink / raw)
  To: Jason Merrill, Andreas Schwab; +Cc: gcc-patches List

On Tue, Jun 20, 2017 at 09:45:10PM +0200, Andreas Schwab wrote:
> On Jun 20 2017, Jason Merrill <jason@redhat.com> wrote:
> 
> > On Tue, Jun 20, 2017 at 5:40 AM, Andreas Schwab <schwab@suse.de> wrote:
> >> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 10)
> >> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 (test for excess errors)
> >> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14  (test for errors, line 10)
> >> FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++14 (test for excess errors)
> >
> > I'm not seeing this.  Can you give more detail?
> 
> http://gcc.gnu.org/ml/gcc-testresults/2017-06/msg02172.html

It doesn't fail on LP64 targets, but does fail on ILP32,
on x86_64-linux can be reproduced with e.g.
make check-g++ RUNTESTFLAGS='--target_board=unix\{-m32,-m64\} dg.exp=constexpr-cast.C'
The difference is that for LP64, 1 has different sizeof from void * and thus
you get one diagnostics, while on ILP32 int has the same precision as void
*.
So one gets:

/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C:10:22: error: reinterpret_cast from integer to pointer
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C:11:22: error: 'reinterpret_cast<void*>(1)' is not a constant expression
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C:24:26:   in constexpr expansion of 'f<int>()'
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C:24:27: error: value '4' of type 'int*' is not a constant expression
compiler exited with status 1
XFAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 bug c++/49171 (test for errors, line 8)
FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 10)
PASS: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 11)
PASS: g++.dg/cpp0x/constexpr-cast.C  -std=c++11  (test for errors, line 24)
FAIL: g++.dg/cpp0x/constexpr-cast.C  -std=c++11 (test for excess errors)
Excess errors:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C:10:22: error: reinterpret_cast from integer to pointer

The following patch fixes it by allowing that wording too on the line 10.
Is this ok for trunk or do you have some other preference?

2017-06-21  Jakub Jelinek  <jakub@redhat.com>

	* g++.dg/cpp0x/constexpr-cast.C: Adjust dg-error for ILP32.

--- gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C.jj	2016-08-08 21:42:30.825683528 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C	2017-06-21 12:30:19.425955047 +0200
@@ -7,7 +7,7 @@ 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 *r0 = reinterpret_cast<void*>(1);    // { dg-error "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" }
 
 template <class T>


	Jakub

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: C++ PATCH for c++/81073, constexpr and static var in statement-expression
  2017-06-21 10:32       ` Jakub Jelinek
@ 2017-06-21 14:52         ` Jason Merrill
  0 siblings, 0 replies; 6+ messages in thread
From: Jason Merrill @ 2017-06-21 14:52 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Andreas Schwab, gcc-patches List

On Wed, Jun 21, 2017 at 6:32 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> The following patch fixes it by allowing that wording too on the line 10.
> Is this ok for trunk or do you have some other preference?

OK, thanks.

Jason

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-06-21 14:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-19 17:42 C++ PATCH for c++/81073, constexpr and static var in statement-expression Jason Merrill
2017-06-20  9:40 ` Andreas Schwab
2017-06-20 18:50   ` Jason Merrill
2017-06-20 19:45     ` Andreas Schwab
2017-06-21 10:32       ` Jakub Jelinek
2017-06-21 14:52         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).