/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ 1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
field = fields[i--];
while (i >= lo && DECL_NAME (fields[i]) == name);
if (TREE_CODE (field) != TYPE_DECL
- && !DECL_CLASS_TEMPLATE_P (field))
+ && !DECL_TYPE_TEMPLATE_P (field))
field = NULL_TREE;
}
else
field = fields[i++];
while (i < hi && DECL_NAME (fields[i]) == name);
}
+
+ if (field)
+ {
+ field = strip_using_decl (field);
+ if (is_overloaded_fn (field))
+ field = NULL_TREE;
+ }
+
return field;
}
}
#endif /* GATHER_STATISTICS */
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
+ tree decl = field;
+
#ifdef GATHER_STATISTICS
n_fields_searched++;
#endif /* GATHER_STATISTICS */
if (temp)
return temp;
}
- if (TREE_CODE (field) == USING_DECL)
+
+ if (TREE_CODE (decl) == USING_DECL
+ && DECL_NAME (decl) == name)
{
- /* We generally treat class-scope using-declarations as
- ARM-style access specifications, because support for the
- ISO semantics has not been implemented. So, in general,
- there's no reason to return a USING_DECL, and the rest of
- the compiler cannot handle that. Once the class is
- defined, USING_DECLs are purged from TYPE_FIELDS; see
- handle_using_decl. However, we make special efforts to
- make using-declarations in class templates and class
- template partial specializations work correctly. */
- if (!DECL_DEPENDENT_P (field))
+ decl = strip_using_decl (decl);
+ if (is_overloaded_fn (decl))
continue;
}
- if (DECL_NAME (field) == name
+ if (DECL_NAME (decl) == name
&& (!want_type
- || TREE_CODE (field) == TYPE_DECL
- || DECL_CLASS_TEMPLATE_P (field)))
- return field;
+ || TREE_CODE (decl) == TYPE_DECL
+ || DECL_TYPE_TEMPLATE_P (decl)))
+ return decl;
}
/* Not found. */
if (name == vptr_identifier)
at_function_scope_p (void)
{
tree cs = current_scope ();
- return cs && TREE_CODE (cs) == FUNCTION_DECL;
+ /* Also check cfun to make sure that we're really compiling
+ this function (as opposed to having set current_function_decl
+ for access checking or some such). */
+ return (cs && TREE_CODE (cs) == FUNCTION_DECL
+ && cfun && cfun->decl == current_function_decl);
}
/* Returns true if the innermost active scope is a class scope. */
member with the same name, and if there's a function and a type
with the same name, the type is hidden by the function. */
if (!lfi->want_type)
- {
- int idx = lookup_fnfields_1 (type, lfi->name);
- if (idx >= 0)
- nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
- }
+ nval = lookup_fnfields_slot (type, lfi->name);
if (!nval)
/* Look for a data member or type. */
/* If we're looking up a type (as with an elaborated type specifier)
we ignore all non-types we find. */
if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL
- && !DECL_CLASS_TEMPLATE_P (nval))
+ && !DECL_TYPE_TEMPLATE_P (nval))
{
if (lfi->name == TYPE_IDENTIFIER (type))
{
If nothing can be found return NULL_TREE and do not issue an error. */
tree
-lookup_member (tree xbasetype, tree name, int protect, bool want_type)
+lookup_member (tree xbasetype, tree name, int protect, bool want_type,
+ tsubst_flags_t complain)
{
tree rval, rval_binfo = NULL_TREE;
tree type = NULL_TREE, basetype_path = NULL_TREE;
const char *errstr = 0;
- if (name == error_mark_node)
+ if (name == error_mark_node
+ || xbasetype == NULL_TREE
+ || xbasetype == error_mark_node)
return NULL_TREE;
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
if (errstr && protect)
{
- error (errstr, name, type);
- if (lfi.ambiguous)
- print_candidates (lfi.ambiguous);
+ if (complain & tf_error)
+ {
+ error (errstr, name, type);
+ if (lfi.ambiguous)
+ print_candidates (lfi.ambiguous);
+ }
rval = error_mark_node;
}
tree
lookup_field (tree xbasetype, tree name, int protect, bool want_type)
{
- tree rval = lookup_member (xbasetype, name, protect, want_type);
+ tree rval = lookup_member (xbasetype, name, protect, want_type,
+ tf_warning_or_error);
/* Ignore functions, but propagate the ambiguity list. */
if (!error_operand_p (rval)
tree
lookup_fnfields (tree xbasetype, tree name, int protect)
{
- tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false);
+ tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false,
+ tf_warning_or_error);
/* Ignore non-functions, but propagate the ambiguity list. */
if (!error_operand_p (rval)
}
/* TYPE is a class type. Return the index of the fields within
- the method vector with name NAME, or -1 if no such field exists. */
+ the method vector with name NAME, or -1 if no such field exists.
+ Does not lazily declare implicitly-declared member functions. */
-int
-lookup_fnfields_1 (tree type, tree name)
+static int
+lookup_fnfields_idx_nolazy (tree type, tree name)
{
VEC(tree,gc) *method_vec;
tree fn;
if (!CLASS_TYPE_P (type))
return -1;
- if (COMPLETE_TYPE_P (type))
- {
- if ((name == ctor_identifier
- || name == base_ctor_identifier
- || name == complete_ctor_identifier))
- {
- if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
- lazily_declare_fn (sfk_constructor, type);
- if (CLASSTYPE_LAZY_COPY_CTOR (type))
- lazily_declare_fn (sfk_copy_constructor, type);
- if (CLASSTYPE_LAZY_MOVE_CTOR (type))
- lazily_declare_fn (sfk_move_constructor, type);
- }
- else if (name == ansi_assopname (NOP_EXPR))
- {
- if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
- lazily_declare_fn (sfk_copy_assignment, type);
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
- lazily_declare_fn (sfk_move_assignment, type);
- }
- else if ((name == dtor_identifier
- || name == base_dtor_identifier
- || name == complete_dtor_identifier
- || name == deleting_dtor_identifier)
- && CLASSTYPE_LAZY_DESTRUCTOR (type))
- lazily_declare_fn (sfk_destructor, type);
- }
-
method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
return -1;
}
+/* TYPE is a class type. Return the index of the fields within
+ the method vector with name NAME, or -1 if no such field exists. */
+
+int
+lookup_fnfields_1 (tree type, tree name)
+{
+ if (!CLASS_TYPE_P (type))
+ return -1;
+
+ if (COMPLETE_TYPE_P (type))
+ {
+ if ((name == ctor_identifier
+ || name == base_ctor_identifier
+ || name == complete_ctor_identifier))
+ {
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+ lazily_declare_fn (sfk_constructor, type);
+ if (CLASSTYPE_LAZY_COPY_CTOR (type))
+ lazily_declare_fn (sfk_copy_constructor, type);
+ if (CLASSTYPE_LAZY_MOVE_CTOR (type))
+ lazily_declare_fn (sfk_move_constructor, type);
+ }
+ else if (name == ansi_assopname (NOP_EXPR))
+ {
+ if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
+ lazily_declare_fn (sfk_copy_assignment, type);
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
+ lazily_declare_fn (sfk_move_assignment, type);
+ }
+ else if ((name == dtor_identifier
+ || name == base_dtor_identifier
+ || name == complete_dtor_identifier
+ || name == deleting_dtor_identifier)
+ && CLASSTYPE_LAZY_DESTRUCTOR (type))
+ lazily_declare_fn (sfk_destructor, type);
+ }
+
+ return lookup_fnfields_idx_nolazy (type, name);
+}
+
/* TYPE is a class type. Return the field within the method vector with
name NAME, or NULL_TREE if no such field exists. */
tree
lookup_fnfields_slot (tree type, tree name)
{
- int ix = lookup_fnfields_1 (type, name);
+ int ix = lookup_fnfields_1 (complete_type (type), name);
+ if (ix < 0)
+ return NULL_TREE;
+ return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+}
+
+/* As above, but avoid lazily declaring functions. */
+
+tree
+lookup_fnfields_slot_nolazy (tree type, tree name)
+{
+ int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
if (ix < 0)
return NULL_TREE;
return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
}
}
+ if (BASELINK_P (decl))
+ BASELINK_QUALIFIED_P (decl) = true;
+
return decl;
}
tree base_type = TREE_TYPE (basefn);
tree over_return = TREE_TYPE (over_type);
tree base_return = TREE_TYPE (base_type);
- tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
- tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
+ tree over_throw, base_throw;
+
int fail = 0;
if (DECL_INVALID_OVERRIDER_P (overrider))
}
/* Check throw specifier is at least as strict. */
+ maybe_instantiate_noexcept (basefn);
+ maybe_instantiate_noexcept (overrider);
+ base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
+ over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
+
if (!comp_except_specs (base_throw, over_throw, ce_derived))
{
error ("looser throw specifier for %q+#F", overrider);
}
/* Check for conflicting type attributes. */
- if (!targetm.comp_type_attributes (over_type, base_type))
+ if (!comp_type_attributes (over_type, base_type))
{
error ("conflicting type attributes specified for %q+#D", overrider);
error (" overriding %q+#D", basefn);
}
return 0;
}
+ if (DECL_FINAL_P (basefn))
+ {
+ error ("virtual function %q+D", overrider);
+ error ("overriding final function %q+D", basefn);
+ return 0;
+ }
return 1;
}