Commit 4b691b13 by Jason Merrill Committed by Jason Merrill

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.

From-SVN: r249382
parent c9f8853f
2017-06-19 Jason Merrill <jason@redhat.com>
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.
2017-06-19 Nathan Sidwell <nathan@acm.org> 2017-06-19 Nathan Sidwell <nathan@acm.org>
* pt.c (coerce_template_parms): Fix indentation. * pt.c (coerce_template_parms): Fix indentation.
......
...@@ -5212,10 +5212,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, ...@@ -5212,10 +5212,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
if (want_rval if (want_rval
&& !var_in_maybe_constexpr_fn (t) && !var_in_maybe_constexpr_fn (t)
&& !type_dependent_expression_p (t) && !type_dependent_expression_p (t)
&& !decl_constant_var_p (t) && !decl_maybe_constant_var_p (t)
&& (strict && (strict
|| !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t)) || !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)) && COMPLETE_TYPE_P (TREE_TYPE (t))
&& !is_really_empty_class (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, ...@@ -5540,21 +5541,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
{ {
if (flags & tf_error) if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
"%<static%> in %<constexpr%> function", tmp); "%<static%> in %<constexpr%> context", tmp);
return false; return false;
} }
else if (CP_DECL_THREAD_LOCAL_P (tmp)) else if (CP_DECL_THREAD_LOCAL_P (tmp))
{ {
if (flags & tf_error) if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared "
"%<thread_local%> in %<constexpr%> function", tmp); "%<thread_local%> in %<constexpr%> context", tmp);
return false; return false;
} }
else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp)) else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp))
{ {
if (flags & tf_error) if (flags & tf_error)
error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized " error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized "
"variable %qD in %<constexpr%> function", tmp); "variable %qD in %<constexpr%> context", tmp);
return false; return false;
} }
} }
......
...@@ -4145,10 +4145,19 @@ decl_maybe_constant_var_p (tree decl) ...@@ -4145,10 +4145,19 @@ decl_maybe_constant_var_p (tree decl)
/* A proxy isn't constant. */ /* A proxy isn't constant. */
return false; return false;
if (TREE_CODE (type) == REFERENCE_TYPE) 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 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 /* Complain that DECL uses a type with no linkage. In C++98 mode this is
......
...@@ -6585,10 +6585,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) ...@@ -6585,10 +6585,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
if (complain & tf_error) if (complain & tf_error)
{ {
int errs = errorcount, warns = warningcount + werrorcount; int errs = errorcount, warns = warningcount + werrorcount;
if (processing_template_decl if (!require_potential_constant_expression (expr))
&& !require_potential_constant_expression (expr)) expr = error_mark_node;
return NULL_TREE; else
expr = cxx_constant_value (expr); expr = cxx_constant_value (expr);
if (errorcount > errs || warningcount + werrorcount > warns) if (errorcount > errs || warningcount + werrorcount > warns)
inform (loc, "in template argument for type %qT ", type); inform (loc, "in template argument for type %qT ", type);
if (expr == error_mark_node) if (expr == error_mark_node)
......
...@@ -821,8 +821,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) ...@@ -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))) || (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl)))
{ {
/* Diagnose a non-constant initializer for constexpr. */ /* Diagnose a non-constant initializer for constexpr. */
if (processing_template_decl if (!require_potential_constant_expression (value))
&& !require_potential_constant_expression (value))
value = error_mark_node; value = error_mark_node;
else else
value = cxx_constant_value (value, decl); value = cxx_constant_value (value, decl);
......
...@@ -16,5 +16,5 @@ constexpr int i = ai.f(); ...@@ -16,5 +16,5 @@ constexpr int i = ai.f();
constexpr int b = A<B>().f(); // { dg-error "" } constexpr int b = A<B>().f(); // { dg-error "" }
template <class T> template <class T>
constexpr int f (T t) { return 42; } // { dg-error "parameter" } constexpr int f (T t) { return 42; }
constexpr int x = f(B()); // { dg-error "constexpr" } constexpr int x = f(B()); // { dg-error "non-literal" }
...@@ -10,5 +10,5 @@ struct T ...@@ -10,5 +10,5 @@ struct T
int main() int main()
{ {
constexpr T t = (T{} = T{}); constexpr T t = (T{} = T{}); // { dg-error "" "" { target c++11_only } }
} }
// 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(){}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment