aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.cc')
-rw-r--r--gcc/cp/pt.cc314
1 files changed, 233 insertions, 81 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7b296d1..3362a6f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -202,7 +202,6 @@ static tree for_each_template_parm_r (tree *, int *, void *);
static tree copy_default_args_to_explicit_spec_1 (tree, tree);
static void copy_default_args_to_explicit_spec (tree);
static bool invalid_nontype_parm_type_p (tree, tsubst_flags_t);
-static bool dependent_template_arg_p (tree);
static bool dependent_type_p_r (tree);
static tree tsubst_stmt (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t, bool = true);
@@ -10052,15 +10051,20 @@ tsubst_entering_scope (tree t, tree args, tsubst_flags_t complain, tree in_decl)
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
+ If D1 is an identifier and CONTEXT is non-NULL, then the lookup is
+ carried out in CONTEXT. Currently, only namespaces are supported for
+ CONTEXT.
+
+ If D1 is an identifier and CONTEXT is NULL, the lookup is performed
+ in the innermost non-namespace binding.
+
+ Otherwise CONTEXT is ignored and no lookup is carried out.
+
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate.
Issue error and warning messages under control of COMPLAIN.
- If the template class is really a local class in a template
- function, then the FUNCTION_CONTEXT is the function in which it is
- being instantiated.
-
??? Note that this function is currently called *twice* for each
template-id: the first time from the parser, while creating the
incomplete type (finish_template_type), and the second type during the
@@ -10079,20 +10083,23 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context,
spec_entry **slot;
spec_entry *entry;
- if (identifier_p (d1))
+ if (identifier_p (d1) && context)
+ {
+ gcc_checking_assert (TREE_CODE (context) == NAMESPACE_DECL);
+ push_decl_namespace (context);
+ templ = lookup_name (d1, LOOK_where::NAMESPACE, LOOK_want::NORMAL);
+ pop_decl_namespace ();
+ }
+ else if (identifier_p (d1))
{
tree value = innermost_non_namespace_value (d1);
if (value && DECL_TEMPLATE_TEMPLATE_PARM_P (value))
templ = value;
else
- {
- if (context)
- push_decl_namespace (context);
+ {
templ = lookup_name (d1);
templ = maybe_get_template_decl_from_type_decl (templ);
- if (context)
- pop_decl_namespace ();
- }
+ }
}
else if (TREE_CODE (d1) == TYPE_DECL && MAYBE_CLASS_TYPE_P (TREE_TYPE (d1)))
{
@@ -11378,6 +11385,7 @@ limit_bad_template_recursion (tree decl)
static int tinst_depth;
extern int max_tinst_depth;
int depth_reached;
+int tinst_dump_id;
static GTY(()) struct tinst_level *last_error_tinst_level;
@@ -11430,6 +11438,40 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
set_refcount_ptr (new_level->next, current_tinst_level);
set_refcount_ptr (current_tinst_level, new_level);
+ if (cxx_dump_pretty_printer pp {tinst_dump_id})
+ {
+#if __GNUC__ >= 10
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+ bool list_p = new_level->list_p ();
+ if (list_p && !pp.has_flag (TDF_DETAILS))
+ /* Skip non-instantiations unless -details. */;
+ else
+ {
+ if (tinst_depth == 0)
+ pp_newline (&pp);
+ if (loc && pp.has_flag (TDF_LINENO))
+ {
+ for (int i = 0; i < tinst_depth; ++i)
+ pp_space (&pp);
+ const expanded_location el = expand_location (loc);
+ pp_printf (&pp, "%s:%d:%d", el.file, el.line, el.column);
+ pp_newline (&pp);
+ }
+ for (int i = 0; i < tinst_depth; ++i)
+ pp_space (&pp);
+ if (list_p)
+ pp_printf (&pp, "S %S", new_level->get_node ());
+ else
+ pp_printf (&pp, "I %D", tldcl);
+ pp_newline (&pp);
+ }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic pop
+#endif
+ }
+
++tinst_depth;
if (GATHER_STATISTICS && (tinst_depth > depth_reached))
depth_reached = tinst_depth;
@@ -11481,6 +11523,20 @@ pop_tinst_level (void)
--tinst_depth;
}
+/* True if the instantiation represented by LEVEL is complete. */
+
+static bool
+tinst_complete_p (struct tinst_level *level)
+{
+ gcc_assert (!level->list_p ());
+ tree node = level->get_node ();
+ if (TYPE_P (node))
+ return COMPLETE_TYPE_P (node);
+ else
+ return (DECL_TEMPLATE_INSTANTIATED (node)
+ || DECL_TEMPLATE_SPECIALIZATION (node));
+}
+
/* We're instantiating a deferred template; restore the template
instantiation context in which the instantiation was requested, which
is one step out from LEVEL. Return the corresponding DECL or TYPE. */
@@ -11499,6 +11555,38 @@ reopen_tinst_level (struct tinst_level *level)
if (current_tinst_level && !current_tinst_level->had_errors)
current_tinst_level->errors = errorcount+sorrycount;
+ if (cxx_dump_pretty_printer pp {tinst_dump_id})
+ {
+#if __GNUC__ >= 10
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+ /* Dump the reopened instantiation context. */
+ t = current_tinst_level;
+ if (!pp.has_flag (TDF_DETAILS))
+ /* Skip non-instantiations unless -details. */
+ while (t && t->list_p ())
+ t = t->next;
+ if (t)
+ {
+ static tree last_ctx = NULL_TREE;
+ tree ctx = t->get_node ();
+ if (ctx != last_ctx)
+ {
+ last_ctx = ctx;
+ pp_newline (&pp);
+ if (t->list_p ())
+ pp_printf (&pp, "RS %S", ctx);
+ else
+ pp_printf (&pp, "RI %D", ctx);
+ pp_newline (&pp);
+ }
+ }
+#if __GNUC__ >= 10
+#pragma GCC diagnostic pop
+#endif
+ }
+
tree decl = level->maybe_get_node ();
if (decl && modules_p ())
{
@@ -14902,6 +14990,8 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
if (closure && DECL_IOBJ_MEMBER_FUNCTION_P (t))
parms = DECL_CHAIN (parms);
parms = tsubst (parms, args, complain, t);
+ if (parms == error_mark_node)
+ return error_mark_node;
for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = r;
if (closure && DECL_IOBJ_MEMBER_FUNCTION_P (t))
@@ -15474,6 +15564,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
/* We're dealing with a normal parameter. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node && !(complain & tf_error))
+ RETURN (error_mark_node);
+
type = type_decays_to (type);
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
@@ -15511,8 +15604,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
/* If cp_unevaluated_operand is set, we're just looking for a
single dummy parameter, so don't keep going. */
if (DECL_CHAIN (t) && !cp_unevaluated_operand)
- DECL_CHAIN (r) = tsubst (DECL_CHAIN (t), args,
- complain, DECL_CHAIN (t));
+ {
+ tree chain = tsubst (DECL_CHAIN (t), args,
+ complain, DECL_CHAIN (t));
+ if (chain == error_mark_node)
+ RETURN (error_mark_node);
+ DECL_CHAIN (r) = chain;
+ }
/* FIRST_R contains the start of the chain we've built. */
r = first_r;
@@ -15908,7 +16006,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
- if ((!local_p || TREE_STATIC (t)) && DECL_SECTION_NAME (t))
+ if ((!local_p || TREE_STATIC (t))
+ && !(flag_openmp && DECL_LANG_SPECIFIC (t)
+ && DECL_OMP_DECLARE_MAPPER_P (t))
+ && DECL_SECTION_NAME (t))
set_decl_section_name (r, t);
}
@@ -15960,6 +16061,13 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (r));
}
+ if (flag_openmp
+ && VAR_P (t)
+ && DECL_LANG_SPECIFIC (t)
+ && DECL_OMP_DECLARE_MAPPER_P (t)
+ && strchr (IDENTIFIER_POINTER (DECL_NAME (t)), '~') == NULL)
+ DECL_NAME (r) = omp_mapper_id (DECL_NAME (t), TREE_TYPE (r));
+
layout_decl (r, 0);
}
break;
@@ -17477,10 +17585,18 @@ tsubst_baselink (tree baselink, tree object_type,
if (!baselink)
{
- if ((complain & tf_error)
- && constructor_name_p (name, qualifying_scope))
- error ("cannot call constructor %<%T::%D%> directly",
- qualifying_scope, name);
+ if (complain & tf_error)
+ {
+ if (constructor_name_p (name, qualifying_scope))
+ error ("cannot call constructor %<%T::%D%> directly",
+ qualifying_scope, name);
+ else
+ /* Lookup succeeded at parse time, but failed during
+ instantiation; must be because we're trying to refer to it
+ while forming its declaration (c++/120204). */
+ error ("declaration of %<%T::%D%> depends on itself",
+ qualifying_scope, name);
+ }
return error_mark_node;
}
@@ -18224,8 +18340,10 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
}
new_clauses = nreverse (new_clauses);
- if (ort != C_ORT_OMP_DECLARE_SIMD)
+ if (ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_OMP_DECLARE_MAPPER)
{
+ if (ort == C_ORT_OMP_TARGET)
+ new_clauses = c_omp_instantiate_mappers (new_clauses);
new_clauses = finish_omp_clauses (new_clauses, ort);
if (linear_no_step)
for (nc = new_clauses; nc; nc = OMP_CLAUSE_CHAIN (nc))
@@ -18279,7 +18397,9 @@ tsubst_omp_context_selector (tree ctx, tree args, tsubst_flags_t complain,
}
}
- switch (omp_ts_map[OMP_TS_CODE (sel)].tp_type)
+ enum omp_tp_type property_kind
+ = omp_ts_map[OMP_TS_CODE (sel)].tp_type;
+ switch (property_kind)
{
case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR:
case OMP_TRAIT_PROPERTY_BOOL_EXPR:
@@ -18287,12 +18407,26 @@ tsubst_omp_context_selector (tree ctx, tree args, tsubst_flags_t complain,
args, complain, in_decl);
t = fold_non_dependent_expr (t);
if (!value_dependent_expression_p (t)
- && !type_dependent_expression_p (t)
- && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
- error_at (cp_expr_loc_or_input_loc (t),
- "property must be integer expression");
- else
- properties = make_trait_property (NULL_TREE, t, NULL_TREE);
+ && !type_dependent_expression_p (t))
+ {
+ if (property_kind == OMP_TRAIT_PROPERTY_BOOL_EXPR)
+ t = maybe_convert_cond (t);
+ else
+ {
+ t = convert_from_reference (t);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (cp_expr_loc_or_input_loc (t),
+ "property must be integer expression");
+ t = error_mark_node;
+ }
+ }
+ }
+ if (t != error_mark_node
+ && !processing_template_decl
+ && TREE_CODE (t) != CLEANUP_POINT_EXPR)
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ properties = make_trait_property (NULL_TREE, t, NULL_TREE);
break;
case OMP_TRAIT_PROPERTY_CLAUSE_LIST:
if (OMP_TS_CODE (sel) == OMP_TRAIT_CONSTRUCT_SIMD)
@@ -19945,6 +20079,22 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
}
+ case OMP_DECLARE_MAPPER:
+ {
+ t = copy_node (t);
+
+ tree decl = OMP_DECLARE_MAPPER_DECL (t);
+ decl = tsubst (decl, args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree clauses = OMP_DECLARE_MAPPER_CLAUSES (t);
+ clauses = tsubst_omp_clauses (clauses, C_ORT_OMP_DECLARE_MAPPER, args,
+ complain, in_decl);
+ TREE_TYPE (t) = type;
+ OMP_DECLARE_MAPPER_DECL (t) = decl;
+ OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ RETURN (t);
+ }
+
case TRANSACTION_EXPR:
{
int flags = 0;
@@ -21004,6 +21154,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
RETURN (build_omp_array_section (EXPR_LOCATION (t), op0, op1, op2));
}
+ case OMP_DECLARE_MAPPER:
+ {
+ t = copy_node (t);
+
+ tree decl = OMP_DECLARE_MAPPER_DECL (t);
+ DECL_OMP_DECLARE_MAPPER_P (decl) = 1;
+ decl = tsubst (decl, args, complain, in_decl);
+ tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ tree clauses = OMP_DECLARE_MAPPER_CLAUSES (t);
+ clauses = tsubst_omp_clauses (clauses, C_ORT_OMP_DECLARE_MAPPER, args,
+ complain, in_decl);
+ TREE_TYPE (t) = type;
+ OMP_DECLARE_MAPPER_DECL (t) = decl;
+ OMP_DECLARE_MAPPER_CLAUSES (t) = clauses;
+ RETURN (t);
+ }
+
case SIZEOF_EXPR:
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
@@ -23254,7 +23421,7 @@ fn_type_unification (tree fn,
conversions that we know are not going to induce template instantiation
(PR99599). */
if (strict == DEDUCE_CALL
- && incomplete
+ && incomplete && flag_concepts
&& check_non_deducible_conversions (parms, args, nargs, fn, strict, flags,
convs, explain_p,
/*noninst_only_p=*/true))
@@ -23501,9 +23668,13 @@ maybe_adjust_types_for_deduction (tree tparms,
return result;
}
-/* Return true if computing a conversion from FROM to TO might induce template
- instantiation. Conversely, if this predicate returns false then computing
- the conversion definitely won't induce template instantiation. */
+/* Return true if computing a conversion from FROM to TO might consider
+ user-defined conversions, which could lead to arbitrary template
+ instantiations (e.g. g++.dg/cpp2a/concepts-nondep1.C). If this predicate
+ returns false then computing the conversion definitely won't try UDCs.
+
+ Note that this restriction parallels LOOKUP_DEFAULTED for CWG1092, but in
+ this case we want the early filter to pass instead of fail. */
static bool
conversion_may_instantiate_p (tree to, tree from)
@@ -23511,45 +23682,23 @@ conversion_may_instantiate_p (tree to, tree from)
to = non_reference (to);
from = non_reference (from);
- bool ptr_conv_p = false;
- if (TYPE_PTR_P (to)
- && TYPE_PTR_P (from))
- {
- to = TREE_TYPE (to);
- from = TREE_TYPE (from);
- ptr_conv_p = true;
- }
-
- /* If one of the types is a not-yet-instantiated class template
- specialization, then computing the conversion might instantiate
- it in order to inspect bases, conversion functions and/or
- converting constructors. */
- if ((CLASS_TYPE_P (to)
- && !COMPLETE_TYPE_P (to)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (to))
- || (CLASS_TYPE_P (from)
- && !COMPLETE_TYPE_P (from)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (from)))
- return true;
-
- /* Converting from one pointer type to another, or between
- reference-related types, always yields a standard conversion. */
- if (ptr_conv_p || reference_related_p (to, from))
+ /* Converting between reference-related types is a standard conversion. */
+ if (reference_related_p (to, from))
return false;
/* Converting to a non-aggregate class type will consider its
user-declared constructors, which might induce instantiation. */
- if (CLASS_TYPE_P (to)
- && CLASSTYPE_NON_AGGREGATE (to))
+ if (CLASS_TYPE_P (complete_type (to))
+ && type_has_converting_constructor (to))
return true;
/* Similarly, converting from a class type will consider its conversion
functions. */
- if (CLASS_TYPE_P (from)
+ if (CLASS_TYPE_P (complete_type (from))
&& TYPE_HAS_CONVERSION (from))
return true;
- /* Otherwise, computing this conversion definitely won't induce
+ /* Otherwise, computing this conversion won't risk arbitrary
template instantiation. */
return false;
}
@@ -24455,7 +24604,8 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain)
}
if (good == 1)
{
- mark_used (goodfn);
+ if (!mark_used (goodfn, complain) && !(complain & tf_error))
+ return error_mark_node;
expr = goodfn;
if (baselink)
expr = build_baselink (BASELINK_BINFO (baselink),
@@ -25795,10 +25945,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
UNIFY_ALLOW_NONE, explain_p);
- else
- return unify_success (explain_p);
+ gcc_checking_assert (t == arg);
}
- else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
+
+ if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
return unify_type_mismatch (explain_p, parm, arg);
return unify_success (explain_p);
@@ -27387,6 +27537,10 @@ tree
template_for_substitution (tree decl)
{
tree tmpl = DECL_TI_TEMPLATE (decl);
+ if (VAR_P (decl))
+ if (tree partial = most_specialized_partial_spec (decl, tf_none))
+ if (partial != error_mark_node)
+ tmpl = TI_TEMPLATE (partial);
/* Set TMPL to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. This is not always the most general
@@ -27965,7 +28119,9 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
|| (external_p && VAR_P (d))
/* Handle here a deleted function too, avoid generating
its body (c++/61080). */
- || deleted_p)
+ || deleted_p
+ /* We need the initializer for an OpenMP declare mapper. */
+ || (VAR_P (d) && DECL_LANG_SPECIFIC (d) && DECL_OMP_DECLARE_MAPPER_P (d)))
{
/* The definition of the static data member is now required so
we must substitute the initializer. */
@@ -28078,14 +28234,16 @@ instantiate_pending_templates (int retries)
reconsider = 0;
while (*t)
{
- tree instantiation = reopen_tinst_level ((*t)->tinst);
- bool complete = false;
+ struct tinst_level *tinst = (*t)->tinst;
+ bool complete = tinst_complete_p (tinst);
- if (limit_bad_template_recursion (instantiation))
- /* Do nothing. */;
- else if (TYPE_P (instantiation))
+ if (!complete)
{
- if (!COMPLETE_TYPE_P (instantiation))
+ tree instantiation = reopen_tinst_level (tinst);
+
+ if (limit_bad_template_recursion (instantiation))
+ /* Do nothing. */;
+ else if (TYPE_P (instantiation))
{
instantiate_class_template (instantiation);
if (CLASSTYPE_TEMPLATE_INSTANTIATION (instantiation))
@@ -28102,13 +28260,7 @@ instantiate_pending_templates (int retries)
if (COMPLETE_TYPE_P (instantiation))
reconsider = 1;
}
-
- complete = COMPLETE_TYPE_P (instantiation);
- }
- else
- {
- if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
- && !DECL_TEMPLATE_INSTANTIATED (instantiation))
+ else
{
instantiation
= instantiate_decl (instantiation,
@@ -28118,8 +28270,10 @@ instantiate_pending_templates (int retries)
reconsider = 1;
}
- complete = (DECL_TEMPLATE_SPECIALIZATION (instantiation)
- || DECL_TEMPLATE_INSTANTIATED (instantiation));
+ complete = tinst_complete_p (tinst);
+
+ tinst_depth = 0;
+ set_refcount_ptr (current_tinst_level);
}
if (complete)
@@ -28136,8 +28290,6 @@ instantiate_pending_templates (int retries)
last = *t;
t = &(*t)->next;
}
- tinst_depth = 0;
- set_refcount_ptr (current_tinst_level);
}
last_pending_template = last;
}