building RTL. These routines are used both during actual parsing
and during the instantiation of template functions.
- Copyright (C) 1998-2019 Free Software Foundation, Inc.
+ Copyright (C) 1998-2020 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible. */
- vec<deferred_access_check, va_gc> * GTY(()) deferred_access_checks;
+ vec<deferred_access_check, va_gc> *deferred_access_checks;
/* The current mode of access checks. */
enum deferring_kind deferring_access_checks_kind;
-
};
/* Data for deferred access checking. */
}
}
+/* If the current scope isn't allowed to access DECL along
+ BASETYPE_PATH, give an error, or if we're parsing a function or class
+ template, defer the access check to be performed at instantiation time.
+ The most derived class in BASETYPE_PATH is the one used to qualify DECL.
+ DIAG_DECL is the declaration to use in the error diagnostic. */
+
+static bool
+enforce_access (tree basetype_path, tree decl, tree diag_decl,
+ tsubst_flags_t complain, access_failure_info *afi = NULL)
+{
+ gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
+
+ if (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (decl))
+ {
+ /* 7.3.3/18: The additional constructors are accessible if they would be
+ accessible when used to construct an object of the corresponding base
+ class. */
+ decl = strip_inheriting_ctors (decl);
+ basetype_path = lookup_base (basetype_path, DECL_CONTEXT (decl),
+ ba_any, NULL, complain);
+ }
+
+ tree cs = current_scope ();
+ if (processing_template_decl
+ && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL))
+ if (tree template_info = get_template_info (cs))
+ {
+ /* When parsing a function or class template, we in general need to
+ defer access checks until template instantiation time, since a friend
+ declaration may grant access only to a particular specialization of
+ the template. */
+
+ if (accessible_p (basetype_path, decl, /*consider_local_p=*/true))
+ /* But if the member is deemed accessible at parse time, then we can
+ assume it'll be accessible at instantiation time. */
+ return true;
+
+ /* Access of a dependent decl should be rechecked after tsubst'ing
+ into the user of the decl, rather than explicitly deferring the
+ check here. */
+ gcc_assert (!uses_template_parms (decl));
+ if (TREE_CODE (decl) == FIELD_DECL)
+ gcc_assert (!uses_template_parms (DECL_CONTEXT (decl)));
+
+ /* Defer this access check until instantiation time. */
+ deferred_access_check access_check;
+ access_check.binfo = basetype_path;
+ access_check.decl = decl;
+ access_check.diag_decl = diag_decl;
+ access_check.loc = input_location;
+ vec_safe_push (TI_DEFERRED_ACCESS_CHECKS (template_info), access_check);
+ return true;
+ }
+
+ if (!accessible_p (basetype_path, decl, /*consider_local_p=*/true))
+ {
+ if (flag_new_inheriting_ctors)
+ diag_decl = strip_inheriting_ctors (diag_decl);
+ if (complain & tf_error)
+ complain_about_access (decl, diag_decl, true);
+ if (afi)
+ afi->record_access_failure (basetype_path, decl, diag_decl);
+ return false;
+ }
+
+ return true;
+}
+
/* Perform the access checks in CHECKS. The TREE_PURPOSE of each node
is the BINFO indicating the qualifying scope used to access the
DECL node stored in the TREE_VALUE of the node. If CHECKS is empty
deferred_access *ptr;
deferred_access_check *chk;
-
- /* Exit if we are in a context that no access checking is performed.
- */
+ /* Exit if we are in a context that no access checking is performed. */
if (deferred_access_no_check)
return true;
/* 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 false;
tree fndecl = cp_get_callee_fndecl_nofold (fn);
+ if (fndecl == NULL_TREE)
+ return false;
+
if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
BUILT_IN_FRONTEND))
return true;
return ret;
}
-/* If we are currently parsing a template and we encountered a typedef
- TYPEDEF_DECL that is being accessed though CONTEXT, this function
- adds the typedef to a list tied to the current template.
- At template instantiation time, that list is walked and access check
- performed for each typedef.
- LOCATION is the location of the usage point of TYPEDEF_DECL. */
-
-void
-add_typedef_to_current_template_for_access_check (tree typedef_decl,
- tree context,
- location_t location)
-{
- tree template_info = NULL;
- tree cs = current_scope ();
-
- if (!is_typedef_decl (typedef_decl)
- || !context
- || !CLASS_TYPE_P (context)
- || !cs)
- return;
-
- if (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)
- template_info = get_template_info (cs);
-
- if (template_info
- && TI_TEMPLATE (template_info)
- && !currently_open_class (context))
- append_type_to_template_for_access_check (cs, typedef_decl,
- context, location);
-}
-
/* DECL was the declaration to which a qualified-id resolved. Issue
an error message if it is not accessible. If OBJECT_TYPE is
non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the
type of `*x', or `x', respectively. If the DECL was named as
- `A::B' then NESTED_NAME_SPECIFIER is `A'. */
+ `A::B' then NESTED_NAME_SPECIFIER is `A'. Return value is like
+ perform_access_checks above. */
-void
+bool
check_accessibility_of_qualified_id (tree decl,
tree object_type,
- tree nested_name_specifier)
+ tree nested_name_specifier,
+ tsubst_flags_t complain)
{
- tree scope;
- tree qualifying_type = NULL_TREE;
-
- /* If we are parsing a template declaration and if decl is a typedef,
- add it to a list tied to the template.
- At template instantiation time, that list will be walked and
- access check performed. */
- add_typedef_to_current_template_for_access_check (decl,
- nested_name_specifier
- ? nested_name_specifier
- : DECL_CONTEXT (decl),
- input_location);
-
/* If we're not checking, return immediately. */
if (deferred_access_no_check)
- return;
+ return true;
/* Determine the SCOPE of DECL. */
- scope = context_for_name_lookup (decl);
+ tree scope = context_for_name_lookup (decl);
/* If the SCOPE is not a type, then DECL is not a member. */
- if (!TYPE_P (scope))
- return;
+ if (!TYPE_P (scope)
+ /* If SCOPE is dependent then we can't perform this access check now,
+ and since we'll perform this access check again after substitution
+ there's no need to explicitly defer it. */
+ || dependent_type_p (scope))
+ return true;
+
+ tree qualifying_type = NULL_TREE;
/* Compute the scope through which DECL is being accessed. */
if (object_type
/* OBJECT_TYPE might not be a class type; consider:
if (qualifying_type
/* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
or similar in a default argument value. */
- && CLASS_TYPE_P (qualifying_type)
- && !dependent_type_p (qualifying_type))
- perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
- decl, tf_warning_or_error);
+ && CLASS_TYPE_P (qualifying_type))
+ return perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
+ decl, complain);
+
+ return true;
}
/* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the
bool abnormal = true;
for (lkp_iterator iter (fn); abnormal && iter; ++iter)
{
- tree fndecl = *iter;
+ tree fndecl = STRIP_TEMPLATE (*iter);
if (TREE_CODE (fndecl) != FUNCTION_DECL
|| !TREE_THIS_VOLATILE (fndecl))
abnormal = false;
tree arg2 = (*orig_args)[2];
int literal_mask = ((literal_integer_zerop (arg1) << 1)
| (literal_integer_zerop (arg2) << 2));
- arg2 = instantiate_non_dependent_expr (arg2);
warn_for_memset (input_location, arg0, arg2, literal_mask);
}
{
if (!vec_safe_is_empty (*args))
error ("arguments to destructor are not allowed");
- /* Mark the pseudo-destructor call as having side-effects so
- that we do not issue warnings about its use. */
- result = build1 (NOP_EXPR,
- void_type_node,
- TREE_OPERAND (fn, 0));
- TREE_SIDE_EFFECTS (result) = 1;
+ /* C++20/DR: If the postfix-expression names a pseudo-destructor (in
+ which case the postfix-expression is a possibly-parenthesized class
+ member access), the function call destroys the object of scalar type
+ denoted by the object expression of the class member access. */
+ tree ob = TREE_OPERAND (fn, 0);
+ if (obvalue_p (ob))
+ result = build_trivial_dtor_call (ob);
+ else
+ /* No location to clobber. */
+ result = convert_to_void (ob, ICV_STATEMENT, complain);
}
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
/* If the "function" is really an object of class type, it might
}
}
- return build3_loc (loc, PSEUDO_DTOR_EXPR, void_type_node, object,
+ tree type = (type_dependent_expression_p (object)
+ ? NULL_TREE : void_type_node);
+
+ return build3_loc (loc, PSEUDO_DTOR_EXPR, type, object,
scope, destructor);
}
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, finfo->interface_unknown);
}
- reset_specialization();
+ reset_specialization ();
/* Make a declaration for this class in its own scope. */
build_self_reference ();
process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use)
{
if (cp_unevaluated_operand)
- /* It's not a use (3.2) if we're in an unevaluated context. */
- return decl;
+ {
+ tree type = TREE_TYPE (decl);
+ if (!dependent_type_p (type)
+ && variably_modified_type_p (type, NULL_TREE))
+ /* VLAs are used even in unevaluated context. */;
+ else
+ /* It's not a use (3.2) if we're in an unevaluated context. */
+ return decl;
+ }
if (decl == error_mark_node)
return decl;
t = TREE_OPERAND (t, 0);
ret = t;
if (TREE_CODE (t) == COMPONENT_REF
- && ort == C_ORT_OMP
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
|| OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
return error_mark_node;
}
t = TREE_OPERAND (t, 0);
+ if (ort == C_ORT_ACC && TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
}
if (REFERENCE_REF_P (t))
t = TREE_OPERAND (t, 0);
if (low_bound == NULL_TREE)
low_bound = integer_zero_node;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+ {
+ if (length != integer_one_node)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "expected single pointer in %qs clause",
+ c_omp_map_clause_name (c, ort == C_ORT_ACC));
+ return error_mark_node;
+ }
+ }
if (length != NULL_TREE)
{
if (!integer_nonzerop (length))
if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ {
+ gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER;
+ OMP_CLAUSE_SET_MAP_KIND (c2, k);
+ }
else if (REFERENCE_REF_P (t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
t = TREE_OPERAND (t, 0);
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER;
+ OMP_CLAUSE_SET_MAP_KIND (c2, k);
}
else
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
omp_reduction_id (ERROR_MARK,
TREE_OPERAND (id, 1),
type),
- false, false);
+ LOOK_want::NORMAL, false);
tree fns = id;
id = NULL_TREE;
if (fns && is_overloaded_fn (fns))
return ret;
}
+/* Ensure that pointers are used in OpenACC attach and detach clauses.
+ Return true if an error has been detected. */
+
+static bool
+cp_oacc_check_attachments (tree c)
+{
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+ return false;
+
+ /* OpenACC attach / detach clauses must be pointers. */
+ if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+ {
+ tree t = OMP_CLAUSE_DECL (c);
+ tree type;
+
+ while (TREE_CODE (t) == TREE_LIST)
+ t = TREE_CHAIN (t);
+
+ type = TREE_TYPE (t);
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+
+ if (TREE_CODE (type) != POINTER_TYPE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause",
+ c_omp_map_clause_name (c, true));
+ return true;
+ }
+ }
+
+ return false;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
t = OMP_CLAUSE_DECL (c);
check_dup_generic_t:
if (t == current_class_ptr
- && (ort != C_ORT_OMP_DECLARE_SIMD
+ && ((ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_ACC)
|| (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
{
handle_field_decl:
if (!remove
&& TREE_CODE (t) == FIELD_DECL
- && t == OMP_CLAUSE_DECL (c)
- && ort != C_ORT_ACC)
+ && t == OMP_CLAUSE_DECL (c))
{
OMP_CLAUSE_DECL (c)
= omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
else
t = OMP_CLAUSE_DECL (c);
- if (t == current_class_ptr)
+ if (ort != C_ORT_ACC && t == current_class_ptr)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%<this%> allowed in OpenMP only in %<declare simd%>"
}
if (t == error_mark_node)
remove = true;
- else if (t == current_class_ptr)
+ else if (ort != C_ORT_ACC && t == current_class_ptr)
{
error_at (OMP_CLAUSE_LOCATION (c),
"%<this%> allowed in OpenMP only in %<declare simd%>"
}
}
}
+ if (cp_oacc_check_attachments (c))
+ remove = true;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+ /* In this case, we have a single array element which is a
+ pointer, and we already set OMP_CLAUSE_SIZE in
+ handle_omp_array_sections above. For attach/detach clauses,
+ reset the OMP_CLAUSE_SIZE (representing a bias) to zero
+ here. */
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
break;
}
if (t == error_mark_node)
remove = true;
break;
}
+ /* OpenACC attach / detach clauses must be pointers. */
+ if (cp_oacc_check_attachments (c))
+ {
+ remove = true;
+ break;
+ }
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+ /* For attach/detach clauses, set OMP_CLAUSE_SIZE (representing a
+ bias) to zero here, so it is not set erroneously to the pointer
+ size later on in gimplify.c. */
+ OMP_CLAUSE_SIZE (c) = size_zero_node;
if (REFERENCE_REF_P (t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
{
t = TREE_OPERAND (t, 0);
OMP_CLAUSE_DECL (c) = t;
}
+ if (ort == C_ORT_ACC
+ && TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
+ t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
if (TREE_CODE (t) == COMPONENT_REF
- && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ && ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+ || ort == C_ORT_ACC)
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
{
if (type_dependent_expression_p (t))
break;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
- || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH))
break;
if (DECL_P (t))
error_at (OMP_CLAUSE_LOCATION (c),
else
bitmap_set_bit (&generic_head, DECL_UID (t));
}
- else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ else if (bitmap_bit_p (&map_head, DECL_UID (t))
+ && (ort != C_ORT_ACC
+ || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
OMP_CLAUSE_MAP);
if (TREE_CODE (t) == COMPONENT_REF)
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+ {
+ gomp_map_kind k
+ = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+ : GOMP_MAP_ALWAYS_POINTER;
+ OMP_CLAUSE_SET_MAP_KIND (c2, k);
+ }
else
OMP_CLAUSE_SET_MAP_KIND (c2,
GOMP_MAP_FIRSTPRIVATE_REFERENCE);
TREE_OPERAND (cond, 1), iter);
return true;
}
- if (!c_omp_check_loop_iv_exprs (locus, orig_declv,
+ if (!c_omp_check_loop_iv_exprs (locus, orig_declv, i,
TREE_VEC_ELT (declv, i), NULL_TREE,
cond, cp_walk_subtrees))
return true;
tree orig_init;
FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
if (orig_init
- && !c_omp_check_loop_iv_exprs (locus, orig_declv
- ? orig_declv : declv,
+ && !c_omp_check_loop_iv_exprs (locus,
+ orig_declv ? orig_declv : declv, i,
TREE_VEC_ELT (declv, i), orig_init,
NULL_TREE, cp_walk_subtrees))
fail = true;
return NULL;
}
- if (!processing_template_decl)
- {
- init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
- init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init,
- tf_warning_or_error);
- }
+ if (!processing_template_decl && TREE_CODE (init) != TREE_VEC)
+ init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init,
+ tf_warning_or_error);
else
init = build2 (MODIFY_EXPR, void_type_node, decl, init);
- if (cond
- && TREE_SIDE_EFFECTS (cond)
- && COMPARISON_CLASS_P (cond)
- && !processing_template_decl)
- {
- tree t = TREE_OPERAND (cond, 0);
- if (TREE_SIDE_EFFECTS (t)
- && t != decl
- && (TREE_CODE (t) != NOP_EXPR
- || TREE_OPERAND (t, 0) != decl))
- TREE_OPERAND (cond, 0)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
-
- t = TREE_OPERAND (cond, 1);
- if (TREE_SIDE_EFFECTS (t)
- && t != decl
- && (TREE_CODE (t) != NOP_EXPR
- || TREE_OPERAND (t, 0) != decl))
- TREE_OPERAND (cond, 1)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
- }
if (decl == error_mark_node || init == error_mark_node)
return NULL;
for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
{
- decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i), 0);
+ init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i);
+ decl = TREE_OPERAND (init, 0);
+ cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), i);
incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i);
+ if (!processing_template_decl)
+ {
+ if (TREE_CODE (TREE_OPERAND (init, 1)) == TREE_VEC)
+ {
+ tree t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 1);
+ TREE_VEC_ELT (TREE_OPERAND (init, 1), 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 2);
+ TREE_VEC_ELT (TREE_OPERAND (init, 1), 2)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ else
+ {
+ tree t = TREE_OPERAND (init, 1);
+ TREE_OPERAND (init, 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ if (TREE_CODE (TREE_OPERAND (cond, 1)) == TREE_VEC)
+ {
+ tree t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1);
+ TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2);
+ TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ else
+ {
+ tree t = TREE_OPERAND (cond, 1);
+ TREE_OPERAND (cond, 1)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ }
+
if (TREE_CODE (incr) != MODIFY_EXPR)
continue;
error ("static assertion failed: %s",
TREE_STRING_POINTER (message));
- /* Actually explain the failure if this is a concept check. */
- if (concept_check_p (orig_condition))
+ /* Actually explain the failure if this is a concept check or a
+ requires-expression. */
+ if (concept_check_p (orig_condition)
+ || TREE_CODE (orig_condition) == REQUIRES_EXPR)
diagnose_constraints (location, orig_condition, NULL_TREE);
}
else if (condition && condition != error_mark_node)
return type;
}
+ else if (processing_template_decl)
+ {
+ ++cp_unevaluated_operand;
+ expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+ --cp_unevaluated_operand;
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
/* The type denoted by decltype(e) is defined as follows: */
capture_decltype (tree decl)
{
tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
- tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
- /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
+ tree cap = lookup_name_real (DECL_NAME (decl), LOOK_where::BLOCK,
+ LOOK_want::NORMAL | LOOK_want::HIDDEN_LAMBDA);
tree type;
if (cap && is_capture_proxy (cap))
tree ret = NULL_TREE;
if (!type_dependent_expression_p (arg) && !dependent_type_p (type))
- ret = c_build_vec_convert (cp_expr_loc_or_input_loc (arg), arg,
+ ret = c_build_vec_convert (cp_expr_loc_or_input_loc (arg),
+ decay_conversion (arg, complain),
loc, type, (complain & tf_error) != 0);
if (!processing_template_decl)