aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c91
1 files changed, 68 insertions, 23 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 59543ca0dfa..28c295695e4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -161,6 +161,7 @@ static int coerce_template_template_parms PROTO((tree, tree, int,
static tree determine_specialization PROTO((tree, tree, tree *, int));
static int template_args_equal PROTO((tree, tree));
static void print_template_context PROTO((int));
+static int has_pvbases_p PROTO((tree, tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -2210,12 +2211,17 @@ check_default_tmpl_args (decl, parms, is_primary, is_partial)
if (current_class_type
&& !TYPE_BEING_DEFINED (current_class_type)
- && DECL_REAL_CONTEXT (decl) == current_class_type
&& DECL_LANG_SPECIFIC (decl)
- && DECL_DEFINED_IN_CLASS_P (decl))
+ /* If this is either a friend defined in the scope of the class
+ or a member function. */
+ && DECL_CLASS_CONTEXT (decl) == current_class_type
+ /* And, if it was a member function, it really was defined in
+ the scope of the class. */
+ && (!DECL_FUNCTION_MEMBER_P (decl) || DECL_DEFINED_IN_CLASS_P (decl)))
/* We already checked these parameters when the template was
- declared, so there's no need to do it again now. This is an
- inline member function definition. */
+ declared, so there's no need to do it again now. This function
+ was defined in class scope, but we're processing it's body now
+ that the class is complete. */
return;
if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
@@ -2781,18 +2787,14 @@ convert_nontype_argument (type, expr)
applied. */
e = perform_qualification_conversions (type, expr);
if (TREE_CODE (e) == NOP_EXPR)
- {
- /* The call to perform_qualification_conversions will
- insert a NOP_EXPR over EXPR to do express
- conversion, if necessary. But, that will confuse
- us if we use this (converted) template parameter to
- instantiate another template; then the thing will
- not look like a valid template argument. So, just
- make a new constant, of the appropriate type. */
- e = make_node (PTRMEM_CST);
- TREE_TYPE (e) = type;
- PTRMEM_CST_MEMBER (e) = PTRMEM_CST_MEMBER (expr);
- }
+ /* The call to perform_qualification_conversions will
+ insert a NOP_EXPR over EXPR to do express conversion,
+ if necessary. But, that will confuse us if we use
+ this (converted) template parameter to instantiate
+ another template; then the thing will not look like a
+ valid template argument. So, just make a new
+ constant, of the appropriate type. */
+ e = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
return e;
}
else if (TREE_CODE (type_pointed_to) == FUNCTION_TYPE)
@@ -3573,6 +3575,7 @@ maybe_get_template_decl_from_type_decl (decl)
return (decl != NULL_TREE
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_ARTIFICIAL (decl)
+ && CLASS_TYPE_P (TREE_TYPE (decl))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl)))
? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl;
}
@@ -4683,6 +4686,23 @@ tsubst_friend_class (friend_tmpl, args)
return friend_type;
}
+static int
+has_pvbases_p (t, pattern)
+ tree t, pattern;
+{
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (t))
+ return 0;
+
+ if (TYPE_USES_PVBASES (pattern))
+ return 1;
+
+ for (t = CLASSTYPE_VBASECLASSES (t); t; t = TREE_CHAIN (t))
+ if (TYPE_VIRTUAL_P (BINFO_TYPE (t)))
+ return 1;
+
+ return 0;
+}
+
tree
instantiate_class_template (type)
tree type;
@@ -5033,6 +5053,13 @@ instantiate_class_template (type)
}
}
+ /* After we have calculated the bases, we can now compute whether we
+ have polymorphic vbases. This needs to happen before we
+ instantiate the methods, because the constructors may take
+ additional arguments. */
+ if (flag_vtable_thunks >= 2)
+ TYPE_USES_PVBASES (type) = has_pvbases_p (type, pattern);
+
/* Set up the list (TYPE_METHODS) and vector (CLASSTYPE_METHOD_VEC)
for this instantiation. */
for (t = TYPE_METHODS (pattern); t; t = TREE_CHAIN (t))
@@ -5714,9 +5741,17 @@ tsubst_decl (t, args, type, in_decl)
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
+
+ if (DECL_CONSTRUCTOR_P (r) || DECL_DESTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+
/* Set the mangled name for R. */
if (DECL_DESTRUCTOR_P (t))
- DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
+ DECL_ASSEMBLER_NAME (r) =
+ build_destructor_name (ctx, DECL_DESTRUCTOR_FOR_PVBASE_P (r));
else
{
/* Instantiations of template functions must be mangled
@@ -5759,11 +5794,14 @@ tsubst_decl (t, args, type, in_decl)
in_decl);
}
+#if 0
+ /* This has now moved further up. */
if (DECL_CONSTRUCTOR_P (r))
{
maybe_retrofit_in_chrg (r);
grok_ctor_properties (ctx, r);
}
+#endif
if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
@@ -6128,6 +6166,11 @@ tsubst (t, args, complain, in_decl)
if (max == error_mark_node)
return error_mark_node;
+ /* See if we can reduce this expression to something simpler. */
+ max = maybe_fold_nontype_arg (max);
+ if (!processing_template_decl && TREE_READONLY_DECL_P (max))
+ max = decl_constant_value (max);
+
if (processing_template_decl
/* When providing explicit arguments to a template
function, but leaving some arguments for subsequent
@@ -6540,6 +6583,8 @@ tsubst (t, args, complain, in_decl)
}
f = make_typename_type (ctx, f);
+ if (f == error_mark_node)
+ return f;
return cp_build_qualified_type (f,
CP_TYPE_QUALS (f)
| CP_TYPE_QUALS (t));
@@ -8909,8 +8954,8 @@ do_decl_instantiation (declspecs, declarator, storage)
No program shall both explicitly instantiate and explicitly
specialize a template. */
- cp_error ("explicit instantiation of `%#D' after", result);
- cp_error_at ("explicit specialization here", result);
+ cp_pedwarn ("explicit instantiation of `%#D' after", result);
+ cp_pedwarn_at ("explicit specialization here", result);
return;
}
else if (DECL_EXPLICIT_INSTANTIATION (result))
@@ -8923,8 +8968,8 @@ do_decl_instantiation (declspecs, declarator, storage)
We check DECL_INTERFACE_KNOWN so as not to complain when the
first instantiation was `extern' and the second is not, and
EXTERN_P for the opposite case. */
- if (DECL_INTERFACE_KNOWN (result) && !extern_p)
- cp_error ("duplicate explicit instantiation of `%#D'", result);
+ if (DECL_INTERFACE_KNOWN (result) && !extern_p && !flag_use_repository)
+ cp_pedwarn ("duplicate explicit instantiation of `%#D'", result);
/* If we've already instantiated the template, just return now. */
if (DECL_INTERFACE_KNOWN (result))
@@ -9051,8 +9096,8 @@ do_type_instantiation (t, storage)
If CLASSTYPE_INTERFACE_ONLY, then the first explicit
instantiation was `extern', and if EXTERN_P then the second
is. Both cases are OK. */
- if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p)
- cp_error ("duplicate explicit instantiation of `%#T'", t);
+ if (!CLASSTYPE_INTERFACE_ONLY (t) && !extern_p && !flag_use_repository)
+ cp_pedwarn ("duplicate explicit instantiation of `%#T'", t);
/* If we've already instantiated the template, just return now. */
if (!CLASSTYPE_INTERFACE_ONLY (t))