building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-2019 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
#include "attribs.h"
#include "gomp-constants.h"
#include "predict.h"
+#include "memmodel.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
/* When we expand a statement-tree, we must know whether or not the
statements are full-expressions. We record that fact here. */
- STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
+ if (STATEMENT_CODE_P (TREE_CODE (t)))
+ STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
}
if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
return NULL_TREE;
/* Wait until we instantiate templates before doing conversion. */
- if (processing_template_decl)
+ if (type_dependent_expression_p (cond))
return cond;
- if (warn_sequence_point)
+ if (warn_sequence_point && !processing_template_decl)
verify_sequence_points (cond);
/* Do the conversion. */
if (TREE_CODE (cond) == MODIFY_EXPR
&& !TREE_NO_WARNING (cond)
- && warn_parentheses)
- {
- warning_at (EXPR_LOC_OR_LOC (cond, input_location), OPT_Wparentheses,
- "suggest parentheses around assignment used as truth value");
- TREE_NO_WARNING (cond) = 1;
- }
+ && warn_parentheses
+ && warning_at (cp_expr_loc_or_loc (cond, input_location),
+ OPT_Wparentheses, "suggest parentheses around "
+ "assignment used as truth value"))
+ TREE_NO_WARNING (cond) = 1;
return condition_conversion (cond);
}
: &FOR_SCOPE (for_stmt));
tree scope = *scope_ptr;
*scope_ptr = NULL;
+
+ /* During parsing of the body, range for uses "__for_{range,begin,end} "
+ decl names to make those unaccessible by code in the body.
+ Change it to ones with underscore instead of space, so that it can
+ be inspected in the debugger. */
+ tree range_for_decl[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
+ gcc_assert (CPTI_FOR_BEGIN__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 1
+ && CPTI_FOR_END__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 2
+ && CPTI_FOR_RANGE_IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 3
+ && CPTI_FOR_BEGIN_IDENTIFIER == CPTI_FOR_BEGIN__IDENTIFIER + 3
+ && CPTI_FOR_END_IDENTIFIER == CPTI_FOR_END__IDENTIFIER + 3);
+ for (int i = 0; i < 3; i++)
+ {
+ tree id = cp_global_trees[CPTI_FOR_RANGE__IDENTIFIER + i];
+ if (IDENTIFIER_BINDING (id)
+ && IDENTIFIER_BINDING (id)->scope == current_binding_level)
+ {
+ range_for_decl[i] = IDENTIFIER_BINDING (id)->value;
+ gcc_assert (VAR_P (range_for_decl[i])
+ && DECL_ARTIFICIAL (range_for_decl[i]));
+ }
+ }
+
add_stmt (do_poplevel (scope));
+
+ for (int i = 0; i < 3; i++)
+ if (range_for_decl[i])
+ DECL_NAME (range_for_decl[i])
+ = cp_global_trees[CPTI_FOR_RANGE_IDENTIFIER + i];
}
/* Begin a range-for-statement. Returns a new RANGE_FOR_STMT.
{
begin_maybe_infinite_loop (boolean_false_node);
- tree r = build_stmt (input_location, RANGE_FOR_STMT,
- NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
+ tree r = build_stmt (input_location, RANGE_FOR_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
if (scope == NULL_TREE)
{
scope = begin_for_scope (&init);
}
- /* RANGE_FOR_STMTs do not use nor save the init tree, so we
- pop it now. */
- if (init)
- pop_stmt_list (init);
+ /* Since C++20, RANGE_FOR_STMTs can use the init tree, so save it. */
+ RANGE_FOR_INIT_STMT (r) = init;
RANGE_FOR_SCOPE (r) = scope;
return r;
}
/* Finish the head of a range-based for statement, which may
- be given by RANGE_FOR_STMT. DECL must be the declaration
+ be given by RANGE_FOR_STMT. DECL must be the declaration
and EXPR must be the loop expression. */
void
finish_range_for_decl (tree range_for_stmt, tree decl, tree expr)
{
+ if (processing_template_decl)
+ RANGE_FOR_INIT_STMT (range_for_stmt)
+ = pop_stmt_list (RANGE_FOR_INIT_STMT (range_for_stmt));
RANGE_FOR_DECL (range_for_stmt) = decl;
RANGE_FOR_EXPR (range_for_stmt) = expr;
add_stmt (range_for_stmt);
/* Finish an asm-statement, whose components are a STRING, some
OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some
LABELS. Also note whether the asm-statement should be
- considered volatile. */
+ considered volatile, and whether it is asm inline. */
tree
finish_asm_stmt (int volatile_p, tree string, tree output_operands,
- tree input_operands, tree clobbers, tree labels)
+ tree input_operands, tree clobbers, tree labels, bool inline_p)
{
tree r;
tree t;
effectively const. */
|| (CLASS_TYPE_P (TREE_TYPE (operand))
&& C_TYPE_FIELDS_READONLY (TREE_TYPE (operand)))))
- cxx_readonly_error (operand, lv_asm);
+ cxx_readonly_error (input_location, operand, lv_asm);
tree *op = &operand;
while (TREE_CODE (*op) == COMPOUND_EXPR)
output_operands, input_operands,
clobbers, labels);
ASM_VOLATILE_P (r) = volatile_p || noutputs == 0;
+ ASM_INLINE_P (r) = inline_p;
r = maybe_cleanup_point_expr_void (r);
return add_stmt (r);
}
if (cp_unevaluated_operand)
return expr;
- if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
+ if (!DECL_P (tree_strip_any_location_wrapper (expr))
+ && TREE_CODE (expr) != COMPONENT_REF
&& TREE_CODE (expr) != SCOPE_REF)
return expr;
REF_PARENTHESIZED_P (expr) = true;
else if (processing_template_decl)
expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
- else if (VAR_P (expr) && DECL_HARD_REGISTER (expr))
- /* We can't bind a hard register variable to a reference. */;
else
{
- cp_lvalue_kind kind = lvalue_kind (expr);
- if ((kind & ~clk_class) != clk_none)
- {
- tree type = unlowered_expr_type (expr);
- bool rval = !!(kind & clk_rvalueref);
- type = cp_build_reference_type (type, rval);
- /* This inhibits warnings in, eg, cxx_mark_addressable
- (c++/60955). */
- warning_sentinel s (extra_warnings);
- expr = build_static_cast (type, expr, tf_error);
- if (expr != error_mark_node)
- REF_PARENTHESIZED_P (expr) = true;
- }
+ expr = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+ REF_PARENTHESIZED_P (expr) = true;
}
return expr;
}
else if (TREE_CODE (t) == PAREN_EXPR)
t = TREE_OPERAND (t, 0);
+ else if (TREE_CODE (t) == VIEW_CONVERT_EXPR
+ && REF_PARENTHESIZED_P (t))
+ t = TREE_OPERAND (t, 0);
return t;
}
enclosed in parentheses. */
PTRMEM_OK_P (expr) = 0;
- if (TREE_CODE (expr) == STRING_CST)
- PAREN_STRING_LITERAL_P (expr) = 1;
+ tree stripped_expr = tree_strip_any_location_wrapper (expr);
+ if (TREE_CODE (stripped_expr) == STRING_CST)
+ PAREN_STRING_LITERAL_P (stripped_expr) = 1;
expr = cp_expr (force_paren_expr (expr), expr.get_location ());
{
tree scope = qualifying_scope;
if (scope == NULL_TREE)
- scope = context_for_name_lookup (decl);
+ {
+ scope = context_for_name_lookup (decl);
+ if (!TYPE_P (scope))
+ {
+ /* Can happen during error recovery (c++/85014). */
+ gcc_assert (seen_error ());
+ return error_mark_node;
+ }
+ }
object = maybe_dummy_object (scope, NULL);
}
if (current_class_ptr)
TREE_USED (current_class_ptr) = 1;
- if (processing_template_decl && !qualifying_scope)
+ if (processing_template_decl)
{
tree type = TREE_TYPE (decl);
type = cp_build_qualified_type (type, quals);
}
- ret = (convert_from_reference
- (build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
+ if (qualifying_scope)
+ /* Wrap this in a SCOPE_REF for now. */
+ ret = build_qualified_name (type, qualifying_scope, decl,
+ /*template_p=*/false);
+ else
+ ret = (convert_from_reference
+ (build_min (COMPONENT_REF, type, object, decl, NULL_TREE)));
}
/* If PROCESSING_TEMPLATE_DECL is nonzero here, then
- QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF
- for now. */
- else if (processing_template_decl)
- ret = build_qualified_name (TREE_TYPE (decl),
- qualifying_scope,
- decl,
- /*template_p=*/false);
+ QUALIFYING_SCOPE is also non-null. */
else
{
tree access_type = TREE_TYPE (object);
{
/* See if any of the functions are non-static members. */
/* If so, the expression may be relative to 'this'. */
- if (!shared_member_p (expr)
+ if ((type_dependent_expression_p (expr)
+ || !shared_member_p (expr))
&& current_class_ptr
&& DERIVED_FROM_P (qualifying_class,
current_nonlambda_class_type ()))
expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
complain);
}
+ else if (!template_p
+ && TREE_CODE (expr) == TEMPLATE_DECL
+ && !DECL_FUNCTION_TEMPLATE_P (expr))
+ {
+ if (complain & tf_error)
+ error ("%qE missing template arguments", expr);
+ return error_mark_node;
+ }
else
{
/* In a template, return a SCOPE_REF for most qualified-ids
non-type template argument handling. */
if (processing_template_decl
&& (!currently_open_class (qualifying_class)
+ || TREE_CODE (expr) == IDENTIFIER_NODE
+ || TREE_CODE (expr) == TEMPLATE_ID_EXPR
|| TREE_CODE (expr) == BIT_NOT_EXPR))
expr = build_qualified_name (TREE_TYPE (expr),
qualifying_class, expr,
template_p);
+ else if (tree wrap = maybe_get_tls_wrapper_call (expr))
+ expr = wrap;
expr = convert_from_reference (expr);
}
return false;
}
-/* Perform Koenig lookup. FN is the postfix-expression representing
+/* Perform Koenig lookup. FN_EXPR is the postfix-expression representing
the function (or functions) to call; ARGS are the arguments to the
call. Returns the functions to be considered by overload resolution. */
cp_expr
-perform_koenig_lookup (cp_expr fn, vec<tree, va_gc> *args,
+perform_koenig_lookup (cp_expr fn_expr, vec<tree, va_gc> *args,
tsubst_flags_t complain)
{
tree identifier = NULL_TREE;
tree functions = NULL_TREE;
tree tmpl_args = NULL_TREE;
bool template_id = false;
- location_t loc = fn.get_location ();
+ location_t loc = fn_expr.get_location ();
+ tree fn = fn_expr.get_value ();
+
+ STRIP_ANY_LOCATION_WRAPPER (fn);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
if (fn && template_id && fn != error_mark_node)
fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args);
- return fn;
+ return cp_expr (fn, loc);
}
/* Generate an expression for `FN (ARGS)'. This may change the
{
tree result;
tree orig_fn;
- vec<tree, va_gc> *orig_args = NULL;
+ vec<tree, va_gc> *orig_args = *args;
if (fn == error_mark_node)
return error_mark_node;
it so that we can tell this is a call to a known function. */
fn = maybe_undo_parenthesized_ref (fn);
+ STRIP_ANY_LOCATION_WRAPPER (fn);
+
orig_fn = fn;
if (processing_template_decl)
|| any_type_dependent_arguments_p (*args))
{
result = build_min_nt_call_vec (orig_fn, *args);
- SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
+ SET_EXPR_LOCATION (result, cp_expr_loc_or_loc (fn, input_location));
KOENIG_LOOKUP_P (result) = koenig_p;
if (is_overloaded_fn (fn))
- {
- fn = get_fns (fn);
- lookup_keep (fn, true);
- }
+ fn = get_fns (fn);
if (cfun)
{
sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
}
+ if ((complain & tf_warning)
+ && TREE_CODE (fn) == FUNCTION_DECL
+ && fndecl_built_in_p (fn, BUILT_IN_MEMSET)
+ && vec_safe_length (*args) == 3
+ && !any_type_dependent_arguments_p (*args))
+ {
+ tree arg0 = (*orig_args)[0];
+ tree arg1 = (*orig_args)[1];
+ tree arg2 = (*orig_args)[2];
+ int literal_mask = ((literal_integer_zerop (arg1) << 1)
+ | (literal_integer_zerop (arg2) << 2));
+ warn_for_memset (input_location, arg0, arg2, literal_mask);
+ }
+
/* A call to a namespace-scope function. */
result = build_new_function_call (fn, args, complain);
}
result = convert_from_reference (result);
}
- /* Free or retain OVERLOADs from lookup. */
- if (is_overloaded_fn (orig_fn))
- lookup_keep (get_fns (orig_fn), processing_template_decl);
-
return result;
}
/* TODO: build_x_unary_op doesn't always honor the location. */
result.set_location (combined_loc);
- tree result_ovl, expr_ovl;
+ if (result == error_mark_node)
+ return result;
if (!(complain & tf_warning))
return result;
- result_ovl = result;
- expr_ovl = expr;
+ tree result_ovl = result;
+ tree expr_ovl = expr;
if (!processing_template_decl)
expr_ovl = cp_fully_fold (expr_ovl);
return error_mark_node;
}
+ /* Used to hold a copy of the compound literal in a template. */
+ tree orig_cl = NULL_TREE;
+
if (processing_template_decl)
{
- TREE_TYPE (compound_literal) = type;
+ const bool dependent_p
+ = (instantiation_dependent_expression_p (compound_literal)
+ || dependent_type_p (type));
+ if (dependent_p)
+ /* We're about to return, no need to copy. */
+ orig_cl = compound_literal;
+ else
+ /* We're going to need a copy. */
+ orig_cl = unshare_constructor (compound_literal);
+ TREE_TYPE (orig_cl) = type;
/* Mark the expression as a compound literal. */
- TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
+ TREE_HAS_CONSTRUCTOR (orig_cl) = 1;
+ /* And as instantiation-dependent. */
+ CONSTRUCTOR_IS_DEPENDENT (orig_cl) = dependent_p;
if (fcl_context == fcl_c99)
- CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
- return compound_literal;
+ CONSTRUCTOR_C99_COMPOUND_LITERAL (orig_cl) = 1;
+ /* If the compound literal is dependent, we're done for now. */
+ if (dependent_p)
+ return orig_cl;
+ /* Otherwise, do go on to e.g. check narrowing. */
}
type = complete_type (type);
return error_mark_node;
compound_literal = reshape_init (type, compound_literal, complain);
if (SCALAR_TYPE_P (type)
- && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)
- && !check_narrowing (type, compound_literal, complain))
- return error_mark_node;
+ && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal))
+ {
+ tree t = instantiate_non_dependent_expr_sfinae (compound_literal,
+ complain);
+ if (!check_narrowing (type, t, complain))
+ return error_mark_node;
+ }
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
if (type == error_mark_node)
return error_mark_node;
}
- compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL,
+ compound_literal = digest_init_flags (type, compound_literal,
+ LOOKUP_NORMAL | LOOKUP_NO_NARROWING,
complain);
+ if (compound_literal == error_mark_node)
+ return error_mark_node;
+
+ /* If we're in a template, return the original compound literal. */
+ if (orig_cl)
+ {
+ if (!VECTOR_TYPE_P (type))
+ return get_target_expr_sfinae (orig_cl, complain);
+ else
+ return orig_cl;
+ }
+
if (TREE_CODE (compound_literal) == CONSTRUCTOR)
{
TREE_HAS_CONSTRUCTOR (compound_literal) = true;
if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t)))
return error_mark_node;
- if (processing_template_parmlist)
+ if (processing_template_parmlist && !LAMBDA_TYPE_P (t))
{
error ("definition of %q#T inside template parameter list", t);
return error_mark_node;
= decl_function_context (containing_function);
}
- /* In a lambda within a template, wait until instantiation
- time to implicitly capture. */
+ /* In a lambda within a template, wait until instantiation time to implicitly
+ capture a parameter pack. We want to wait because we don't know if we're
+ capturing the whole pack or a single element, and it's OK to wait because
+ find_parameter_packs_r walks into the lambda body. */
if (context == containing_function
- && DECL_TEMPLATE_INFO (containing_function)
- && uses_template_parms (DECL_TI_ARGS (containing_function)))
+ && DECL_PACK_P (decl))
return decl;
if (lambda_expr && VAR_P (decl)
the use of "this" explicit.
Upon return, *IDK will be filled in appropriately. */
-cp_expr
-finish_id_expression (tree id_expression,
- tree decl,
- tree scope,
- cp_id_kind *idk,
- bool integral_constant_expression_p,
- bool allow_non_integral_constant_expression_p,
- bool *non_integral_constant_expression_p,
- bool template_p,
- bool done,
- bool address_p,
- bool template_arg_p,
- const char **error_msg,
- location_t location)
+static cp_expr
+finish_id_expression_1 (tree id_expression,
+ tree decl,
+ tree scope,
+ cp_id_kind *idk,
+ bool integral_constant_expression_p,
+ bool allow_non_integral_constant_expression_p,
+ bool *non_integral_constant_expression_p,
+ bool template_p,
+ bool done,
+ bool address_p,
+ bool template_arg_p,
+ const char **error_msg,
+ location_t location)
{
decl = strip_using_decl (decl);
*idk = CP_ID_KIND_NONE;
if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX)
decl = TEMPLATE_PARM_DECL (decl);
- r = convert_from_reference (DECL_INITIAL (decl));
-
+ r = DECL_INITIAL (decl);
+ if (CLASS_TYPE_P (TREE_TYPE (r)) && !CP_TYPE_CONST_P (TREE_TYPE (r)))
+ {
+ /* If the entity is a template parameter object for a template
+ parameter of type T, the type of the expression is const T. */
+ tree ctype = TREE_TYPE (r);
+ ctype = cp_build_qualified_type (ctype, (cp_type_quals (ctype)
+ | TYPE_QUAL_CONST));
+ r = build1 (VIEW_CONVERT_EXPR, ctype, r);
+ }
+ r = convert_from_reference (r);
if (integral_constant_expression_p
&& !dependent_type_p (TREE_TYPE (decl))
&& !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r))))
*non_integral_constant_expression_p = true;
}
- tree wrap;
- if (VAR_P (decl)
- && !cp_unevaluated_operand
- && !processing_template_decl
- && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
- && CP_DECL_THREAD_LOCAL_P (decl)
- && (wrap = get_tls_wrapper_fn (decl)))
- {
- /* Replace an evaluated use of the thread_local variable with
- a call to its wrapper. */
- decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
- }
+ if (tree wrap = maybe_get_tls_wrapper_call (decl))
+ /* Replace an evaluated use of the thread_local variable with
+ a call to its wrapper. */
+ decl = wrap;
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& !dependent_p
&& variable_template_p (TREE_OPERAND (decl, 0)))
return error_mark_node;
if (!template_arg_p
- && TREE_CODE (first_fn) == FUNCTION_DECL
- && DECL_FUNCTION_MEMBER_P (first_fn)
- && !shared_member_p (decl))
+ && (TREE_CODE (first_fn) == USING_DECL
+ || (TREE_CODE (first_fn) == FUNCTION_DECL
+ && DECL_FUNCTION_MEMBER_P (first_fn)
+ && !shared_member_p (decl))))
{
/* A set of member functions. */
decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
return cp_expr (decl, location);
}
+/* As per finish_id_expression_1, but adding a wrapper node
+ around the result if needed to express LOCATION. */
+
+cp_expr
+finish_id_expression (tree id_expression,
+ tree decl,
+ tree scope,
+ cp_id_kind *idk,
+ bool integral_constant_expression_p,
+ bool allow_non_integral_constant_expression_p,
+ bool *non_integral_constant_expression_p,
+ bool template_p,
+ bool done,
+ bool address_p,
+ bool template_arg_p,
+ const char **error_msg,
+ location_t location)
+{
+ cp_expr result
+ = finish_id_expression_1 (id_expression, decl, scope, idk,
+ integral_constant_expression_p,
+ allow_non_integral_constant_expression_p,
+ non_integral_constant_expression_p,
+ template_p, done, address_p, template_arg_p,
+ error_msg, location);
+ return result.maybe_add_location_wrapper ();
+}
+
/* Implement the __typeof keyword: Return the type of EXPR, suitable for
use as a type-specifier. */
return expr;
}
+ if (expr == error_mark_node)
+ return error_mark_node;
+
if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
{
error ("cannot apply %<offsetof%> to destructor %<~%T%>",
if (DECL_INTERFACE_KNOWN (fn))
/* We've already made a decision as to how this function will
be handled. */;
- else if (!at_eof)
+ else if (!at_eof || DECL_OMP_DECLARE_REDUCTION_P (fn))
tentative_decl_linkage (fn);
else
import_export_decl (fn);
be emitted; there may be callers in other DLLs. */
if (DECL_DECLARED_INLINE_P (fn)
&& !DECL_REALLY_EXTERN (fn)
+ && !DECL_OMP_DECLARE_REDUCTION_P (fn)
&& (flag_keep_inline_functions
|| (flag_keep_inline_dllexport
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
/* There's no reason to do any of the work here if we're only doing
semantic analysis; this code just generates RTL. */
if (flag_syntax_only)
+ {
+ /* Pretend that this function has been written out so that we don't try
+ to expand it again. */
+ TREE_ASM_WRITTEN (fn) = 1;
+ return false;
+ }
+
+ if (DECL_OMP_DECLARE_REDUCTION_P (fn))
return false;
return true;
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
return error_mark_node;
}
- else if (TREE_CODE (t) == PARM_DECL
+ else if (ort == C_ORT_OMP
+ && TREE_CODE (t) == PARM_DECL
&& DECL_ARTIFICIAL (t)
&& DECL_NAME (t) == this_identifier)
{
}
if (ort == C_ORT_OMP
- && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
&& TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
if (!integer_nonzerop (length))
{
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
{
if (integer_zerop (length))
{
if (tree_int_cst_equal (size, low_bound))
{
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
{
error_at (OMP_CLAUSE_LOCATION (c),
"zero length array section in %qs clause",
else if (length == NULL_TREE)
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
maybe_zero_len = true;
if (first_non_one == types.length ())
first_non_one++;
else if (length == NULL_TREE)
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
- && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION)
maybe_zero_len = true;
if (first_non_one == types.length ())
first_non_one++;
bool maybe_zero_len = false;
unsigned int first_non_one = 0;
auto_vec<tree, 10> types;
- tree first = handle_omp_array_sections_1 (c, OMP_CLAUSE_DECL (c), types,
+ tree *tp = &OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && TREE_CODE (*tp) == TREE_LIST
+ && TREE_PURPOSE (*tp)
+ && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC)
+ tp = &TREE_VALUE (*tp);
+ tree first = handle_omp_array_sections_1 (c, *tp, types,
maybe_zero_len, first_non_one,
ort);
if (first == error_mark_node)
return false;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
{
- tree t = OMP_CLAUSE_DECL (c);
+ tree t = *tp;
tree tem = NULL_TREE;
if (processing_template_decl)
return false;
}
if (tem)
first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
- OMP_CLAUSE_DECL (c) = first;
+ *tp = first;
}
else
{
if (i > first_non_one
&& ((length && integer_nonzerop (length))
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION))
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION))
continue;
if (length)
l = fold_convert (sizetype, length);
tree eltype = TREE_TYPE (types[num - 1]);
while (TREE_CODE (eltype) == ARRAY_TYPE)
eltype = TREE_TYPE (eltype);
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
size = size_binop (EXACT_DIV_EXPR, size,
size_in_bytes (eltype));
size = size_binop (MULT_EXPR, size, l);
{
if (side_effects)
size = build2 (COMPOUND_EXPR, sizetype, side_effects, size);
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
{
size = size_binop (MINUS_EXPR, size, size_one_node);
+ size = save_expr (size);
tree index_type = build_index_type (size);
tree eltype = TREE_TYPE (first);
while (TREE_CODE (eltype) == ARRAY_TYPE)
TYPE_SIZE_UNIT (type));
if (integer_zerop (size))
{
- error ("%qE in %<reduction%> clause is a zero size array",
- omp_clause_printable_decl (t));
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE in %<reduction%> clause is a zero size array",
+ omp_clause_printable_decl (t));
return true;
}
size = size_binop (MINUS_EXPR, size, size_one_node);
+ size = save_expr (size);
tree index_type = build_index_type (size);
tree atype = build_array_type (type, index_type);
tree ptype = build_pointer_type (type);
}
else if (TYPE_READONLY (type))
{
- error ("%qE has const type for %<reduction%>",
- omp_clause_printable_decl (t));
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE has const type for %<reduction%>",
+ omp_clause_printable_decl (t));
return true;
}
else if (!processing_template_decl)
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0])))
cxx_mark_addressable (placeholder);
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
- && !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
+ && (decl_placeholder
+ || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
cxx_mark_addressable (decl_placeholder ? decl_placeholder
: OMP_CLAUSE_DECL (c));
tree omp_out = placeholder;
{
gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
&& TREE_CODE (stmts[4]) == DECL_EXPR);
- if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
+ if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3]))
+ && (decl_placeholder
+ || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
cxx_mark_addressable (decl_placeholder ? decl_placeholder
: OMP_CLAUSE_DECL (c));
if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
*need_dtor = true;
else
{
- error ("user defined reduction not found for %qE",
- omp_clause_printable_decl (t));
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "user defined reduction not found for %qE",
+ omp_clause_printable_decl (t));
return true;
}
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x))
{
- if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
+ if (TREE_CODE (x) == USING_DECL
+ || !DECL_NONSTATIC_MEMBER_FUNCTION_P (x))
continue;
tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
if (!ods || !TREE_VALUE (ods))
return false;
}
+/* Finish OpenMP iterators ITER. Return true if they are errorneous
+ and clauses containing them should be removed. */
+
+static bool
+cp_omp_finish_iterators (tree iter)
+{
+ bool ret = false;
+ for (tree it = iter; it; it = TREE_CHAIN (it))
+ {
+ tree var = TREE_VEC_ELT (it, 0);
+ tree begin = TREE_VEC_ELT (it, 1);
+ tree end = TREE_VEC_ELT (it, 2);
+ tree step = TREE_VEC_ELT (it, 3);
+ tree orig_step;
+ tree type = TREE_TYPE (var);
+ location_t loc = DECL_SOURCE_LOCATION (var);
+ if (type == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+ if (type_dependent_expression_p (var))
+ continue;
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ {
+ error_at (loc, "iterator %qD has neither integral nor pointer type",
+ var);
+ ret = true;
+ continue;
+ }
+ else if (TYPE_READONLY (type))
+ {
+ error_at (loc, "iterator %qD has const qualified type", var);
+ ret = true;
+ continue;
+ }
+ if (type_dependent_expression_p (begin)
+ || type_dependent_expression_p (end)
+ || type_dependent_expression_p (step))
+ continue;
+ else if (error_operand_p (step))
+ {
+ ret = true;
+ continue;
+ }
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
+ {
+ error_at (EXPR_LOC_OR_LOC (step, loc),
+ "iterator step with non-integral type");
+ ret = true;
+ continue;
+ }
+
+ begin = mark_rvalue_use (begin);
+ end = mark_rvalue_use (end);
+ step = mark_rvalue_use (step);
+ begin = cp_build_c_cast (type, begin, tf_warning_or_error);
+ end = cp_build_c_cast (type, end, tf_warning_or_error);
+ orig_step = step;
+ if (!processing_template_decl)
+ step = orig_step = save_expr (step);
+ tree stype = POINTER_TYPE_P (type) ? sizetype : type;
+ step = cp_build_c_cast (stype, step, tf_warning_or_error);
+ if (POINTER_TYPE_P (type) && !processing_template_decl)
+ {
+ begin = save_expr (begin);
+ step = pointer_int_sum (loc, PLUS_EXPR, begin, step);
+ step = fold_build2_loc (loc, MINUS_EXPR, sizetype,
+ fold_convert (sizetype, step),
+ fold_convert (sizetype, begin));
+ step = fold_convert (ssizetype, step);
+ }
+ if (!processing_template_decl)
+ {
+ begin = maybe_constant_value (begin);
+ end = maybe_constant_value (end);
+ step = maybe_constant_value (step);
+ orig_step = maybe_constant_value (orig_step);
+ }
+ if (integer_zerop (step))
+ {
+ error_at (loc, "iterator %qD has zero step", var);
+ ret = true;
+ continue;
+ }
+
+ if (begin == error_mark_node
+ || end == error_mark_node
+ || step == error_mark_node
+ || orig_step == error_mark_node)
+ {
+ ret = true;
+ continue;
+ }
+
+ if (!processing_template_decl)
+ {
+ begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin);
+ end = fold_build_cleanup_point_expr (TREE_TYPE (end), end);
+ step = fold_build_cleanup_point_expr (TREE_TYPE (step), step);
+ orig_step = fold_build_cleanup_point_expr (TREE_TYPE (orig_step),
+ orig_step);
+ }
+ hash_set<tree> pset;
+ tree it2;
+ for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2))
+ {
+ tree var2 = TREE_VEC_ELT (it2, 0);
+ tree begin2 = TREE_VEC_ELT (it2, 1);
+ tree end2 = TREE_VEC_ELT (it2, 2);
+ tree step2 = TREE_VEC_ELT (it2, 3);
+ location_t loc2 = DECL_SOURCE_LOCATION (var2);
+ if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (begin2, loc2),
+ "begin expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (end2, loc2),
+ "end expression refers to outer iterator %qD", var);
+ break;
+ }
+ else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset))
+ {
+ error_at (EXPR_LOC_OR_LOC (step2, loc2),
+ "step expression refers to outer iterator %qD", var);
+ break;
+ }
+ }
+ if (it2)
+ {
+ ret = true;
+ continue;
+ }
+ TREE_VEC_ELT (it, 1) = begin;
+ TREE_VEC_ELT (it, 2) = end;
+ if (processing_template_decl)
+ TREE_VEC_ELT (it, 3) = orig_step;
+ else
+ {
+ TREE_VEC_ELT (it, 3) = step;
+ TREE_VEC_ELT (it, 4) = orig_step;
+ }
+ }
+ return ret;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
bool copyprivate_seen = false;
bool ordered_seen = false;
bool oacc_async = false;
+ tree last_iterators = NULL_TREE;
+ bool last_iterators_remove = false;
+ bool reduction_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
bitmap_initialize (&aligned_head, &bitmap_default_obstack);
+ /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */
bitmap_initialize (&map_head, &bitmap_default_obstack);
bitmap_initialize (&map_field_head, &bitmap_default_obstack);
+ /* If ort == C_ORT_OMP used as nontemporal_head instead. */
bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack);
if (ort & C_ORT_ACC)
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
+ reduction_seen = true;
+ /* FALLTHRU */
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
t = OMP_CLAUSE_DECL (c);
if (TREE_CODE (t) == TREE_LIST)
|| OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL)
&& !TYPE_REF_P (type))
{
- error ("linear clause with %qs modifier applied to "
- "non-reference variable with %qT type",
- OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
- ? "ref" : "uval", TREE_TYPE (t));
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear clause with %qs modifier applied to "
+ "non-reference variable with %qT type",
+ OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF
+ ? "ref" : "uval", TREE_TYPE (t));
remove = true;
break;
}
if (!INTEGRAL_TYPE_P (type)
&& !TYPE_PTR_P (type))
{
- error ("linear clause applied to non-integral non-pointer"
- " variable with %qT type", TREE_TYPE (t));
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear clause applied to non-integral "
+ "non-pointer variable with %qT type",
+ TREE_TYPE (t));
remove = true;
break;
}
|| !TYPE_REF_P (TREE_TYPE (t))
|| !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (t)))))
{
- error ("linear step expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "linear step expression must be integral");
remove = true;
break;
}
|| (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
remove = true;
break;
}
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
if (DECL_P (t))
- error ("%qD is not a variable in clause %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
else
- error ("%qE is not a variable in clause %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (ort == C_ORT_ACC
{
if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
{
- error ("%qD appears more than once in reduction clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in reduction clauses",
+ t);
remove = true;
}
else
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
remove = true;
}
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
&& bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
else
- error ("%qD appears both in data and map clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears both in data and map clauses", t);
remove = true;
}
else
t = OMP_CLAUSE_DECL (c);
if (ort != C_ORT_ACC && t == current_class_ptr)
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
remove = true;
break;
}
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
if (DECL_P (t))
- error ("%qD is not a variable in clause %<firstprivate%>", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in clause %<firstprivate%>",
+ t);
else
- error ("%qE is not a variable in clause %<firstprivate%>", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %<firstprivate%>",
+ t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
remove = true;
}
else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
else
- error ("%qD appears both in data and map clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears both in data and map clauses", t);
remove = true;
}
else
t = OMP_CLAUSE_DECL (c);
if (t == current_class_ptr)
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
remove = true;
break;
}
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
if (DECL_P (t))
- error ("%qD is not a variable in clause %<lastprivate%>", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in clause %<lastprivate%>",
+ t);
else
- error ("%qE is not a variable in clause %<lastprivate%>", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %<lastprivate%>",
+ t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
{
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<gang%> static expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<gang%> static expression must be integral");
remove = true;
}
else
break;
case OMP_CLAUSE_SCHEDULE:
- if (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
- {
- const char *p = NULL;
- switch (OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
- {
- case OMP_CLAUSE_SCHEDULE_STATIC: p = "static"; break;
- case OMP_CLAUSE_SCHEDULE_DYNAMIC: break;
- case OMP_CLAUSE_SCHEDULE_GUIDED: break;
- case OMP_CLAUSE_SCHEDULE_AUTO: p = "auto"; break;
- case OMP_CLAUSE_SCHEDULE_RUNTIME: p = "runtime"; break;
- default: gcc_unreachable ();
- }
- if (p)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<nonmonotonic%> modifier specified for %qs "
- "schedule kind", p);
- OMP_CLAUSE_SCHEDULE_KIND (c)
- = (enum omp_clause_schedule_kind)
- (OMP_CLAUSE_SCHEDULE_KIND (c)
- & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
- }
- }
-
t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
if (t == NULL)
;
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("schedule chunk size expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "schedule chunk size expression must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%qs length expression must be integral",
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs length expression must be integral",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else
if (TREE_CODE (t) != INTEGER_CST
|| tree_int_cst_sgn (t) != 1)
{
- error ("%qs length expression must be positive constant"
- " integer expression",
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs length expression must be positive "
+ "constant integer expression",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
}
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<async%> expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<async%> expression must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<thread_limit%> expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<thread_limit%> expression must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<device%> id must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<device%> id must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<dist_schedule%> chunk size expression must be "
- "integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<dist_schedule%> chunk size expression must be "
+ "integral");
remove = true;
}
else
{
t = mark_rvalue_use (t);
- if (!processing_template_decl)
+ if (!processing_template_decl)
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
}
t = OMP_CLAUSE_DECL (c);
if (t == current_class_ptr && ort != C_ORT_OMP_DECLARE_SIMD)
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
remove = true;
break;
}
if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
if (DECL_P (t))
- error ("%qD is not a variable in %<aligned%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %<aligned%> clause", t);
else
- error ("%qE is not a variable in %<aligned%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<aligned%> clause", t);
remove = true;
}
else if (!type_dependent_expression_p (t)
}
else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
{
- error ("%qD appears more than once in %<aligned%> clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in %<aligned%> clauses",
+ t);
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<aligned%> clause alignment expression must "
- "be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<aligned%> clause alignment expression must "
+ "be integral");
remove = true;
}
else
if (TREE_CODE (t) != INTEGER_CST
|| tree_int_cst_sgn (t) != 1)
{
- error ("%<aligned%> clause alignment expression must be "
- "positive constant integer expression");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<aligned%> clause alignment expression must "
+ "be positive constant integer expression");
remove = true;
}
+ else
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
}
OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t;
}
break;
+ case OMP_CLAUSE_NONTEMPORAL:
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %<nontemporal%> clause",
+ t);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<nontemporal%> clause",
+ t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in %<nontemporal%> "
+ "clauses", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
+ break;
+
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
remove = true;
break;
}
+ if (TREE_CODE (t) == TREE_LIST
+ && TREE_PURPOSE (t)
+ && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+ {
+ if (TREE_PURPOSE (t) != last_iterators)
+ last_iterators_remove
+ = cp_omp_finish_iterators (TREE_PURPOSE (t));
+ last_iterators = TREE_PURPOSE (t);
+ t = TREE_VALUE (t);
+ if (last_iterators_remove)
+ t = error_mark_node;
+ }
+ else
+ last_iterators = NULL_TREE;
+
if (TREE_CODE (t) == TREE_LIST)
{
if (handle_omp_array_sections (c, ort))
remove = true;
+ else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<depend%> clause with %<depobj%> dependence "
+ "type on array section");
+ remove = true;
+ }
break;
}
if (t == error_mark_node)
remove = true;
- else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ else if (t == current_class_ptr)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ }
+ else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ else if (!lvalue_p (t))
{
- if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
- break;
if (DECL_P (t))
- error ("%qD is not a variable in %<depend%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not lvalue expression nor array section "
+ "in %<depend%> clause", t);
else
- error ("%qE is not a variable in %<depend%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not lvalue expression nor array section "
+ "in %<depend%> clause", t);
remove = true;
}
- else if (t == current_class_ptr)
+ else if (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
+ && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "bit-field %qE in %qs clause", t, "depend");
remove = true;
}
- else if (!processing_template_decl
- && !cxx_mark_addressable (t))
- remove = true;
+ else if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ)
+ {
+ if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+ ? TREE_TYPE (TREE_TYPE (t))
+ : TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE does not have %<omp_depend_t%> type in "
+ "%<depend%> clause with %<depobj%> dependence "
+ "type", t);
+ remove = true;
+ }
+ }
+ else if (c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t))
+ ? TREE_TYPE (TREE_TYPE (t))
+ : TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE should not have %<omp_depend_t%> type in "
+ "%<depend%> clause with dependence type other than "
+ "%<depobj%>", t);
+ remove = true;
+ }
+ if (!remove)
+ {
+ tree addr = cp_build_addr_expr (t, tf_warning_or_error);
+ if (addr == error_mark_node)
+ remove = true;
+ else
+ {
+ t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ tf_warning_or_error);
+ if (t == error_mark_node)
+ remove = true;
+ else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+ && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+ == TREE_VEC))
+ TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+ else
+ OMP_CLAUSE_DECL (c) = t;
+ }
+ }
break;
case OMP_CLAUSE_MAP:
if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
- error ("%qD appears more than once in motion"
- " clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in motion"
+ " clauses", t);
else if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data"
- " clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data"
+ " clauses", t);
else
- error ("%qD appears more than once in map"
- " clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in map"
+ " clauses", t);
remove = true;
}
else
|| OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
break;
if (DECL_P (t))
- error ("%qD is not a variable in %qs clause", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
else
- error ("%qE is not a variable in %qs clause", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t))
{
- error ("%qD is threadprivate variable in %qs clause", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is threadprivate variable in %qs clause", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (ort != C_ORT_ACC && t == current_class_ptr)
{
- error ("%<this%> allowed in OpenMP only in %<declare simd%>"
- " clauses");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
remove = true;
break;
}
&& !type_dependent_expression_p (t)
&& !INDIRECT_TYPE_P (TREE_TYPE (t)))
{
- error ("%qD is not a pointer variable", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a pointer variable", t);
remove = true;
}
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
remove = true;
}
else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
else
- error ("%qD appears both in data and map clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears both in data and map clauses", t);
remove = true;
}
else
else if (bitmap_bit_p (&map_head, DECL_UID (t)))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
- error ("%qD appears more than once in motion clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in motion clauses", t);
if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
else
- error ("%qD appears more than once in map clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in map clauses", t);
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
|| bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
- error ("%qD appears more than once in data clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
else
- error ("%qD appears both in data and map clauses", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears both in data and map clauses", t);
remove = true;
}
else
handle_map_references:
if (!remove
&& !processing_template_decl
- && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ && ort != C_ORT_DECLARE_SIMD
&& TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
{
t = OMP_CLAUSE_DECL (c);
if (processing_template_decl)
break;
if (DECL_P (t))
- error ("%qD is not an argument in %<uniform%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not an argument in %<uniform%> clause", t);
else
- error ("%qE is not an argument in %<uniform%> clause", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not an argument in %<uniform%> clause", t);
remove = true;
break;
}
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<grainsize%> expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<grainsize%> expression must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<priority%> expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<priority%> expression must be integral");
remove = true;
}
else
else if (!type_dependent_expression_p (t)
&& !INTEGRAL_TYPE_P (TREE_TYPE (t)))
{
- error ("%<num_tasks%> expression must be integral");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<hint%> expression must be integral");
remove = true;
}
else
{
t = maybe_constant_value (t);
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ if (TREE_CODE (t) != INTEGER_CST)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<hint%> expression must be constant integer "
+ "expression");
+ remove = true;
+ }
}
OMP_CLAUSE_HINT_EXPR (c) = t;
}
case OMP_CLAUSE_AUTO:
case OMP_CLAUSE_INDEPENDENT:
case OMP_CLAUSE_SEQ:
+ case OMP_CLAUSE_IF_PRESENT:
+ case OMP_CLAUSE_FINALIZE:
break;
case OMP_CLAUSE_TILE:
case OMP_CLAUSE_NOTINBRANCH:
if (branch_seen)
{
- error ("%<inbranch%> clause is incompatible with "
- "%<notinbranch%>");
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inbranch%> clause is incompatible with "
+ "%<notinbranch%>");
remove = true;
}
branch_seen = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LINEAR:
}
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_NOGROUP:
+ if (reduction_seen)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<nogroup%> clause must not be used together with "
+ "%<reduction%> clause");
+ *pc = OMP_CLAUSE_CHAIN (c);
+ continue;
+ }
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
case OMP_CLAUSE_NOWAIT:
if (copyprivate_seen)
{
break;
case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
if (finish_omp_reduction_clause (c, &need_default_ctor,
&need_dtor))
remove = true;
case OMP_CLAUSE_COPYIN:
if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t))
{
- error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE must be %<threadprivate%> for %<copyin%>", t);
remove = true;
}
break;
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
- else if (TYPE_REF_P (TREE_TYPE (t))
+ else if (!processing_template_decl
+ && TYPE_REF_P (TREE_TYPE (t))
&& !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
remove = true;
}
case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
break;
case OMP_CLAUSE_DEFAULT_SHARED:
- /* const vars may be specified in firstprivate clause. */
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
- && cxx_omp_const_qual_no_mutable (t))
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+ && c_omp_predefined_variable (t))
+ /* The __func__ variable and similar function-local predefined
+ variables may be listed in a shared or firstprivate
+ clause. */
break;
+ if (VAR_P (t)
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && TREE_STATIC (t)
+ && cxx_omp_const_qual_no_mutable (t))
+ {
+ tree ctx = CP_DECL_CONTEXT (t);
+ /* const qualified static data members without mutable
+ member may be specified in firstprivate clause. */
+ if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
+ break;
+ }
share_name = "shared";
break;
case OMP_CLAUSE_DEFAULT_PRIVATE:
}
if (share_name)
{
- error ("%qE is predetermined %qs for %qs",
- omp_clause_printable_decl (t), share_name,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is predetermined %qs for %qs",
+ omp_clause_printable_decl (t), share_name,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE
+ && cxx_omp_const_qual_no_mutable (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<const%> qualified %qE without %<mutable%> member "
+ "may appear only in %<shared%> or %<firstprivate%> "
+ "clauses", omp_clause_printable_decl (t));
remove = true;
}
}
inner_type = type = TREE_TYPE (t);
if ((need_complete_type
|| need_copy_assignment
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
&& TYPE_REF_P (inner_type))
inner_type = TREE_TYPE (inner_type);
while (TREE_CODE (inner_type) == ARRAY_TYPE)
{
/* Allocate a LANG_SPECIFIC structure for V, if needed. */
if (DECL_LANG_SPECIFIC (v) == NULL)
- {
- retrofit_lang_decl (v);
-
- /* Make sure that DECL_DISCRIMINATOR_P continues to be true
- after the allocation of the lang_decl structure. */
- if (DECL_DISCRIMINATOR_P (v))
- DECL_LANG_SPECIFIC (v)->u.base.u2sel = 1;
- }
+ retrofit_lang_decl (v);
if (! CP_DECL_THREAD_LOCAL_P (v))
{
handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
tree declv, tree orig_declv, tree initv,
tree condv, tree incrv, tree *body,
- tree *pre_body, tree &clauses, tree *lastp,
+ tree *pre_body, tree &clauses,
int collapse, int ordered)
{
tree diff, iter_init, iter_incr = NULL, last;
if (init && EXPR_HAS_LOCATION (init))
elocus = EXPR_LOCATION (init);
- cond = cp_fully_fold (cond);
switch (TREE_CODE (cond))
{
case GT_EXPR:
}
incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error);
+ incr = cp_fully_fold (incr);
bool taskloop_iv_seen = false;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
}
+ if (TREE_CODE (TREE_VEC_ELT (orig_declv, i)) == TREE_LIST)
+ {
+ tree t = TREE_VEC_ELT (orig_declv, i);
+ gcc_assert (TREE_PURPOSE (t) == NULL_TREE
+ && TREE_VALUE (t) == NULL_TREE
+ && TREE_CODE (TREE_CHAIN (t)) == TREE_VEC);
+ TREE_PURPOSE (t) = TREE_VEC_ELT (declv, i);
+ TREE_VALUE (t) = last;
+ }
+ else
+ TREE_VEC_ELT (orig_declv, i)
+ = tree_cons (TREE_VEC_ELT (declv, i), last, NULL_TREE);
TREE_VEC_ELT (declv, i) = decl;
TREE_VEC_ELT (initv, i) = init;
TREE_VEC_ELT (condv, i) = cond;
TREE_VEC_ELT (incrv, i) = incr;
- *lastp = last;
return false;
}
{
tree omp_for = NULL, orig_incr = NULL;
tree decl = NULL, init, cond, incr;
- tree last = NULL_TREE;
location_t elocus;
int i;
int collapse = 1;
if (init && EXPR_HAS_LOCATION (init))
elocus = EXPR_LOCATION (init);
+ if (cond == global_namespace)
+ continue;
+
if (cond == NULL)
{
error_at (elocus, "missing controlling predicate");
tree orig_init;
FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
if (orig_init
- && !c_omp_check_loop_iv_exprs (locus, declv,
+ && !c_omp_check_loop_iv_exprs (locus, orig_declv
+ ? orig_declv : declv,
TREE_VEC_ELT (declv, i), orig_init,
NULL_TREE, cp_walk_subtrees))
fail = true;
}
if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv,
initv, condv, incrv, &body,
- &pre_body, clauses, &last,
+ &pre_body, clauses,
collapse, ordered))
return NULL;
continue;
i++;
}
- if (IS_EMPTY_STMT (pre_body))
+ if (pre_body && IS_EMPTY_STMT (pre_body))
pre_body = NULL;
omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
- incrv, body, pre_body);
+ incrv, body, pre_body,
+ !processing_template_decl);
/* Check for iterators appearing in lb, b or incr expressions. */
if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees))
return omp_for;
}
+/* Fix up range for decls. Those decls were pushed into BIND's BIND_EXPR_VARS
+ and need to be moved into the BIND_EXPR inside of the OMP_FOR's body. */
+
+tree
+finish_omp_for_block (tree bind, tree omp_for)
+{
+ if (omp_for == NULL_TREE
+ || !OMP_FOR_ORIG_DECLS (omp_for)
+ || bind == NULL_TREE
+ || TREE_CODE (bind) != BIND_EXPR)
+ return bind;
+ tree b = NULL_TREE;
+ for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (omp_for)); i++)
+ if (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) == TREE_LIST
+ && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)))
+ {
+ tree v = TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i));
+ gcc_assert (BIND_EXPR_BLOCK (bind)
+ && (BIND_EXPR_VARS (bind)
+ == BLOCK_VARS (BIND_EXPR_BLOCK (bind))));
+ for (int j = 2; j < TREE_VEC_LENGTH (v); j++)
+ for (tree *p = &BIND_EXPR_VARS (bind); *p; p = &DECL_CHAIN (*p))
+ {
+ if (*p == TREE_VEC_ELT (v, j))
+ {
+ tree var = *p;
+ *p = DECL_CHAIN (*p);
+ if (b == NULL_TREE)
+ {
+ b = make_node (BLOCK);
+ b = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+ OMP_FOR_BODY (omp_for), b);
+ TREE_SIDE_EFFECTS (b) = 1;
+ OMP_FOR_BODY (omp_for) = b;
+ }
+ DECL_CHAIN (var) = BIND_EXPR_VARS (b);
+ BIND_EXPR_VARS (b) = var;
+ BLOCK_VARS (BIND_EXPR_BLOCK (b)) = var;
+ }
+ }
+ BLOCK_VARS (BIND_EXPR_BLOCK (bind)) = BIND_EXPR_VARS (bind);
+ }
+ return bind;
+}
+
void
-finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs,
- tree rhs, tree v, tree lhs1, tree rhs1, bool seq_cst)
+finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
+ tree lhs, tree rhs, tree v, tree lhs1, tree rhs1,
+ tree clauses, enum omp_memory_order mo)
{
tree orig_lhs;
tree orig_rhs;
|| (v && type_dependent_expression_p (v))
|| (lhs1 && type_dependent_expression_p (lhs1))
|| (rhs1 && type_dependent_expression_p (rhs1)));
+ if (clauses)
+ {
+ gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE
+ && OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT
+ && OMP_CLAUSE_CHAIN (clauses) == NULL_TREE);
+ if (type_dependent_expression_p (OMP_CLAUSE_HINT_EXPR (clauses))
+ || TREE_CODE (OMP_CLAUSE_HINT_EXPR (clauses)) != INTEGER_CST)
+ dependent_p = true;
+ }
if (!dependent_p)
{
lhs = build_non_dependent_expr (lhs);
"expressions for memory");
return;
}
- stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs,
- v, lhs1, rhs1, swapped, seq_cst,
+ stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs,
+ v, lhs1, rhs1, swapped, mo,
processing_template_decl != 0);
if (stmt == error_mark_node)
return;
{
if (code == OMP_ATOMIC_READ)
{
- stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs),
- OMP_ATOMIC_READ, orig_lhs);
- OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+ stmt = build_min_nt_loc (loc, OMP_ATOMIC_READ, orig_lhs);
+ OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
else
COMPOUND_EXPR, orig_rhs1, stmt);
if (code != OMP_ATOMIC)
{
- stmt = build_min_nt_loc (EXPR_LOCATION (orig_lhs1),
- code, orig_lhs1, stmt);
- OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+ stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt);
+ OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt);
}
}
- stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt);
- OMP_ATOMIC_SEQ_CST (stmt) = seq_cst;
+ stmt = build2 (OMP_ATOMIC, void_type_node,
+ clauses ? clauses : integer_zero_node, stmt);
+ OMP_ATOMIC_MEMORY_ORDER (stmt) = mo;
+ SET_EXPR_LOCATION (stmt, loc);
}
+
+ /* Avoid -Wunused-value warnings here, the whole construct has side-effects
+ and even if it might be wrapped from fold-const.c or c-omp.c wrapped
+ in some tree that appears to be unused, the value is not unused. */
+ warning_sentinel w (warn_unused_value);
finish_expr_stmt (stmt);
}
}
void
-finish_omp_flush (void)
+finish_omp_depobj (location_t loc, tree depobj,
+ enum omp_clause_depend_kind kind, tree clause)
+{
+ if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj))
+ {
+ if (!lvalue_p (depobj))
+ {
+ error_at (EXPR_LOC_OR_LOC (depobj, loc),
+ "%<depobj%> expression is not lvalue expression");
+ depobj = error_mark_node;
+ }
+ }
+
+ if (processing_template_decl)
+ {
+ if (clause == NULL_TREE)
+ clause = build_int_cst (integer_type_node, kind);
+ add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause));
+ return;
+ }
+
+ if (!error_operand_p (depobj))
+ {
+ tree addr = cp_build_addr_expr (depobj, tf_warning_or_error);
+ if (addr == error_mark_node)
+ depobj = error_mark_node;
+ else
+ depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ tf_warning_or_error);
+ }
+
+ c_finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+void
+finish_omp_flush (int mo)
{
tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
vec<tree, va_gc> *vec = make_tree_vector ();
+ if (mo != MEMMODEL_LAST)
+ {
+ fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
+ vec->quick_push (build_int_cst (integer_type_node, mo));
+ }
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
release_tree_vector (vec);
finish_expr_stmt (stmt);
tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
if (ifc != NULL_TREE)
{
- tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
- ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
- boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc),
- build_zero_cst (type));
+ if (OMP_CLAUSE_IF_MODIFIER (ifc) != ERROR_MARK
+ && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST)
+ error_at (OMP_CLAUSE_LOCATION (ifc),
+ "expected %<cancel%> %<if%> clause modifier");
+ else
+ {
+ tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF);
+ if (ifc2 != NULL_TREE)
+ {
+ gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST
+ && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK
+ && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST);
+ error_at (OMP_CLAUSE_LOCATION (ifc2),
+ "expected %<cancel%> %<if%> clause modifier");
+ }
+ }
+
+ if (!processing_template_decl)
+ ifc = maybe_convert_cond (OMP_CLAUSE_IF_EXPR (ifc));
+ else
+ ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
+ OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK,
+ integer_zero_node, ERROR_MARK,
+ NULL, tf_warning_or_error);
}
else
ifc = boolean_true_node;
/* Fold the expression and convert it to a boolean value. */
condition = perform_implicit_conversion_flags (boolean_type_node, condition,
complain, LOOKUP_NORMAL);
- condition = fold_non_dependent_expr (condition);
+ condition = fold_non_dependent_expr (condition, complain,
+ /*manifestly_const_eval=*/true);
if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
/* Do nothing; the condition is satisfied. */
if (identifier_p (expr))
expr = lookup_name (expr);
- if (INDIRECT_REF_P (expr))
+ if (INDIRECT_REF_P (expr)
+ || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
/* This can happen when the expression is, e.g., "a.b". Just
look at the underlying operand. */
expr = TREE_OPERAND (expr, 0);
if (copy_fn_p (fn) > 0)
{
saw_copy = true;
- maybe_instantiate_noexcept (fn);
- if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
+ if (!maybe_instantiate_noexcept (fn)
+ || !TYPE_NOTHROW_P (TREE_TYPE (fn)))
return false;
}
}
return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
|| (CLASS_TYPE_P (type1)
&& (t = locate_ctor (type1))
- && (maybe_instantiate_noexcept (t),
- TYPE_NOTHROW_P (TREE_TYPE (t)))));
+ && maybe_instantiate_noexcept (t)
+ && TYPE_NOTHROW_P (TREE_TYPE (t))));
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
type1 = strip_array_types (type1);
capture_decltype (tree decl)
{
tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
- /* FIXME do lookup instead of list walk? */
- tree cap = value_member (decl, LAMBDA_EXPR_CAPTURE_LIST (lam));
+ tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
+ /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
tree type;
- if (cap)
- type = TREE_TYPE (TREE_PURPOSE (cap));
+ if (cap && is_capture_proxy (cap))
+ type = TREE_TYPE (cap);
else
switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam))
{
TREE_TYPE (arg), 1, arg);
}
+/* Finish __builtin_convertvector (arg, type). */
+
+tree
+cp_build_vec_convert (tree arg, location_t loc, tree type,
+ tsubst_flags_t complain)
+{
+ if (error_operand_p (type))
+ return error_mark_node;
+ if (error_operand_p (arg))
+ return error_mark_node;
+
+ tree ret = NULL_TREE;
+ if (!type_dependent_expression_p (arg) && !dependent_type_p (type))
+ ret = c_build_vec_convert (cp_expr_loc_or_loc (arg, input_location),
+ decay_conversion (arg, complain),
+ loc, type, (complain & tf_error) != 0);
+
+ if (!processing_template_decl)
+ return ret;
+
+ return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg);
+}
+
#include "gt-cp-semantics.h"