+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>
* pt.c (coerce_template_parms): Fix indentation.
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)))
{
{
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;
}
}
/* 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
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)
|| (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);
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" }
int main()
{
- constexpr T t = (T{} = T{});
+ constexpr T t = (T{} = T{}); // { dg-error "" "" { target c++11_only } }
}
--- /dev/null
+// 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(){}