building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
static tree maybe_convert_cond (tree);
static tree simplify_aggr_init_exprs_r (tree *, int *, void *);
-static void emit_associated_thunks (tree);
static tree finalize_nrv_r (tree *, int *, void *);
if (TREE_CODE (cond) == DECL_EXPR)
expr = cond;
- check_for_bare_parameter_packs (expr);
+ if (check_for_bare_parameter_packs (&expr))
+ *cond_p = error_mark_node;
}
*cond_p = expr;
}
else if (!type_dependent_expression_p (expr))
convert_to_void (build_non_dependent_expr (expr), "statement");
- check_for_bare_parameter_packs (expr);
+ if (check_for_bare_parameter_packs (&expr))
+ expr = error_mark_node;
/* Simplification of inner statement expressions, compound exprs,
etc can result in us already having an EXPR_STMT. */
else if (!type_dependent_expression_p (expr))
convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
expr = maybe_cleanup_point_expr_void (expr);
- check_for_bare_parameter_packs (expr);
+ if (check_for_bare_parameter_packs (&expr))
+ expr = error_mark_node;
FOR_EXPR (for_stmt) = expr;
}
cond = index;
}
}
+ if (check_for_bare_parameter_packs (&cond))
+ cond = error_mark_node;
finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
SWITCH_STMT_TYPE (switch_stmt) = orig_type;
add_stmt (switch_stmt);
push_switch (switch_stmt);
SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
- check_for_bare_parameter_packs (cond);
}
/* Finish the body of a switch-statement, which may be given by
any parameter packs in the TREE_VALUE have already been
bound as part of the TREE_PURPOSE. See
make_pack_expansion for more information. */
- if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
- check_for_bare_parameter_packs (TREE_VALUE (mem));
+ if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION
+ && check_for_bare_parameter_packs (&TREE_VALUE (mem)))
+ TREE_VALUE (mem) = error_mark_node;
}
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
{
result = build_nt_call_list (fn, args);
KOENIG_LOOKUP_P (result) = koenig_p;
+ if (cfun)
+ {
+ do
+ {
+ tree fndecl = OVL_CURRENT (fn);
+ if (TREE_CODE (fndecl) != FUNCTION_DECL
+ || !TREE_THIS_VOLATILE (fndecl))
+ break;
+ fn = OVL_NEXT (fn);
+ }
+ while (fn);
+ if (!fn)
+ current_function_returns_abnormally = 1;
+ }
return result;
}
if (!BASELINK_P (fn)
tree
finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
{
- if (destructor == error_mark_node)
+ if (object == error_mark_node || destructor == error_mark_node)
return error_mark_node;
gcc_assert (TYPE_P (destructor));
gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
+ check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl),
+ /*is_primary=*/true, /*is_partial=*/false,
+ /*is_friend=*/0);
+
return finish_template_type_parm (aggr, tmpl);
}
DECL_CONTEXT (decl) = current_class_type;
/* Check for bare parameter packs in the member variable declaration. */
- if (TREE_CODE (decl) == FIELD_DECL
- && !check_for_bare_parameter_packs (TREE_TYPE (decl)))
- TREE_TYPE (decl) = error_mark_node;
+ if (TREE_CODE (decl) == FIELD_DECL)
+ {
+ if (check_for_bare_parameter_packs (&TREE_TYPE (decl)))
+ TREE_TYPE (decl) = error_mark_node;
+ if (check_for_bare_parameter_packs (&DECL_ATTRIBUTES (decl)))
+ DECL_ATTRIBUTES (decl) = NULL_TREE;
+ }
/* [dcl.link]
else
{
if (DECL_P (decl) && DECL_NONLOCAL (decl)
- && DECL_CLASS_SCOPE_P (decl)
- && context_for_name_lookup (decl) != current_class_type)
+ && DECL_CLASS_SCOPE_P (decl))
{
- tree path;
-
- path = currently_open_derived_class (DECL_CONTEXT (decl));
- perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
+ tree context = context_for_name_lookup (decl);
+ if (context != current_class_type)
+ {
+ tree path = currently_open_derived_class (context);
+ perform_or_defer_access_check (TYPE_BINFO (path),
+ decl, decl);
+ }
}
decl = convert_from_reference (decl);
/* Emit all thunks to FN that should be emitted when FN is emitted. */
-static void
+void
emit_associated_thunks (tree fn)
{
/* When we use vcall offsets, we emit thunks with the virtual
/* Generate RTL for FN. */
void
-expand_body (tree fn)
-{
- /* Emit any thunks that should be emitted at the same time as FN. */
- emit_associated_thunks (fn);
-
- /* This function is only called from cgraph, or recursively from
- emit_associated_thunks. In neither case should we be currently
- generating trees for a function. */
- gcc_assert (function_depth == 0);
-
- c_expand_body (fn);
-}
-
-/* Generate RTL for FN. */
-
-void
expand_or_defer_fn (tree fn)
{
/* When the parser calls us after finishing the body of a template
t = OMP_CLAUSE_NUM_THREADS_EXPR (c);
if (t == error_mark_node)
remove = true;
- else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- && !type_dependent_expression_p (t))
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
error ("num_threads expression must be integral");
remove = true;
;
else if (t == error_mark_node)
remove = true;
- else if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- && !type_dependent_expression_p (t))
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
error ("schedule chunk size expression must be integral");
remove = true;
finish_omp_for (location_t locus, tree decl, tree init, tree cond,
tree incr, tree body, tree pre_body)
{
- tree omp_for;
+ tree omp_for = NULL;
if (decl == NULL)
{
pre_body = NULL;
}
- init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
+ if (!processing_template_decl)
+ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
init = build_modify_expr (decl, NOP_EXPR, init);
if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond))
{
int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0;
tree t = TREE_OPERAND (cond, n);
- TREE_OPERAND (cond, n)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ if (!processing_template_decl)
+ TREE_OPERAND (cond, n)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
}
- omp_for = c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
+ if (decl != error_mark_node && init != error_mark_node)
+ omp_for = c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
if (omp_for != NULL
&& TREE_CODE (OMP_FOR_INCR (omp_for)) == MODIFY_EXPR
&& TREE_SIDE_EFFECTS (TREE_OPERAND (OMP_FOR_INCR (omp_for), 1))
tree t = TREE_OPERAND (OMP_FOR_INCR (omp_for), 1);
int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
- TREE_OPERAND (t, n)
- = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
- TREE_OPERAND (t, n));
+ if (!processing_template_decl)
+ TREE_OPERAND (t, n)
+ = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
+ TREE_OPERAND (t, n));
}
return omp_for;
}
void
finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
{
+ tree orig_lhs;
+ tree orig_rhs;
+ bool dependent_p;
tree stmt;
- if (processing_template_decl
- && (type_dependent_expression_p (lhs)
- || type_dependent_expression_p (rhs)))
- stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
- build2 (code, void_type_node, lhs, rhs));
- else
+ orig_lhs = lhs;
+ orig_rhs = rhs;
+ dependent_p = false;
+ stmt = NULL_TREE;
+
+ /* Even in a template, we can detect invalid uses of the atomic
+ pragma if neither LHS nor RHS is type-dependent. */
+ if (processing_template_decl)
{
- /* Even in a template, we can detect invalid uses of the atomic
- pragma if neither LHS nor RHS is type-dependent. */
- if (processing_template_decl)
+ dependent_p = (type_dependent_expression_p (lhs)
+ || type_dependent_expression_p (rhs));
+ if (!dependent_p)
{
lhs = build_non_dependent_expr (lhs);
rhs = build_non_dependent_expr (rhs);
}
-
+ }
+ if (!dependent_p)
+ {
stmt = c_finish_omp_atomic (code, lhs, rhs);
+ if (stmt == error_mark_node)
+ return;
}
-
- if (stmt != error_mark_node)
- add_stmt (stmt);
+ if (processing_template_decl)
+ stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node,
+ build2 (code, void_type_node, orig_lhs, orig_rhs));
+ add_stmt (stmt);
}
void
tree orig_expr = expr;
tree type;
+ if (!expr || error_operand_p (expr))
+ return error_mark_node;
+
+ if (TYPE_P (expr)
+ || TREE_CODE (expr) == TYPE_DECL
+ || (TREE_CODE (expr) == BIT_NOT_EXPR
+ && TYPE_P (TREE_OPERAND (expr, 0))))
+ {
+ error ("argument to decltype must be an expression");
+ return error_mark_node;
+ }
+
if (type_dependent_expression_p (expr))
{
type = make_aggr_type (DECLTYPE_TYPE);
break;
default:
- gcc_assert (TYPE_P (expr) || DECL_P (expr));
+ gcc_assert (TYPE_P (expr) || DECL_P (expr)
+ || TREE_CODE (expr) == SCOPE_REF);
error ("argument to decltype must be an expression");
return error_mark_node;
}
{
tree fndecl;
+ /* Expressions of reference type are sometimes wrapped in
+ INDIRECT_REFs. INDIRECT_REFs are just internal compiler
+ representation, not part of the language, so we have to look
+ through them. */
+ if (TREE_CODE (expr) == INDIRECT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
+ == REFERENCE_TYPE)
+ expr = TREE_OPERAND (expr, 0);
+
if (TREE_CODE (expr) == CALL_EXPR
&& (fndecl = get_callee_fndecl (expr))
&& (fndecl != error_mark_node))
decltype(e) is defined as T&, otherwise decltype(e) is
defined as T. */
type = TREE_TYPE (expr);
- if (expr == current_class_ptr)
+ if (type == error_mark_node)
+ return error_mark_node;
+ else if (expr == current_class_ptr)
/* If the expression is just "this", we want the
cv-unqualified pointer for the "this" type. */
type = TYPE_MAIN_VARIANT (type);