From: Jason Merrill <jason@redhat.com>
To: gcc-patches List <gcc-patches@gcc.gnu.org>
Subject: C++ PATCH for c++/81073, constexpr and static var in statement-expression
Date: Mon, 19 Jun 2017 17:42:00 -0000 [thread overview]
Message-ID: <CADzB+2knUZB=xvAAYNSdDTxdR4tB5n7RrJ+dHzwwsvnU9-7kXA@mail.gmail.com> (raw)
[-- 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(){}
next reply other threads:[~2017-06-19 17:42 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-19 17:42 Jason Merrill [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CADzB+2knUZB=xvAAYNSdDTxdR4tB5n7RrJ+dHzwwsvnU9-7kXA@mail.gmail.com' \
--to=jason@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).