static void template_parm_level_and_index (tree, int*, int*);
static int unify_pack_expansion (tree, tree, tree,
tree, unification_kind_t, bool, bool);
+static tree copy_template_args (tree);
static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
if (!t || t == error_mark_node)
return NULL;
- if (TREE_CODE (t) == NAMESPACE_DECL)
+ if (TREE_CODE (t) == NAMESPACE_DECL
+ || TREE_CODE (t) == PARM_DECL)
return NULL;
if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
{
int depth;
- for (depth = 0;
- type && TREE_CODE (type) != NAMESPACE_DECL;
- type = (TREE_CODE (type) == FUNCTION_DECL)
- ? CP_DECL_CONTEXT (type) : CP_TYPE_CONTEXT (type))
+ for (depth = 0; type && TREE_CODE (type) != NAMESPACE_DECL; )
{
tree tinfo = get_template_info (type);
if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
&& uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
++depth;
+
+ if (DECL_P (type))
+ type = CP_DECL_CONTEXT (type);
+ else if (LAMBDA_TYPE_P (type))
+ type = LAMBDA_TYPE_EXTRA_SCOPE (type);
+ else
+ type = CP_TYPE_CONTEXT (type);
}
return depth;
/* Propagate type and const-expression information. */
TREE_TYPE (result) = TREE_TYPE (arg);
TREE_CONSTANT (result) = TREE_CONSTANT (arg);
+ /* Mark this read now, since the expansion might be length 0. */
+ mark_exp_read (arg);
}
else
/* Just use structural equality for these TYPE_PACK_EXPANSIONS;
as two declarations of the same function, for example. */
if (processing_template_decl
- && !instantiation_dependent_expression_p (expr)
- && potential_constant_expression (expr))
+ && potential_nondependent_constant_expression (expr))
{
processing_template_decl_sentinel s;
expr = instantiate_non_dependent_expr_internal (expr, complain);
return NULL_TREE;
if (processing_template_decl)
{
- if (instantiation_dependent_expression_p (expr)
- || !potential_constant_expression (expr))
+ if (!potential_nondependent_constant_expression (expr))
expr = NULL_TREE;
else
{
if (TYPE_REF_OBJ_P (type)
&& has_value_dependent_address (expr))
/* If we want the address and it's value-dependent, don't fold. */;
- else if (!type_unknown_p (expr)
- && processing_template_decl
- && !instantiation_dependent_expression_p (expr)
- && potential_constant_expression (expr))
+ else if (processing_template_decl
+ && potential_nondependent_constant_expression (expr))
non_dep = true;
if (error_operand_p (expr))
return error_mark_node;
tree canon = strip_typedefs (arg, &removed_attributes);
if (removed_attributes
&& (complain & tf_warning))
- warning (0, "ignoring attributes on template argument %qT", arg);
+ warning (OPT_Wignored_attributes,
+ "ignoring attributes on template argument %qT", arg);
return canon;
}
break;
case TYPENAME_TYPE:
- if (!fn)
- WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t));
+ /* A template-id in a TYPENAME_TYPE might be a deduced context after
+ partial instantiation. */
+ WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t));
break;
case CONSTRUCTOR:
return 1;
}
-static tree tsubst_omp_clauses (tree, bool, bool, tree, tsubst_flags_t, tree);
+static tree tsubst_omp_clauses (tree, enum c_omp_region_type, tree,
+ tsubst_flags_t, tree);
/* Instantiate a single dependent attribute T (a TREE_LIST), and return either
T or a new TREE_LIST, possibly a chain in the case of a pack expansion. */
get_attribute_name (t)))
{
tree clauses = TREE_VALUE (val);
- clauses = tsubst_omp_clauses (clauses, true, false, args,
+ clauses = tsubst_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD, args,
complain, in_decl);
c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
- clauses = finish_omp_clauses (clauses, false, true);
+ clauses = finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
tree parms = DECL_ARGUMENTS (*decl_p);
clauses
= c_omp_declare_simd_clauses_to_numbers (parms, clauses);
DECL_SOURCE_LOCATION (typedecl);
TYPE_PACKED (type) = TYPE_PACKED (pattern);
- TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
+ SET_TYPE_ALIGN (type, TYPE_ALIGN (pattern));
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (pattern);
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
if (ANON_AGGR_TYPE_P (pattern))
template <class U> friend class T::C;
otherwise. */
+ /* Bump processing_template_decl in case this is something like
+ template <class T> friend struct A<T>::B. */
+ ++processing_template_decl;
friend_type = tsubst (friend_type, args,
tf_warning_or_error, NULL_TREE);
- /* Bump processing_template_decl for correct
- dependent_type_p calculation. */
- ++processing_template_decl;
if (dependent_type_p (friend_type))
adjust_processing_template_decl = true;
--processing_template_decl;
sequence, the value of the expression is as follows; the program is
ill-formed if the operator is not listed in this table.
- * 1
- + 0
- & -1
- | 0
&& true
|| false
, void() */
if (!FOLD_EXPR_MODIFY_P (t))
switch (code)
{
- case MULT_EXPR:
- return integer_one_node;
- case PLUS_EXPR:
- return integer_zero_node;
- case BIT_AND_EXPR:
- return integer_minus_one_node;
- case BIT_IOR_EXPR:
- return integer_zero_node;
case TRUTH_ANDIF_EXPR:
return boolean_true_node;
case TRUTH_ORIF_EXPR:
/* We can't substitute for this parameter pack. We use a flag as
well as the missing_level counter because function parameter
packs don't have a level. */
+ gcc_assert (processing_template_decl);
unsubstituted_packs = true;
}
}
/* For each argument in each argument pack, substitute into the
pattern. */
result = make_tree_vec (len);
+ tree elem_args = copy_template_args (args);
for (i = 0; i < len; ++i)
{
t = gen_elem_of_pack_expansion_instantiation (pattern, packs,
i,
- args, complain,
+ elem_args, complain,
in_decl);
TREE_VEC_ELT (result, i) = t;
if (t == error_mark_node)
return patparm;
}
+/* Make an argument pack out of the TREE_VEC VEC. */
+
+static tree
+make_argument_pack (tree vec)
+{
+ tree pack;
+ tree elt = TREE_VEC_ELT (vec, 0);
+ if (TYPE_P (elt))
+ pack = cxx_make_type (TYPE_ARGUMENT_PACK);
+ else
+ {
+ pack = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_TYPE (pack) = TREE_TYPE (elt);
+ TREE_CONSTANT (pack) = 1;
+ }
+ SET_ARGUMENT_PACK_ARGS (pack, vec);
+ return pack;
+}
+
+/* Return an exact copy of template args T that can be modified
+ independently. */
+
+static tree
+copy_template_args (tree t)
+{
+ if (t == error_mark_node)
+ return t;
+
+ int len = TREE_VEC_LENGTH (t);
+ tree new_vec = make_tree_vec (len);
+
+ for (int i = 0; i < len; ++i)
+ {
+ tree elt = TREE_VEC_ELT (t, i);
+ if (elt && TREE_CODE (elt) == TREE_VEC)
+ elt = copy_template_args (elt);
+ TREE_VEC_ELT (new_vec, i) = elt;
+ }
+
+ NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_vec)
+ = NON_DEFAULT_TEMPLATE_ARGS_COUNT (t);
+
+ return new_vec;
+}
+
/* Substitute ARGS into the vector or list of template arguments T. */
static tree
if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
{
tree spec;
- bool dependent_p;
- /* If T is not dependent, just return it. We have to
- increment PROCESSING_TEMPLATE_DECL because
- value_dependent_expression_p assumes that nothing is
- dependent when PROCESSING_TEMPLATE_DECL is zero. */
- ++processing_template_decl;
- dependent_p = value_dependent_expression_p (t);
- --processing_template_decl;
- if (!dependent_p)
+ /* If T is not dependent, just return it. */
+ if (!uses_template_parms (DECL_TI_ARGS (t)))
RETURN (t);
/* Calculate the most general template of which R is a
/* The initializer must not be expanded until it is required;
see [temp.inst]. */
DECL_INITIAL (r) = NULL_TREE;
+ if (VAR_P (r))
+ DECL_MODE (r) = VOIDmode;
if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
SET_DECL_RTL (r, NULL);
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
if (TYPE_USER_ALIGN (t))
{
- TYPE_ALIGN (r) = TYPE_ALIGN (t);
+ SET_TYPE_ALIGN (r, TYPE_ALIGN (t));
TYPE_USER_ALIGN (r) = 1;
}
name = mangle_conv_op_name_for_type (optype);
baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
if (!baselink)
- return error_mark_node;
+ {
+ if (constructor_name_p (name, qualifying_scope))
+ {
+ if (complain & tf_error)
+ error ("cannot call constructor %<%T::%D%> directly",
+ qualifying_scope, name);
+ }
+ return error_mark_node;
+ }
/* If lookup found a single function, mark it as used at this
point. (If it lookup found multiple functions the one selected
/* Add back the template arguments, if present. */
if (BASELINK_P (baselink) && template_id_p)
BASELINK_FUNCTIONS (baselink)
- = build_nt (TEMPLATE_ID_EXPR,
- BASELINK_FUNCTIONS (baselink),
- template_args);
+ = build2 (TEMPLATE_ID_EXPR,
+ unknown_type_node,
+ BASELINK_FUNCTIONS (baselink),
+ template_args);
/* Update the conversion operator type. */
BASELINK_OPTYPE (baselink) = optype;
if (r == NULL_TREE)
{
- /* We get here for a use of 'this' in an NSDMI. */
+ /* We get here for a use of 'this' in an NSDMI as part of a
+ constructor call or as part of an aggregate initialization. */
if (DECL_NAME (t) == this_identifier
- && current_function_decl
- && DECL_CONSTRUCTOR_P (current_function_decl))
+ && ((current_function_decl
+ && DECL_CONSTRUCTOR_P (current_function_decl))
+ || (current_class_ref
+ && TREE_CODE (current_class_ref) == PLACEHOLDER_EXPR)))
return current_class_ptr;
/* This can happen for a parameter name used later in a function
}
case SIZEOF_EXPR:
- if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+ if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+ || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
{
tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ if (PACK_EXPANSION_P (op))
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+ else
+ expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op),
+ args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
return error_mark_node;
else if (PACK_EXPANSION_P (expanded)
|| (TREE_CODE (expanded) == TREE_VEC
- && len > 0
- && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+ && pack_expansion_args_count (expanded)))
+
{
- if (TREE_CODE (expanded) == TREE_VEC)
- expanded = TREE_VEC_ELT (expanded, len - 1);
+ if (PACK_EXPANSION_P (expanded))
+ /* OK. */;
+ else if (TREE_VEC_LENGTH (expanded) == 1)
+ expanded = TREE_VEC_ELT (expanded, 0);
else
- PACK_EXPANSION_SIZEOF_P (expanded) = true;
+ expanded = make_argument_pack (expanded);
if (TYPE_P (expanded))
return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
-tsubst_omp_clauses (tree clauses, bool declare_simd, bool allow_fields,
+tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
tree args, tsubst_flags_t complain, tree in_decl)
{
tree new_clauses = NULL_TREE, nc, oc;
default:
gcc_unreachable ();
}
- if (allow_fields)
+ if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP)
switch (OMP_CLAUSE_CODE (nc))
{
case OMP_CLAUSE_SHARED:
}
new_clauses = nreverse (new_clauses);
- if (!declare_simd)
+ if (ort != C_ORT_OMP_DECLARE_SIMD)
{
- new_clauses = finish_omp_clauses (new_clauses, allow_fields);
+ new_clauses = finish_omp_clauses (new_clauses, ort);
if (linear_no_step)
for (nc = new_clauses; nc; nc = OMP_CLAUSE_CHAIN (nc))
if (nc == linear_no_step)
{
tree c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (c) = decl;
- c = finish_omp_clauses (c, true);
+ c = finish_omp_clauses (c, C_ORT_OMP);
if (c)
{
OMP_CLAUSE_CHAIN (c) = *clauses;
{
tree scope = USING_DECL_SCOPE (decl);
tree name = DECL_NAME (decl);
- tree decl;
scope = tsubst (scope, args, complain, in_decl);
decl = lookup_qualified_name (scope, name,
case OACC_KERNELS:
case OACC_PARALLEL:
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, false, args, complain,
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_ACC, args, complain,
in_decl);
stmt = begin_omp_parallel ();
RECUR (OMP_BODY (t));
case OMP_PARALLEL:
r = push_omp_privatization_clauses (OMP_PARALLEL_COMBINED (t));
- tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false, true,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), C_ORT_OMP, args,
+ complain, in_decl);
if (OMP_PARALLEL_COMBINED (t))
omp_parallel_combined_clauses = &tmp;
stmt = begin_omp_parallel ();
case OMP_TASK:
r = push_omp_privatization_clauses (false);
- tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false, true,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), C_ORT_OMP, args,
+ complain, in_decl);
stmt = begin_omp_task ();
RECUR (OMP_TASK_BODY (t));
finish_omp_task (tmp, stmt);
tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE;
tree orig_declv = NULL_TREE;
tree incrv = NULL_TREE;
+ enum c_omp_region_type ort = C_ORT_OMP;
int i;
+ if (TREE_CODE (t) == CILK_SIMD || TREE_CODE (t) == CILK_FOR)
+ ort = C_ORT_CILK;
+ else if (TREE_CODE (t) == OACC_LOOP)
+ ort = C_ORT_ACC;
+
r = push_omp_privatization_clauses (OMP_FOR_INIT (t) == NULL_TREE);
- clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
- TREE_CODE (t) != OACC_LOOP,
- args, complain, in_decl);
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), ort, args, complain,
+ in_decl);
if (OMP_FOR_INIT (t) != NULL_TREE)
{
declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
case OMP_CRITICAL:
r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
&& OMP_TEAMS_COMBINED (t));
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, true,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain,
+ in_decl);
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt);
case OACC_DATA:
case OMP_TARGET_DATA:
case OMP_TARGET:
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
- TREE_CODE (t) != OACC_DATA,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), (TREE_CODE (t) == OACC_DATA)
+ ? C_ORT_ACC : C_ORT_OMP, args, complain,
+ in_decl);
keep_next_level (true);
stmt = begin_omp_structured_block ();
case OACC_DECLARE:
t = copy_node (t);
- tmp = tsubst_omp_clauses (OACC_DECLARE_CLAUSES (t), false, false,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OACC_DECLARE_CLAUSES (t), C_ORT_ACC, args,
+ complain, in_decl);
OACC_DECLARE_CLAUSES (t) = tmp;
add_stmt (t);
break;
case OMP_TARGET_UPDATE:
case OMP_TARGET_ENTER_DATA:
case OMP_TARGET_EXIT_DATA:
- tmp = tsubst_omp_clauses (OMP_STANDALONE_CLAUSES (t), false, true,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_STANDALONE_CLAUSES (t), C_ORT_OMP, args,
+ complain, in_decl);
t = copy_node (t);
OMP_STANDALONE_CLAUSES (t) = tmp;
add_stmt (t);
case OACC_ENTER_DATA:
case OACC_EXIT_DATA:
case OACC_UPDATE:
- tmp = tsubst_omp_clauses (OMP_STANDALONE_CLAUSES (t), false, false,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_STANDALONE_CLAUSES (t), C_ORT_ACC, args,
+ complain, in_decl);
t = copy_node (t);
OMP_STANDALONE_CLAUSES (t) = tmp;
add_stmt (t);
break;
case OMP_ORDERED:
- tmp = tsubst_omp_clauses (OMP_ORDERED_CLAUSES (t), false, true,
- args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_ORDERED_CLAUSES (t), C_ORT_OMP, args,
+ complain, in_decl);
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt);
else
r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR,
complain|decltype_flag);
+
+ if (TREE_CODE (r) == INDIRECT_REF)
+ REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+
RETURN (r);
}
length, stride, TREE_TYPE (op1)));
}
case SIZEOF_EXPR:
- if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+ if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+ || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
RETURN (tsubst_copy (t, args, complain, in_decl));
/* Fall through */
else
gcc_unreachable ();
LAMBDA_EXPR_EXTRA_SCOPE (r) = scope;
- LAMBDA_EXPR_RETURN_TYPE (r)
- = tsubst (LAMBDA_EXPR_RETURN_TYPE (t), args, complain, in_decl);
gcc_assert (LAMBDA_EXPR_THIS_CAPTURE (t) == NULL_TREE
&& LAMBDA_EXPR_PENDING_PROXIES (t) == NULL);
declaration of the op() for later calls to lambda_function. */
complete_type (type);
+ if (tree fn = lambda_function (type))
+ LAMBDA_EXPR_RETURN_TYPE (r) = TREE_TYPE (TREE_TYPE (fn));
+
LAMBDA_EXPR_THIS_CAPTURE (r) = NULL_TREE;
insert_pending_capture_proxies ();
/* Check to see if we already have this specialization. */
gen_tmpl = most_general_template (tmpl);
- if (tmpl != gen_tmpl)
- /* The TMPL is a partial instantiation. To get a full set of
- arguments we must add the arguments used to perform the
- partial instantiation. */
- targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
- targ_ptr);
+ if (TMPL_ARGS_DEPTH (targ_ptr)
+ < TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl)))
+ /* targ_ptr only has the innermost template args, so add the outer ones
+ from tmpl, which could be either a partial instantiation or gen_tmpl (in
+ the case of a non-dependent call within a template definition). */
+ targ_ptr = (add_outermost_template_args
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl)),
+ targ_ptr));
/* It would be nice to avoid hashing here and then again in tsubst_decl,
but it doesn't seem to be on the hot path. */
if (TREE_CODE (arg1) == TYPE_PACK_EXPANSION)
{
- int i, len2 = list_length (args2);
+ int i, len2 = remaining_arguments (args2);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len2);
tree ta = args2;
}
else if (TREE_CODE (arg2) == TYPE_PACK_EXPANSION)
{
- int i, len1 = list_length (args1);
+ int i, len1 = remaining_arguments (args1);
tree parmvec = make_tree_vec (1);
tree argvec = make_tree_vec (len1);
tree ta = args1;
if (TREE_CODE (d) == FUNCTION_DECL)
{
deleted_p = DECL_DELETED_FN (code_pattern);
- pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE
+ pattern_defined = ((DECL_SAVED_TREE (code_pattern) != NULL_TREE
+ && DECL_INITIAL (code_pattern) != error_mark_node)
|| DECL_DEFAULTED_OUTSIDE_CLASS_P (code_pattern)
|| deleted_p);
}
if (enter_context)
pop_nested_class ();
- if (variable_template_p (td))
+ if (variable_template_p (gen_tmpl))
note_variable_template_instantiation (d);
}
else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern))
switch (TREE_CODE (expression))
{
+ case BASELINK:
+ /* A dependent member function of the current instantiation. */
+ return dependent_type_p (BINFO_TYPE (BASELINK_BINFO (expression)));
+
+ case FUNCTION_DECL:
+ /* A dependent member function of the current instantiation. */
+ if (DECL_CLASS_SCOPE_P (expression)
+ && dependent_type_p (DECL_CONTEXT (expression)))
+ return true;
+ break;
+
case IDENTIFIER_NODE:
/* A name that has not been looked up -- must be dependent. */
return true;
&& (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
/* cp_finish_decl doesn't fold reference initializers. */
|| TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
+ || type_dependent_expression_p (DECL_INITIAL (expression))
|| value_dependent_expression_p (DECL_INITIAL (expression))))
return true;
return false;
return true;
else if (TYPE_P (expression))
return dependent_type_p (expression);
- return instantiation_dependent_expression_p (expression);
+ return instantiation_dependent_uneval_expression_p (expression);
case AT_ENCODE_EXPR:
/* An 'encode' expression is value-dependent if the operand is
case NOEXCEPT_EXPR:
expression = TREE_OPERAND (expression, 0);
- return instantiation_dependent_expression_p (expression);
+ return instantiation_dependent_uneval_expression_p (expression);
case SCOPE_REF:
/* All instantiation-dependent expressions should also be considered
case CALL_EXPR:
{
+ if (value_dependent_expression_p (CALL_EXPR_FN (expression)))
+ return true;
tree fn = get_callee_fndecl (expression);
int i, nargs;
- if (!fn && value_dependent_expression_p (CALL_EXPR_FN (expression)))
- return true;
nargs = call_expr_nargs (expression);
for (i = 0; i < nargs; ++i)
{
|| dependent_scope_p (scope));
}
- /* A function template specialization is type-dependent if it has any
- dependent template arguments. */
- if (TREE_CODE (expression) == FUNCTION_DECL
- && DECL_LANG_SPECIFIC (expression)
- && DECL_TEMPLATE_INFO (expression))
- return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
-
if (TREE_CODE (expression) == TEMPLATE_DECL
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
return false;
&& DECL_INITIAL (expression))
return true;
- /* A variable template specialization is type-dependent if it has any
- dependent template arguments. */
- if (VAR_P (expression)
+ /* A function or variable template-id is type-dependent if it has any
+ dependent template arguments. Note that we only consider the innermost
+ template arguments here, since those are the ones that come from the
+ template-id; the template arguments for the enclosing class do not make it
+ type-dependent, they only make a member function value-dependent. */
+ if (VAR_OR_FUNCTION_DECL_P (expression)
&& DECL_LANG_SPECIFIC (expression)
&& DECL_TEMPLATE_INFO (expression)
- && variable_template_p (DECL_TI_TEMPLATE (expression)))
- return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
+ && (any_dependent_template_arguments_p
+ (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
+ return true;
/* Always dependent, on the number of arguments if nothing else. */
if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
return (dependent_type_p (TREE_TYPE (expression)));
}
+/* [temp.dep.expr]/5: A class member access expression (5.2.5) is
+ type-dependent if the expression refers to a member of the current
+ instantiation and the type of the referenced member is dependent, or the
+ class member access expression refers to a member of an unknown
+ specialization.
+
+ This function returns true if the OBJECT in such a class member access
+ expression is of an unknown specialization. */
+
+bool
+type_dependent_object_expression_p (tree object)
+{
+ tree scope = TREE_TYPE (object);
+ return (!scope || dependent_scope_p (scope));
+}
+
/* walk_tree callback function for instantiation_dependent_expression_p,
below. Returns non-zero if a dependent subexpression is found. */
case TREE_VEC:
return NULL_TREE;
- case VAR_DECL:
- case CONST_DECL:
- /* A constant with a dependent initializer is dependent. */
- if (value_dependent_expression_p (*tp))
- return *tp;
- break;
-
case TEMPLATE_PARM_INDEX:
return *tp;
break;
}
- case TRAIT_EXPR:
- if (value_dependent_expression_p (*tp))
- return *tp;
- *walk_subtrees = false;
- return NULL_TREE;
-
case COMPONENT_REF:
if (identifier_p (TREE_OPERAND (*tp, 1)))
/* In a template, finish_class_member_access_expr creates a
"An expression is instantiation-dependent if it is type-dependent
or value-dependent, or it has a subexpression that is type-dependent
- or value-dependent." */
+ or value-dependent."
+
+ Except don't actually check value-dependence for unevaluated expressions,
+ because in sizeof(i) we don't care about the value of i. Checking
+ type-dependence will in turn check value-dependence of array bounds/template
+ arguments as needed. */
bool
-instantiation_dependent_expression_p (tree expression)
+instantiation_dependent_uneval_expression_p (tree expression)
{
tree result;
return result != NULL_TREE;
}
+/* As above, but also check value-dependence of the expression as a whole. */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+ return (instantiation_dependent_uneval_expression_p (expression)
+ || value_dependent_expression_p (expression));
+}
+
/* Like type_dependent_expression_p, but it also works while not processing
a template definition, i.e. during substitution or mangling. */
if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
arg = ARGUMENT_PACK_SELECT_ARG (arg);
- if (TREE_CODE (arg) == TEMPLATE_DECL
- || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- return dependent_template_p (arg);
+ if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+ return true;
+ if (TREE_CODE (arg) == TEMPLATE_DECL)
+ {
+ if (DECL_TEMPLATE_PARM_P (arg))
+ return true;
+ /* A member template of a dependent class is not necessarily
+ type-dependent, but it is a dependent template argument because it
+ will be a member of an unknown specialization to that template. */
+ tree scope = CP_DECL_CONTEXT (arg);
+ return TYPE_P (scope) && dependent_type_p (scope);
+ }
else if (ARGUMENT_PACK_P (arg))
{
tree args = ARGUMENT_PACK_ARGS (arg);
return false;
}
-/* Returns TRUE if the template TMPL is dependent. */
+/* Returns TRUE if the template TMPL is type-dependent. */
bool
dependent_template_p (tree tmpl)
/* So are names that have not been looked up. */
if (TREE_CODE (tmpl) == SCOPE_REF || identifier_p (tmpl))
return true;
- /* So are member templates of dependent classes. */
- if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
- return dependent_type_p (DECL_CONTEXT (tmpl));
return false;
}
{
/* Ill-formed programs can cause infinite recursion here, so we
must catch that. */
- TYPENAME_IS_RESOLVING_P (type) = 1;
+ TYPENAME_IS_RESOLVING_P (result) = 1;
result = resolve_typename_type (result, only_current_p);
- TYPENAME_IS_RESOLVING_P (type) = 0;
+ TYPENAME_IS_RESOLVING_P (result) = 0;
}
/* Qualify the resulting type. */
/* When checking, try to get a constant value for all non-dependent
expressions in order to expose bugs in *_dependent_expression_p
- and constexpr. */
- if (flag_checking && cxx_dialect >= cxx11
+ and constexpr. This can affect code generation, see PR70704, so
+ only do this for -fchecking=2. */
+ if (flag_checking > 1
+ && cxx_dialect >= cxx11
/* Don't do this during nsdmi parsing as it can lead to
unexpected recursive instantiations. */
&& !parsing_nsdmi ())