/* Add implicit 'typename' to types from template bases. lookup_field
will do this for us. If classval is actually from an enclosing
scope, lookup_nested_field will get it for us. */
- if (processing_template_decl
- && classval && TREE_CODE (classval) == TYPE_DECL
- && ! currently_open_class (DECL_CONTEXT (classval))
- && uses_template_parms (current_class_type)
- && ! DECL_ARTIFICIAL (classval))
+ else if (processing_template_decl
+ && classval && TREE_CODE (classval) == TYPE_DECL
+ && ! currently_open_class (DECL_CONTEXT (classval))
+ && uses_template_parms (current_class_type)
+ && ! DECL_ARTIFICIAL (classval))
classval = lookup_field (current_class_type, name, 0, 1);
/* yylex() calls this with -2, since we should never start digging for
else
val = unqualified_namespace_lookup (name, flags);
+ if (classval && TREE_CODE (val) == TYPE_DECL
+ && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE
+ && TREE_TYPE (TREE_TYPE (val)))
+ {
+ tree nsval = unqualified_namespace_lookup (name, flags);
+
+ if (val && nsval && TREE_CODE (nsval) == TYPE_DECL)
+ {
+ static int explained;
+ cp_warning ("namespace-scope type `%#D'", nsval);
+ cp_warning
+ (" is used instead of `%D' from dependent base class", val);
+ if (! explained)
+ {
+ explained = 1;
+ cp_warning (" (use `typename %D' if that's what you meant)",
+ val);
+ }
+ val = nsval;
+ }
+ }
+
done:
if (val)
{
}
}
+/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
+ because it (or one of the intermediate bases) depends on template parms. */
+
+static int
+dependent_base_p (binfo)
+ tree binfo;
+{
+ for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ if (binfo == current_class_type)
+ break;
+ if (uses_template_parms (TREE_TYPE (binfo)))
+ return 1;
+ }
+ return 0;
+}
+
/* Add the instance variables which this class contributed to the
current class binding contour. When a redefinition occurs, if the
redefinition is strictly within a single inheritance path, we just
tree type = BINFO_TYPE (binfo);
tree fields, *methods, *end;
tree method_vec;
+ int dummy = 0;
+
+ /* Only record types if we're a template base. */
+ if (processing_template_decl && type != current_class_type
+ && dependent_base_p (binfo))
+ dummy = 1;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
+ if (dummy && TREE_CODE (fields) != TYPE_DECL)
+ continue;
+
/* Unmark so that if we are in a constructor, and then find that
this field was initialized by a base initializer,
we can emit an error message. */
}
method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec)
+ if (method_vec && ! dummy)
{
/* Farm out constructors and destructors. */
methods = &TREE_VEC_ELT (method_vec, 2);
tree type = BINFO_TYPE (binfo);
tree method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec != 0)
+ if (processing_template_decl && type != current_class_type
+ && dependent_base_p (binfo))
+ /* We only record types if we're a template base. */;
+ else if (method_vec != 0)
{
/* Farm out constructors and destructors. */
tree *methods = &TREE_VEC_ELT (method_vec, 2);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl;
- tree instance;
+ tree instance, basetype;
tree instance_ptr = *instance_ptrptr;
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
- /* Promoting idx before saving it improves performance on RISC
- targets. Without promoting, the first compare used
- load-with-sign-extend, while the second used normal load then
- shift to sign-extend. An optimizer flaw, perhaps, but it's easier
- to make this change. */
- idx = save_expr (default_conversion
- (build_component_ref (function,
- index_identifier,
- NULL_TREE, 0)));
- e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
delta = cp_convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier,
NULL_TREE, 0));
- delta2 = DELTA2_FROM_PTRMEMFUNC (function);
-
- /* Convert down to the right base, before using the instance. */
- instance
- = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
- instance_ptr);
- if (instance == error_mark_node && instance_ptr != error_mark_node)
- return instance;
-
- vtbl = convert_pointer_to (ptr_type_node, instance);
- vtbl
- = build (PLUS_EXPR,
- build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, cp_convert (ptrdiff_type_node, delta2));
- vtbl = build_indirect_ref (vtbl, NULL_PTR);
- aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
- idx,
- integer_one_node, 1));
- if (! flag_vtable_thunks)
- {
- aref = save_expr (aref);
-
- delta = build_binary_op
+ e3 = PFN_FROM_PTRMEMFUNC (function);
+
+ if (TYPE_SIZE (basetype) != NULL_TREE
+ && ! TYPE_VIRTUAL_P (basetype))
+ /* If basetype doesn't have virtual functions, don't emit code to
+ handle that case. */
+ e1 = e3;
+ else
+ {
+ /* Promoting idx before saving it improves performance on RISC
+ targets. Without promoting, the first compare used
+ load-with-sign-extend, while the second used normal load then
+ shift to sign-extend. An optimizer flaw, perhaps, but it's
+ easier to make this change. */
+ idx = save_expr (default_conversion
+ (build_component_ref (function,
+ index_identifier,
+ NULL_TREE, 0)));
+ e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
+
+ /* Convert down to the right base, before using the instance. */
+ instance = convert_pointer_to_real (basetype, instance_ptr);
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
+ return instance;
+
+ vtbl = convert_pointer_to (ptr_type_node, instance);
+ delta2 = DELTA2_FROM_PTRMEMFUNC (function);
+ vtbl = build
(PLUS_EXPR,
- build_conditional_expr (e1, build_component_ref (aref,
+ build_pointer_type (build_pointer_type (vtable_entry_type)),
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
+ vtbl = build_indirect_ref (vtbl, NULL_PTR);
+ aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
+ idx,
+ integer_one_node, 1));
+ if (! flag_vtable_thunks)
+ {
+ aref = save_expr (aref);
+
+ delta = build_binary_op
+ (PLUS_EXPR,
+ build_conditional_expr (e1,
+ build_component_ref (aref,
delta_identifier,
NULL_TREE, 0),
- integer_zero_node),
- delta, 1);
+ integer_zero_node),
+ delta, 1);
+ }
+
+ if (flag_vtable_thunks)
+ e2 = aref;
+ else
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+ TREE_TYPE (e2) = TREE_TYPE (e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ /* Make sure this doesn't get evaluated first inside one of the
+ branches of the COND_EXPR. */
+ if (TREE_CODE (instance_ptr) == SAVE_EXPR)
+ e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
+ instance_ptr, e1);
}
*instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
instance_ptr, delta);
- if (flag_vtable_thunks)
- e2 = aref;
- else
- e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
-
- e3 = PFN_FROM_PTRMEMFUNC (function);
- TREE_TYPE (e2) = TREE_TYPE (e3);
- e1 = build_conditional_expr (e1, e2, e3);
if (instance_ptr == error_mark_node
&& TREE_CODE (e1) != ADDR_EXPR
cp_error ("object missing in `%E'", function);
function = e1;
-
- /* Make sure this doesn't get evaluated first inside one of the
- branches of the COND_EXPR. */
- if (TREE_CODE (instance_ptr) == SAVE_EXPR)
- function = build (COMPOUND_EXPR, TREE_TYPE (function),
- instance_ptr, function);
}
return function;
}