Commit fe89d797 by Mark Mitchell Committed by Mark Mitchell

re PR c++/26559 (ICE with __builtin_constant_p in template argument)

2006-06-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26559
	* c-common.h (c_finish_omp_atomic): Adjust declaration.
	* c-omp.c (c_finish_omp_atomic): Return the expression to perform,
	rather than calling add_stmt on it.
	* c-parser.c (c_parser_omp_atomic): Adjust accordingly.

2006-06-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26559
	* pt.c (tsubst_expr): Use finish_omp_atomic.
	(value_dependent_expression_p): All CALL_EXPRs are dependent.
	* semantics.c (finish_omp_atomic): Rework to use standard
	paradigms for handling non-dependent expressions.

2006-06-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/26559
	* g++.dg/template/builtin1.C: New test.
	* g++.dg/gomp/tpl-atomic-2.C: Remove XFAIL.

From-SVN: r114665
parent 801522de
2006-06-14 Mark Mitchell <mark@codesourcery.com>
PR c++/26559
* c-common.h (c_finish_omp_atomic): Adjust declaration.
* c-omp.c (c_finish_omp_atomic): Return the expression to perform,
rather than calling add_stmt on it.
* c-parser.c (c_parser_omp_atomic): Adjust accordingly.
2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com> 2006-06-14 Andreas Krebbel <krebbel1@de.ibm.com>
PR middle-end/27959 PR middle-end/27959
......
...@@ -948,7 +948,7 @@ extern tree c_finish_omp_master (tree); ...@@ -948,7 +948,7 @@ extern tree c_finish_omp_master (tree);
extern tree c_finish_omp_critical (tree, tree); extern tree c_finish_omp_critical (tree, tree);
extern tree c_finish_omp_ordered (tree); extern tree c_finish_omp_ordered (tree);
extern void c_finish_omp_barrier (void); extern void c_finish_omp_barrier (void);
extern void c_finish_omp_atomic (enum tree_code, tree, tree); extern tree c_finish_omp_atomic (enum tree_code, tree, tree);
extern void c_finish_omp_flush (void); extern void c_finish_omp_flush (void);
extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree); extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree);
extern void c_split_parallel_clauses (tree, tree *, tree *); extern void c_split_parallel_clauses (tree, tree *, tree *);
......
...@@ -82,15 +82,18 @@ c_finish_omp_barrier (void) ...@@ -82,15 +82,18 @@ c_finish_omp_barrier (void)
/* Complete a #pragma omp atomic construct. The expression to be /* Complete a #pragma omp atomic construct. The expression to be
implemented atomically is LHS code= RHS. */ implemented atomically is LHS code= RHS. The value returned is
either error_mark_node (if the construct was erroneous) or an
OMP_ATOMIC node which should be added to the current statement tree
with add_stmt. */
void tree
c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
{ {
tree x, type, addr; tree x, type, addr;
if (lhs == error_mark_node || rhs == error_mark_node) if (lhs == error_mark_node || rhs == error_mark_node)
return; return error_mark_node;
/* ??? According to one reading of the OpenMP spec, complex type are /* ??? According to one reading of the OpenMP spec, complex type are
supported, but there are no atomic stores for any architecture. supported, but there are no atomic stores for any architecture.
...@@ -102,7 +105,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) ...@@ -102,7 +105,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
&& !SCALAR_FLOAT_TYPE_P (type)) && !SCALAR_FLOAT_TYPE_P (type))
{ {
error ("invalid expression type for %<#pragma omp atomic%>"); error ("invalid expression type for %<#pragma omp atomic%>");
return; return error_mark_node;
} }
/* ??? Validate that rhs does not overlap lhs. */ /* ??? Validate that rhs does not overlap lhs. */
...@@ -111,7 +114,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) ...@@ -111,7 +114,7 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
via indirection. */ via indirection. */
addr = build_unary_op (ADDR_EXPR, lhs, 0); addr = build_unary_op (ADDR_EXPR, lhs, 0);
if (addr == error_mark_node) if (addr == error_mark_node)
return; return error_mark_node;
addr = save_expr (addr); addr = save_expr (addr);
lhs = build_indirect_ref (addr, NULL); lhs = build_indirect_ref (addr, NULL);
...@@ -120,12 +123,12 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs) ...@@ -120,12 +123,12 @@ c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
to do this, and then take it apart again. */ to do this, and then take it apart again. */
x = build_modify_expr (lhs, code, rhs); x = build_modify_expr (lhs, code, rhs);
if (x == error_mark_node) if (x == error_mark_node)
return; return error_mark_node;
gcc_assert (TREE_CODE (x) == MODIFY_EXPR); gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
rhs = TREE_OPERAND (x, 1); rhs = TREE_OPERAND (x, 1);
/* Punt the actual generation of atomic operations to common code. */ /* Punt the actual generation of atomic operations to common code. */
add_stmt (build2 (OMP_ATOMIC, void_type_node, addr, rhs)); return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
} }
......
...@@ -7214,6 +7214,7 @@ static void ...@@ -7214,6 +7214,7 @@ static void
c_parser_omp_atomic (c_parser *parser) c_parser_omp_atomic (c_parser *parser)
{ {
tree lhs, rhs; tree lhs, rhs;
tree stmt;
enum tree_code code; enum tree_code code;
c_parser_skip_to_pragma_eol (parser); c_parser_skip_to_pragma_eol (parser);
...@@ -7280,7 +7281,9 @@ c_parser_omp_atomic (c_parser *parser) ...@@ -7280,7 +7281,9 @@ c_parser_omp_atomic (c_parser *parser)
rhs = c_parser_expression (parser).value; rhs = c_parser_expression (parser).value;
break; break;
} }
c_finish_omp_atomic (code, lhs, rhs); stmt = c_finish_omp_atomic (code, lhs, rhs);
if (stmt != error_mark_node)
add_stmt (stmt);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
} }
......
...@@ -4,6 +4,19 @@ ...@@ -4,6 +4,19 @@
2006-06-14 Mark Mitchell <mark@codesourcery.com> 2006-06-14 Mark Mitchell <mark@codesourcery.com>
* parser.c (cp_parser_unqualified_id): Use constructor_name_p to
check destructor names.
(cp_parser_nested_name_specifier_opt): Remove invalid
optimization.
* parser.c (cp_parser_declarator): Robustify.
PR c++/26559
* pt.c (tsubst_expr): Use finish_omp_atomic.
(value_dependent_expression_p): All CALL_EXPRs are dependent.
* semantics.c (finish_omp_atomic): Rework to use standard
paradigms for handling non-dependent expressions.
PR c++/28018 PR c++/28018
* typeck.c (build_modify_expr): Disallow array assignment. * typeck.c (build_modify_expr): Disallow array assignment.
......
...@@ -8546,10 +8546,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8546,10 +8546,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tree op0, op1; tree op0, op1;
op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl); op0 = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl);
op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl); op1 = tsubst_expr (TREE_OPERAND (t, 1), args, complain, in_decl);
if (OMP_ATOMIC_DEPENDENT_P (t)) finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
c_finish_omp_atomic (OMP_ATOMIC_CODE (t), op0, op1);
else
add_stmt (build2 (OMP_ATOMIC, void_type_node, op0, op1));
} }
break; break;
...@@ -12473,7 +12470,8 @@ dependent_scope_ref_p (tree expression, bool criterion (tree)) ...@@ -12473,7 +12470,8 @@ dependent_scope_ref_p (tree expression, bool criterion (tree))
} }
/* Returns TRUE if the EXPRESSION is value-dependent, in the sense of /* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
[temp.dep.constexpr] */ [temp.dep.constexpr]. EXPRESSION is already known to be a constant
expression. */
bool bool
value_dependent_expression_p (tree expression) value_dependent_expression_p (tree expression)
...@@ -12564,32 +12562,10 @@ value_dependent_expression_p (tree expression) ...@@ -12564,32 +12562,10 @@ value_dependent_expression_p (tree expression)
|| value_dependent_expression_p (TREE_OPERAND (expression, 1))); || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
case CALL_EXPR: case CALL_EXPR:
/* A CALL_EXPR is value-dependent if any argument is /* A CALL_EXPR may appear in a constant expression if it is a
value-dependent. Why do we have to handle CALL_EXPRs in this call to a builtin function, e.g., __builtin_constant_p. All
function at all? First, some function calls, those for which such calls are value-dependent. */
value_dependent_expression_p is true, man appear in constant return true;
expressions. Second, there appear to be bugs which result in
other CALL_EXPRs reaching this point. */
{
tree function = TREE_OPERAND (expression, 0);
tree args = TREE_OPERAND (expression, 1);
if (value_dependent_expression_p (function))
return true;
if (! args)
return false;
if (TREE_CODE (args) == TREE_LIST)
{
for (; args; args = TREE_CHAIN (args))
if (value_dependent_expression_p (TREE_VALUE (args)))
return true;
return false;
}
return value_dependent_expression_p (args);
}
default: default:
/* A constant expression is value-dependent if any subexpression is /* A constant expression is value-dependent if any subexpression is
......
2006-06-14 Mark Mitchell <mark@codesourcery.com> 2006-06-14 Mark Mitchell <mark@codesourcery.com>
PR c++/26559
* g++.dg/template/builtin1.C: New test.
* g++.dg/gomp/tpl-atomic-2.C: Remove XFAIL.
PR c++/28018 PR c++/28018
* g++.old-deja/g++.benjamin/14664-2.C: Expect error for array * g++.old-deja/g++.benjamin/14664-2.C: Expect error for array
assignment. assignment.
...@@ -17,11 +17,10 @@ template<typename T> void f2(float *f) ...@@ -17,11 +17,10 @@ template<typename T> void f2(float *f)
} }
// Here the rhs is dependent, but not type dependent. // Here the rhs is dependent, but not type dependent.
// ??? Fails. See the comment in finish_omp_atomic.
template<typename T> void f3(float *f) template<typename T> void f3(float *f)
{ {
#pragma omp atomic #pragma omp atomic
*f |= sizeof (T); // { dg-error "invalid|evaluation" "" { xfail *-*-* } } *f |= sizeof (T); // { dg-error "invalid|evaluation" }
} }
// And the converse, no error here because we're never fed a T. // And the converse, no error here because we're never fed a T.
......
// PR c++/26559
template<bool> struct cond;
template<int> struct S {
void f(int i) {
cond<__builtin_constant_p(i)>();
}
};
S<1> s;
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