+2017-01-07 Jason Merrill <jason@redhat.com>
+
+ PR c++/78948 - instantiation from discarded statement
+ * parser.h (struct cp_parser): Remove in_discarded_stmt field.
+ * cp-tree.h (in_discarded_stmt): Declare it.
+ (struct saved_scope): Add discarded_stmt bitfield.
+ (in_discarded_stmt): New macro.
+ * decl2.c (mark_used): Check it.
+ * parser.c (cp_parser_selection_statement): Adjust.
+ (cp_parser_jump_statement): Adjust.
+
2017-01-05 Jakub Jelinek <jakub@redhat.com>
PR c++/78931
BOOL_BITFIELD x_processing_explicit_instantiation : 1;
BOOL_BITFIELD need_pop_function_context : 1;
+/* Nonzero if we are parsing the discarded statement of a constexpr
+ if-statement. */
+ BOOL_BITFIELD discarded_stmt : 1;
+
int unevaluated_operand;
int inhibit_evaluation_warnings;
int noexcept_operand;
#define processing_specialization scope_chain->x_processing_specialization
#define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation
+#define in_discarded_stmt scope_chain->discarded_stmt
+
/* RAII sentinel to handle clearing processing_template_decl and restoring
it when done. */
}
/* If we don't need a value, then we don't need to synthesize DECL. */
- if (cp_unevaluated_operand != 0)
+ if (cp_unevaluated_operand || in_discarded_stmt)
return true;
DECL_ODR_USED (decl) = 1;
/* Outside a template, the non-selected branch of a constexpr
if is a 'discarded statement', i.e. unevaluated. */
- bool was_discarded = parser->in_discarded_stmt;
+ bool was_discarded = in_discarded_stmt;
bool discard_then = (cx && !processing_template_decl
&& integer_zerop (condition));
if (discard_then)
{
- parser->in_discarded_stmt = true;
+ in_discarded_stmt = true;
++c_inhibit_evaluation_warnings;
}
if (discard_then)
{
THEN_CLAUSE (statement) = NULL_TREE;
- parser->in_discarded_stmt = was_discarded;
+ in_discarded_stmt = was_discarded;
--c_inhibit_evaluation_warnings;
}
&& integer_nonzerop (condition));
if (discard_else)
{
- parser->in_discarded_stmt = true;
+ in_discarded_stmt = true;
++c_inhibit_evaluation_warnings;
}
if (discard_else)
{
ELSE_CLAUSE (statement) = NULL_TREE;
- parser->in_discarded_stmt = was_discarded;
+ in_discarded_stmt = was_discarded;
--c_inhibit_evaluation_warnings;
}
}
expression. */
expr = NULL_TREE;
/* Build the return-statement. */
- if (current_function_auto_return_pattern && parser->in_discarded_stmt)
+ if (current_function_auto_return_pattern && in_discarded_stmt)
/* Don't deduce from a discarded return statement. */;
else
statement = finish_return_stmt (expr);
a local class. */
bool in_function_body;
- /* TRUE if we are parsing a C++17 discarded statement (the non-taken branch
- of an if constexpr). */
- bool in_discarded_stmt;
-
/* Nonzero if we're processing a __transaction_atomic or
__transaction_relaxed statement. */
unsigned char in_transaction;
--- /dev/null
+// PR c++/79848
+// { dg-options -std=c++1z }
+
+template <int T>
+void sizeof_mismatch()
+{
+ static_assert(T == 0, "sizeof mismatch");
+}
+
+int main()
+{
+ if constexpr(sizeof(long long) == sizeof(char*))
+ ;
+ else
+ sizeof_mismatch<sizeof(long long)>();
+}
--- /dev/null
+// Test that discarded statements differ from unevaluated operands in some
+// ways.
+// { dg-options -std=c++1z }
+
+struct A { int i; };
+
+int main()
+{
+ if constexpr(true)
+ ;
+ else
+ {
+ []{}();
+ A::i; // { dg-error "non-static" }
+ }
+}