mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 15:41:09 +08:00
re PR c++/6936 (member "using" binds wrong)
PR c++/6936 PR c++/25994 PR c++/26256 PR c++/30195 * search.c (lookup_field_1): Look through USING_DECL. (lookup_field_r): Call lookup_fnfields_slot instead of lookup_fnfields_1. * semantics.c (finish_member_declaration): Remove the check that prevents USING_DECLs from being verified by pushdecl_class_level. Call add_method for using declarations that designates functions if the using declaration is in a template class. Set DECL_IGNORED_P on class-scope using declarations. * typeck.c (build_class_member_access_expr): Handle USING_DECLs. * class.c (check_field_decls): Keep using declarations. (add_method): Remove two diagnostics about conflicting using declarations. * parser.c (cp_parser_nonclass_name): Handle USING_DECLs. * decl.c (start_enum): Call xref_tag whenever possible. * cp-tree.h (strip_using_decl): Declare, and reident the previous function. * name-lookup.c (strip_using_decl): New function. (supplement_binding_1): Call strip_using_decl on decl and bval. Perform most of the checks with USING_DECLs stripped. Also check that the target decl and the target bval does not refer to the same declaration. Allow pushing an enum multiple times in a template class. Adjustment to diagnose using redeclarations. Call diagnose_name_conflict. (push_class_level_binding): Call strip_using_decl on decl and bval. Perform most of the checks with USING_DECLs stripped. Return true if both decl and bval refer to USING_DECLs and are dependent. (diagnose_name_conflict): New function. From-SVN: r181359
This commit is contained in:
parent
ac99ebf5ae
commit
557831a91d
@ -1,3 +1,37 @@
|
||||
2011-11-14 Fabien Chêne <fabien@gcc.gnu.org>
|
||||
|
||||
PR c++/6936
|
||||
PR c++/25994
|
||||
PR c++/26256
|
||||
PR c++/30195
|
||||
* search.c (lookup_field_1): Look through USING_DECL.
|
||||
(lookup_field_r): Call lookup_fnfields_slot instead of
|
||||
lookup_fnfields_1.
|
||||
* semantics.c (finish_member_declaration): Remove the check that
|
||||
prevents USING_DECLs from being verified by
|
||||
pushdecl_class_level. Call add_method for using declarations that
|
||||
designates functions if the using declaration is in a template
|
||||
class. Set DECL_IGNORED_P on class-scope using declarations.
|
||||
* typeck.c (build_class_member_access_expr): Handle USING_DECLs.
|
||||
* class.c (check_field_decls): Keep using declarations.
|
||||
(add_method): Remove two diagnostics about conflicting using
|
||||
declarations.
|
||||
* parser.c (cp_parser_nonclass_name): Handle USING_DECLs.
|
||||
* decl.c (start_enum): Call xref_tag whenever possible.
|
||||
* cp-tree.h (strip_using_decl): Declare, and reident the previous
|
||||
function.
|
||||
* name-lookup.c (strip_using_decl): New function.
|
||||
(supplement_binding_1): Call strip_using_decl on decl and
|
||||
bval. Perform most of the checks with USING_DECLs stripped. Also
|
||||
check that the target decl and the target bval does not refer to
|
||||
the same declaration. Allow pushing an enum multiple times in a
|
||||
template class. Adjustment to diagnose using redeclarations. Call
|
||||
diagnose_name_conflict.
|
||||
(push_class_level_binding): Call strip_using_decl on decl and
|
||||
bval. Perform most of the checks with USING_DECLs stripped. Return
|
||||
true if both decl and bval refer to USING_DECLs and are dependent.
|
||||
(diagnose_name_conflict): New function.
|
||||
|
||||
2011-11-12 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/986
|
||||
|
@ -1058,11 +1058,6 @@ add_method (tree type, tree method, tree using_decl)
|
||||
if (DECL_CONTEXT (fn) == type)
|
||||
/* Defer to the local function. */
|
||||
return false;
|
||||
if (DECL_CONTEXT (fn) == DECL_CONTEXT (method))
|
||||
error ("repeated using declaration %q+D", using_decl);
|
||||
else
|
||||
error ("using declaration %q+D conflicts with a previous using declaration",
|
||||
using_decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3039,15 +3034,8 @@ check_field_decls (tree t, tree *access_decls,
|
||||
|
||||
if (TREE_CODE (x) == USING_DECL)
|
||||
{
|
||||
/* Prune the access declaration from the list of fields. */
|
||||
*field = DECL_CHAIN (x);
|
||||
|
||||
/* Save the access declarations for our caller. */
|
||||
*access_decls = tree_cons (NULL_TREE, x, *access_decls);
|
||||
|
||||
/* Since we've reset *FIELD there's no reason to skip to the
|
||||
next field. */
|
||||
next = field;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -5886,7 +5886,8 @@ extern void cxx_omp_finish_clause (tree);
|
||||
extern bool cxx_omp_privatize_by_reference (const_tree);
|
||||
|
||||
/* in name-lookup.c */
|
||||
extern void suggest_alternatives_for (location_t, tree);
|
||||
extern void suggest_alternatives_for (location_t, tree);
|
||||
extern tree strip_using_decl (tree);
|
||||
|
||||
/* -- end of C++ */
|
||||
|
||||
|
@ -11988,8 +11988,22 @@ start_enum (tree name, tree enumtype, tree underlying_type,
|
||||
*is_new = true;
|
||||
}
|
||||
prevtype = enumtype;
|
||||
enumtype = cxx_make_type (ENUMERAL_TYPE);
|
||||
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
|
||||
|
||||
/* Do not push the decl more than once, unless we need to
|
||||
compare underlying types at instantiation time */
|
||||
if (!enumtype
|
||||
|| (underlying_type
|
||||
&& dependent_type_p (underlying_type))
|
||||
|| (ENUM_UNDERLYING_TYPE (enumtype)
|
||||
&& dependent_type_p (ENUM_UNDERLYING_TYPE (enumtype))))
|
||||
{
|
||||
enumtype = cxx_make_type (ENUMERAL_TYPE);
|
||||
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
|
||||
}
|
||||
else
|
||||
enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
|
||||
false);
|
||||
|
||||
if (enumtype == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -53,6 +53,7 @@ static bool qualified_lookup_using_namespace (tree, tree,
|
||||
static tree lookup_type_current_level (tree);
|
||||
static tree push_using_directive (tree);
|
||||
static tree lookup_extern_c_fun_in_all_ns (tree);
|
||||
static void diagnose_name_conflict (tree, tree);
|
||||
|
||||
/* The :: namespace. */
|
||||
|
||||
@ -394,6 +395,16 @@ pop_binding (tree id, tree decl)
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip non dependent using declarations. */
|
||||
|
||||
tree
|
||||
strip_using_decl (tree decl)
|
||||
{
|
||||
while (TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
|
||||
decl = USING_DECL_DECLS (decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* BINDING records an existing declaration for a name in the current scope.
|
||||
But, DECL is another declaration for that same identifier in the
|
||||
same scope. This is the `struct stat' hack whereby a non-typedef
|
||||
@ -417,29 +428,46 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
|
||||
{
|
||||
tree bval = binding->value;
|
||||
bool ok = true;
|
||||
tree target_bval = strip_using_decl (bval);
|
||||
tree target_decl = strip_using_decl (decl);
|
||||
|
||||
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
|
||||
if (TREE_CODE (target_decl) == TYPE_DECL && DECL_ARTIFICIAL (target_decl)
|
||||
&& target_decl != target_bval
|
||||
&& (TREE_CODE (target_bval) != TYPE_DECL
|
||||
/* We allow pushing an enum multiple times in a class
|
||||
template in order to handle late matching of underlying
|
||||
type on an opaque-enum-declaration followed by an
|
||||
enum-specifier. */
|
||||
|| (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
|
||||
&& (dependent_type_p (ENUM_UNDERLYING_TYPE
|
||||
(TREE_TYPE (target_decl)))
|
||||
|| dependent_type_p (ENUM_UNDERLYING_TYPE
|
||||
(TREE_TYPE (target_bval)))))))
|
||||
/* The new name is the type name. */
|
||||
binding->type = decl;
|
||||
else if (/* BVAL is null when push_class_level_binding moves an
|
||||
inherited type-binding out of the way to make room for a
|
||||
new value binding. */
|
||||
!bval
|
||||
/* BVAL is error_mark_node when DECL's name has been used
|
||||
in a non-class scope prior declaration. In that case,
|
||||
we should have already issued a diagnostic; for graceful
|
||||
error recovery purpose, pretend this was the intended
|
||||
declaration for that name. */
|
||||
|| bval == error_mark_node
|
||||
/* If BVAL is anticipated but has not yet been declared,
|
||||
pretend it is not there at all. */
|
||||
|| (TREE_CODE (bval) == FUNCTION_DECL
|
||||
&& DECL_ANTICIPATED (bval)
|
||||
&& !DECL_HIDDEN_FRIEND_P (bval)))
|
||||
else if (/* TARGET_BVAL is null when push_class_level_binding moves
|
||||
an inherited type-binding out of the way to make room
|
||||
for a new value binding. */
|
||||
!target_bval
|
||||
/* TARGET_BVAL is error_mark_node when TARGET_DECL's name
|
||||
has been used in a non-class scope prior declaration.
|
||||
In that case, we should have already issued a
|
||||
diagnostic; for graceful error recovery purpose, pretend
|
||||
this was the intended declaration for that name. */
|
||||
|| target_bval == error_mark_node
|
||||
/* If TARGET_BVAL is anticipated but has not yet been
|
||||
declared, pretend it is not there at all. */
|
||||
|| (TREE_CODE (target_bval) == FUNCTION_DECL
|
||||
&& DECL_ANTICIPATED (target_bval)
|
||||
&& !DECL_HIDDEN_FRIEND_P (target_bval)))
|
||||
binding->value = decl;
|
||||
else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
|
||||
&& (TREE_CODE (decl) != TYPE_DECL
|
||||
|| same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))))
|
||||
else if (TREE_CODE (target_bval) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (target_bval)
|
||||
&& target_decl != target_bval
|
||||
&& (TREE_CODE (target_decl) != TYPE_DECL
|
||||
|| same_type_p (TREE_TYPE (target_decl),
|
||||
TREE_TYPE (target_bval))))
|
||||
{
|
||||
/* The old binding was a type name. It was placed in
|
||||
VALUE field because it was thought, at the point it was
|
||||
@ -450,15 +478,15 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
|
||||
binding->value = decl;
|
||||
binding->value_is_inherited = false;
|
||||
}
|
||||
else if (TREE_CODE (bval) == TYPE_DECL
|
||||
&& TREE_CODE (decl) == TYPE_DECL
|
||||
&& DECL_NAME (decl) == DECL_NAME (bval)
|
||||
else if (TREE_CODE (target_bval) == TYPE_DECL
|
||||
&& TREE_CODE (target_decl) == TYPE_DECL
|
||||
&& DECL_NAME (target_decl) == DECL_NAME (target_bval)
|
||||
&& binding->scope->kind != sk_class
|
||||
&& (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
|
||||
&& (same_type_p (TREE_TYPE (target_decl), TREE_TYPE (target_bval))
|
||||
/* If either type involves template parameters, we must
|
||||
wait until instantiation. */
|
||||
|| uses_template_parms (TREE_TYPE (decl))
|
||||
|| uses_template_parms (TREE_TYPE (bval))))
|
||||
|| uses_template_parms (TREE_TYPE (target_decl))
|
||||
|| uses_template_parms (TREE_TYPE (target_bval))))
|
||||
/* We have two typedef-names, both naming the same type to have
|
||||
the same name. In general, this is OK because of:
|
||||
|
||||
@ -480,9 +508,10 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
|
||||
|
||||
A member shall not be declared twice in the
|
||||
member-specification. */
|
||||
else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
|
||||
&& DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
|
||||
&& !DECL_CLASS_SCOPE_P (decl))
|
||||
else if (TREE_CODE (target_decl) == VAR_DECL
|
||||
&& TREE_CODE (target_bval) == VAR_DECL
|
||||
&& DECL_EXTERNAL (target_decl) && DECL_EXTERNAL (target_bval)
|
||||
&& !DECL_CLASS_SCOPE_P (target_decl))
|
||||
{
|
||||
duplicate_decls (decl, binding->value, /*newdecl_is_friend=*/false);
|
||||
ok = false;
|
||||
@ -501,14 +530,30 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
|
||||
ok = false;
|
||||
else
|
||||
{
|
||||
error ("declaration of %q#D", decl);
|
||||
error ("conflicts with previous declaration %q+#D", bval);
|
||||
diagnose_name_conflict (decl, bval);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Diagnose a name conflict between DECL and BVAL. */
|
||||
|
||||
static void
|
||||
diagnose_name_conflict (tree decl, tree bval)
|
||||
{
|
||||
if (TREE_CODE (decl) == TREE_CODE (bval)
|
||||
&& (TREE_CODE (decl) != TYPE_DECL
|
||||
|| (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval))
|
||||
|| (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval)))
|
||||
&& !is_overloaded_fn (decl))
|
||||
error ("redeclaration of %q#D", decl);
|
||||
else
|
||||
error ("%q#D conflicts with a previous declaration", decl);
|
||||
|
||||
inform (input_location, "previous declaration %q+#D", bval);
|
||||
}
|
||||
|
||||
/* Wrapper for supplement_binding_1. */
|
||||
|
||||
static bool
|
||||
@ -3028,6 +3073,8 @@ push_class_level_binding_1 (tree name, tree x)
|
||||
{
|
||||
tree bval = binding->value;
|
||||
tree old_decl = NULL_TREE;
|
||||
tree target_decl = strip_using_decl (decl);
|
||||
tree target_bval = strip_using_decl (bval);
|
||||
|
||||
if (INHERITED_VALUE_BINDING_P (binding))
|
||||
{
|
||||
@ -3035,8 +3082,10 @@ push_class_level_binding_1 (tree name, tree x)
|
||||
tag name, slide it over to make room for the new binding.
|
||||
The old binding is still visible if explicitly qualified
|
||||
with a class-key. */
|
||||
if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
|
||||
&& !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
|
||||
if (TREE_CODE (target_bval) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (target_bval)
|
||||
&& !(TREE_CODE (target_decl) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (target_decl)))
|
||||
{
|
||||
old_decl = binding->type;
|
||||
binding->type = bval;
|
||||
@ -3048,17 +3097,31 @@ push_class_level_binding_1 (tree name, tree x)
|
||||
old_decl = bval;
|
||||
/* Any inherited type declaration is hidden by the type
|
||||
declaration in the derived class. */
|
||||
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))
|
||||
if (TREE_CODE (target_decl) == TYPE_DECL
|
||||
&& DECL_ARTIFICIAL (target_decl))
|
||||
binding->type = NULL_TREE;
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
|
||||
else if (TREE_CODE (target_decl) == OVERLOAD
|
||||
&& is_overloaded_fn (target_bval))
|
||||
old_decl = bval;
|
||||
else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
|
||||
else if (TREE_CODE (decl) == USING_DECL
|
||||
&& TREE_CODE (bval) == USING_DECL
|
||||
&& same_type_p (USING_DECL_SCOPE (decl),
|
||||
USING_DECL_SCOPE (bval)))
|
||||
/* This is a using redeclaration that will be diagnosed later
|
||||
in supplement_binding */
|
||||
;
|
||||
else if (TREE_CODE (decl) == USING_DECL
|
||||
&& TREE_CODE (bval) == USING_DECL
|
||||
&& DECL_DEPENDENT_P (decl)
|
||||
&& DECL_DEPENDENT_P (bval))
|
||||
return true;
|
||||
else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
|
||||
else if (TREE_CODE (decl) == USING_DECL
|
||||
&& is_overloaded_fn (target_bval))
|
||||
old_decl = bval;
|
||||
else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
|
||||
else if (TREE_CODE (bval) == USING_DECL
|
||||
&& is_overloaded_fn (target_decl))
|
||||
return true;
|
||||
|
||||
if (old_decl && binding->scope == class_binding_level)
|
||||
|
@ -13758,6 +13758,9 @@ cp_parser_nonclass_name (cp_parser* parser)
|
||||
/* Look up the type-name. */
|
||||
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
|
||||
|
||||
/* If it is a using decl, use its underlying decl. */
|
||||
type_decl = strip_using_decl (type_decl);
|
||||
|
||||
if (TREE_CODE (type_decl) != TYPE_DECL
|
||||
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* 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)
|
||||
|
||||
@ -449,6 +449,8 @@ lookup_field_1 (tree type, tree name, bool want_type)
|
||||
#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 */
|
||||
@ -460,26 +462,20 @@ lookup_field_1 (tree type, tree name, bool want_type)
|
||||
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_TYPE_TEMPLATE_P (field)))
|
||||
return field;
|
||||
|| TREE_CODE (decl) == TYPE_DECL
|
||||
|| DECL_TYPE_TEMPLATE_P (decl)))
|
||||
return decl;
|
||||
}
|
||||
/* Not found. */
|
||||
if (name == vptr_identifier)
|
||||
@ -1028,11 +1024,7 @@ lookup_field_r (tree binfo, void *data)
|
||||
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. */
|
||||
|
@ -2658,9 +2658,29 @@ finish_member_declaration (tree decl)
|
||||
}
|
||||
}
|
||||
/* Enter the DECL into the scope of the class. */
|
||||
else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl))
|
||||
|| pushdecl_class_level (decl))
|
||||
else if (pushdecl_class_level (decl))
|
||||
{
|
||||
if (TREE_CODE (decl) == USING_DECL)
|
||||
{
|
||||
/* We need to add the target functions to the
|
||||
CLASSTYPE_METHOD_VEC if an enclosing scope is a template
|
||||
class, so that this function be found by lookup_fnfields_1
|
||||
when the using declaration is not instantiated yet. */
|
||||
|
||||
tree target_decl = strip_using_decl (decl);
|
||||
if (dependent_type_p (current_class_type)
|
||||
&& is_overloaded_fn (target_decl))
|
||||
{
|
||||
tree t = target_decl;
|
||||
for (; t; t = OVL_NEXT (t))
|
||||
add_method (current_class_type, OVL_CURRENT (t), decl);
|
||||
}
|
||||
|
||||
/* For now, ignore class-scope USING_DECLS, so that
|
||||
debugging backends do not see them. */
|
||||
DECL_IGNORED_P (decl) = 1;
|
||||
}
|
||||
|
||||
/* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
|
||||
go at the beginning. The reason is that lookup_field_1
|
||||
searches the list in order, and we want a field name to
|
||||
|
@ -2115,6 +2115,7 @@ build_class_member_access_expr (tree object, tree member,
|
||||
tree object_type;
|
||||
tree member_scope;
|
||||
tree result = NULL_TREE;
|
||||
tree using_decl = NULL_TREE;
|
||||
|
||||
if (error_operand_p (object) || error_operand_p (member))
|
||||
return error_mark_node;
|
||||
@ -2343,6 +2344,11 @@ build_class_member_access_expr (tree object, tree member,
|
||||
result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
|
||||
object, result);
|
||||
}
|
||||
else if ((using_decl = strip_using_decl (member)) != member)
|
||||
result = build_class_member_access_expr (object,
|
||||
using_decl,
|
||||
access_path, preserve_reference,
|
||||
complain);
|
||||
else
|
||||
{
|
||||
if (complain & tf_error)
|
||||
|
@ -1,3 +1,50 @@
|
||||
2011-11-14 Fabien Chêne <fabien@gcc.gnu.org>
|
||||
|
||||
PR c++/6936
|
||||
PR c++/25994
|
||||
PR c++/26256
|
||||
PR c++/30195
|
||||
* g++.old-deja/g++.brendan/misc14.C: Adjust.
|
||||
* g++.old-deja/g++.jason/scoping16.C: Likewise.
|
||||
* g++.old-deja/g++.other/anon7.C: Likewise.
|
||||
* g++.old-deja/g++.other/using1.C: Likewise.
|
||||
* g++.old-deja/g++.other/redecl1.C: Likewise.
|
||||
* g++.old-deja/g++.other/typedef7.C: Likewise.
|
||||
* g++.old-deja/g++.bugs/900127_02.C: Likewise.
|
||||
* g++.dg/template/using2.C: Likewise.
|
||||
* g++.dg/template/static4.C: Likewise.
|
||||
* g++.dg/template/typedef1.C: Likewise.
|
||||
* g++.dg/lookup/name-clash9.C: Likewise.
|
||||
* g++.dg/abi/mangle41.C: Likewise.
|
||||
* g++.dg/parse/ctor5.C: Likewise.
|
||||
* g++.dg/inherit/using4.C: Likewise.
|
||||
* g++.dg/lookup/using24.C: New.
|
||||
* g++.dg/lookup/using25.C: New.
|
||||
* g++.dg/lookup/using26.C: New.
|
||||
* g++.dg/lookup/using27.C: New.
|
||||
* g++.dg/lookup/using28.C: New.
|
||||
* g++.dg/lookup/using29.C: New.
|
||||
* g++.dg/lookup/using30.C: New.
|
||||
* g++.dg/lookup/using31.C: New.
|
||||
* g++.dg/lookup/using32.C: New.
|
||||
* g++.dg/lookup/using33.C: New.
|
||||
* g++.dg/lookup/using34.C: New.
|
||||
* g++.dg/lookup/using35.C: New.
|
||||
* g++.dg/lookup/using36.C: New.
|
||||
* g++.dg/lookup/using37.C: New.
|
||||
* g++.dg/lookup/using38.C: New.
|
||||
* g++.dg/lookup/using39.C: New.
|
||||
* g++.dg/lookup/using40.C: New.
|
||||
* g++.dg/lookup/using41.C: New.
|
||||
* g++.dg/lookup/using42.C: New.
|
||||
* g++.dg/lookup/using43.C: New.
|
||||
* g++.dg/lookup/using44.C: New.
|
||||
* g++.dg/lookup/using45.C: New.
|
||||
* g++.dg/lookup/pr6936.C: New.
|
||||
* g++.dg/debug/using4.C: New.
|
||||
* g++.dg/debug/using5.C: New.
|
||||
* g++.dg/cpp0x/forw_enum10.C: New.
|
||||
|
||||
2011-11-14 Zolotukhin Michael <michael.v.zolotukhin@gmail.com>
|
||||
Jan Hubicka <jh@suse.cz>
|
||||
|
||||
|
@ -3,5 +3,6 @@
|
||||
// { dg-options "-mavx -fabi-version=2" }
|
||||
|
||||
#include <x86intrin.h>
|
||||
void f(__m128) { } // { dg-error "previous" }
|
||||
void f(__m256) { } // { dg-message "declaration|mangling" }
|
||||
void f(__m128) { } // { dg-message "previous declaration" }
|
||||
void f(__m256) { } // { dg-error "conflicts" }
|
||||
// { dg-message "mangling" "" { target *-*-* } 7 }
|
||||
|
31
gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
Normal file
31
gcc/testsuite/g++.dg/cpp0x/forw_enum10.C
Normal file
@ -0,0 +1,31 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
//This error is diagnosed at instantiation time
|
||||
template<typename T> struct S1
|
||||
{
|
||||
enum E : T; // { dg-error "previous definition" }
|
||||
enum E : int; // { dg-error "different underlying type" }
|
||||
};
|
||||
template struct S1<short>; // { dg-message "required from here" }
|
||||
|
||||
template<typename T> struct S2
|
||||
{
|
||||
enum E : T;
|
||||
enum E : T;
|
||||
};
|
||||
template struct S2<short>;
|
||||
|
||||
template<typename T1, typename T2> struct S3
|
||||
{
|
||||
enum E : T1;
|
||||
enum E : T2;
|
||||
};
|
||||
template struct S3<short,short>;
|
||||
|
||||
template<typename T1, typename T2> struct S4
|
||||
{
|
||||
enum E : T1; // { dg-error "previous definition" }
|
||||
enum E : T2; // { dg-error "different underlying type" }
|
||||
};
|
||||
template struct S4<short,char>; // { dg-message "required from here" }
|
24
gcc/testsuite/g++.dg/debug/using4.C
Normal file
24
gcc/testsuite/g++.dg/debug/using4.C
Normal file
@ -0,0 +1,24 @@
|
||||
// PR c++/26256
|
||||
// { dg-do compile }
|
||||
|
||||
struct A
|
||||
{
|
||||
typedef char type;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct C : A, B
|
||||
{
|
||||
using A::type;
|
||||
type f (type);
|
||||
};
|
||||
|
||||
C::type C::f( type )
|
||||
{
|
||||
type c = 'e';
|
||||
return c;
|
||||
}
|
23
gcc/testsuite/g++.dg/debug/using5.C
Normal file
23
gcc/testsuite/g++.dg/debug/using5.C
Normal file
@ -0,0 +1,23 @@
|
||||
// PR c++/26256
|
||||
// { dg-do compile }
|
||||
|
||||
struct A
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
struct C : A, B
|
||||
{
|
||||
using B::i;
|
||||
int f ();
|
||||
};
|
||||
|
||||
int C::f()
|
||||
{
|
||||
return i;
|
||||
}
|
@ -9,6 +9,6 @@ struct B {
|
||||
};
|
||||
|
||||
struct D : B {
|
||||
using B::f;
|
||||
using B::f; // { dg-error "repeated" }
|
||||
using B::f; // { dg-message "previous declaration" }
|
||||
using B::f; // { dg-error "redeclaration" }
|
||||
};
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
struct A
|
||||
{
|
||||
struct type {}; // { dg-error "conflicts with previous" }
|
||||
typedef int type; // { dg-error "declaration" }
|
||||
struct type {}; // { dg-message "previous" }
|
||||
typedef int type; // { dg-error "conflicts" }
|
||||
};
|
||||
|
23
gcc/testsuite/g++.dg/lookup/pr6936.C
Normal file
23
gcc/testsuite/g++.dg/lookup/pr6936.C
Normal file
@ -0,0 +1,23 @@
|
||||
// { dg-do compile }
|
||||
// PR c++/6936
|
||||
|
||||
struct Baser
|
||||
{
|
||||
enum { j, i }; // { dg-error "inaccessible" }
|
||||
};
|
||||
|
||||
struct Base : Baser
|
||||
{
|
||||
static void j();
|
||||
static void i();
|
||||
};
|
||||
|
||||
struct Derv : Base
|
||||
{
|
||||
using Baser::j;
|
||||
private:
|
||||
using Baser::i;
|
||||
};
|
||||
|
||||
int k = Derv::j;
|
||||
int l = Derv::i; // { dg-error "context" }
|
12
gcc/testsuite/g++.dg/lookup/using24.C
Normal file
12
gcc/testsuite/g++.dg/lookup/using24.C
Normal file
@ -0,0 +1,12 @@
|
||||
// PR c++/26256
|
||||
// { dg-do compile }
|
||||
|
||||
struct A { int next; };
|
||||
struct B { int next; };
|
||||
struct C : B { using B::next; };
|
||||
|
||||
struct D : A, C
|
||||
{
|
||||
using C::next;
|
||||
void f() { next = 1; }
|
||||
};
|
28
gcc/testsuite/g++.dg/lookup/using25.C
Normal file
28
gcc/testsuite/g++.dg/lookup/using25.C
Normal file
@ -0,0 +1,28 @@
|
||||
// PR c++/26256
|
||||
// { dg-do run }
|
||||
|
||||
struct A
|
||||
{
|
||||
int next;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
int next;
|
||||
};
|
||||
|
||||
struct C : public A, public B
|
||||
{
|
||||
using A::next;
|
||||
};
|
||||
|
||||
void foo(C& c) { c.next = 42; }
|
||||
|
||||
int main()
|
||||
{
|
||||
C c;
|
||||
foo (c);
|
||||
c.B::next = 12;
|
||||
if (c.next != 42 || c.A::next != 42 || c.B::next != 12)
|
||||
__builtin_abort();
|
||||
}
|
27
gcc/testsuite/g++.dg/lookup/using26.C
Normal file
27
gcc/testsuite/g++.dg/lookup/using26.C
Normal file
@ -0,0 +1,27 @@
|
||||
// PR c++/26256
|
||||
// { dg-do compile }
|
||||
|
||||
struct A
|
||||
{
|
||||
double next;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
private:
|
||||
int next; // { dg-error "private" }
|
||||
};
|
||||
|
||||
struct C
|
||||
{
|
||||
int next;
|
||||
};
|
||||
|
||||
struct D : A, B, C // { dg-error "context" }
|
||||
{
|
||||
using B::next;
|
||||
void f()
|
||||
{
|
||||
next = 12;
|
||||
}
|
||||
};
|
48
gcc/testsuite/g++.dg/lookup/using27.C
Normal file
48
gcc/testsuite/g++.dg/lookup/using27.C
Normal file
@ -0,0 +1,48 @@
|
||||
// PR c++/26256
|
||||
// { dg-do run }
|
||||
|
||||
struct A
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
typedef double type;
|
||||
};
|
||||
|
||||
struct C : A, B
|
||||
{
|
||||
using A::type;
|
||||
type d;
|
||||
|
||||
void f()
|
||||
{
|
||||
type e;
|
||||
if (sizeof (type) != sizeof (A::type))
|
||||
__builtin_abort();
|
||||
}
|
||||
|
||||
void g();
|
||||
};
|
||||
|
||||
void C::g()
|
||||
{
|
||||
type x;
|
||||
if (sizeof (type) != sizeof (A::type))
|
||||
__builtin_abort();
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (sizeof (C::type) != sizeof (A::type))
|
||||
__builtin_abort();
|
||||
|
||||
if (sizeof (C::d) != sizeof (A::type))
|
||||
__builtin_abort();
|
||||
|
||||
C::type x;
|
||||
C c;
|
||||
c.f();
|
||||
c.g();
|
||||
}
|
11
gcc/testsuite/g++.dg/lookup/using28.C
Normal file
11
gcc/testsuite/g++.dg/lookup/using28.C
Normal file
@ -0,0 +1,11 @@
|
||||
// PR c++/26256
|
||||
// { dg-do compile }
|
||||
|
||||
struct A { int f; };
|
||||
struct B { int f; };
|
||||
struct C : A, B { using B::f; };
|
||||
|
||||
struct D : C
|
||||
{
|
||||
void g() { f = 1; }
|
||||
};
|
81
gcc/testsuite/g++.dg/lookup/using29.C
Normal file
81
gcc/testsuite/g++.dg/lookup/using29.C
Normal file
@ -0,0 +1,81 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct A
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
struct B
|
||||
{
|
||||
int i;
|
||||
};
|
||||
|
||||
struct C : A, B
|
||||
{
|
||||
using A::i; // { dg-message "previous" }
|
||||
using B::i; // { dg-error "redeclaration" }
|
||||
};
|
||||
|
||||
struct E
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct F
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct G : E, F
|
||||
{
|
||||
using E::type; // { dg-message "previous" }
|
||||
using F::type; // { dg-error "redeclaration" }
|
||||
};
|
||||
|
||||
struct H
|
||||
{
|
||||
typedef int type;
|
||||
};
|
||||
|
||||
struct I : H
|
||||
{
|
||||
typedef int type; // { dg-message "previous" }
|
||||
using H::type; // { dg-error "conflicts" }
|
||||
};
|
||||
|
||||
struct I2 : H
|
||||
{
|
||||
using H::type; // { dg-message "previous" }
|
||||
typedef int type; // { dg-error "conflicts" }
|
||||
};
|
||||
|
||||
struct J
|
||||
{
|
||||
struct type {};
|
||||
};
|
||||
|
||||
struct K : J
|
||||
{
|
||||
struct type {}; // { dg-message "previous" }
|
||||
using J::type; // { dg-error "conflicts" }
|
||||
};
|
||||
|
||||
struct L : J
|
||||
{
|
||||
using J::type; // { dg-message "previous" }
|
||||
struct type {}; // { dg-error "conflicts" }
|
||||
};
|
||||
|
||||
struct M
|
||||
{
|
||||
typedef int type;
|
||||
struct type2 {};
|
||||
};
|
||||
|
||||
struct N : M
|
||||
{
|
||||
using M::type; // { dg-message "previous" }
|
||||
using M::type; // { dg-error "redeclaration" }
|
||||
using M::type2; // { dg-message "previous" }
|
||||
using M::type2; // { dg-error "redeclaration" }
|
||||
};
|
8
gcc/testsuite/g++.dg/lookup/using30.C
Normal file
8
gcc/testsuite/g++.dg/lookup/using30.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct H { typedef int type; };
|
||||
struct J : H
|
||||
{
|
||||
struct type {}; // { dg-message "previous" }
|
||||
using H::type; // { dg-error "conflicts" }
|
||||
};
|
8
gcc/testsuite/g++.dg/lookup/using31.C
Normal file
8
gcc/testsuite/g++.dg/lookup/using31.C
Normal file
@ -0,0 +1,8 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct H2 { int f (); };
|
||||
struct J2 : H2
|
||||
{
|
||||
struct f {};
|
||||
using H2::f;
|
||||
};
|
9
gcc/testsuite/g++.dg/lookup/using32.C
Normal file
9
gcc/testsuite/g++.dg/lookup/using32.C
Normal file
@ -0,0 +1,9 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct T { struct type {}; };
|
||||
struct T2 : T { using T::type; };
|
||||
struct T3 : T2
|
||||
{
|
||||
struct type {};
|
||||
type t;
|
||||
};
|
26
gcc/testsuite/g++.dg/lookup/using33.C
Normal file
26
gcc/testsuite/g++.dg/lookup/using33.C
Normal file
@ -0,0 +1,26 @@
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
int k (float) {return 0;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Baz
|
||||
{
|
||||
int k (int) {return 1;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Bar : Foo<T> , Baz<T>
|
||||
{
|
||||
using Foo<T>::k;
|
||||
using Baz<T>::k;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Bar<int> bar;
|
||||
return bar.k( 1.0f );
|
||||
}
|
10
gcc/testsuite/g++.dg/lookup/using34.C
Normal file
10
gcc/testsuite/g++.dg/lookup/using34.C
Normal file
@ -0,0 +1,10 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct A { int f (); };
|
||||
struct B : A
|
||||
{
|
||||
using A::f;
|
||||
struct f {};
|
||||
void g() { f(); struct f ff; }
|
||||
struct f ff;
|
||||
};
|
11
gcc/testsuite/g++.dg/lookup/using35.C
Normal file
11
gcc/testsuite/g++.dg/lookup/using35.C
Normal file
@ -0,0 +1,11 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct A { typedef int type; };
|
||||
struct B { typedef int type; };
|
||||
struct C : B { using B::type; };
|
||||
|
||||
struct D : A, C
|
||||
{
|
||||
using C::type;
|
||||
void f() { type t = 0;}
|
||||
};
|
31
gcc/testsuite/g++.dg/lookup/using36.C
Normal file
31
gcc/testsuite/g++.dg/lookup/using36.C
Normal file
@ -0,0 +1,31 @@
|
||||
// PR c++/25994
|
||||
// { dg-do run }
|
||||
|
||||
struct B1
|
||||
{
|
||||
void f (char) {}
|
||||
void f (double) { __builtin_abort(); }
|
||||
};
|
||||
|
||||
struct B2
|
||||
{
|
||||
void f (double) { __builtin_abort(); }
|
||||
void f (int) {}
|
||||
};
|
||||
|
||||
struct D : public B1, public B2
|
||||
{
|
||||
using B1::f;
|
||||
using B2::f;
|
||||
void g ()
|
||||
{
|
||||
f ('a'); // should call B1::f(char)
|
||||
f (33); // should call B2::f(int)
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
D d;
|
||||
d.g();
|
||||
}
|
22
gcc/testsuite/g++.dg/lookup/using37.C
Normal file
22
gcc/testsuite/g++.dg/lookup/using37.C
Normal file
@ -0,0 +1,22 @@
|
||||
// PR c++/30195
|
||||
// { dg-do run }
|
||||
|
||||
template<class T> struct B
|
||||
{
|
||||
void foo(T) {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct D : B<int>, B<double>
|
||||
{
|
||||
using B<int>::foo;
|
||||
using B<double>::foo;
|
||||
void bar() { foo(3); }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
D<int> x;
|
||||
x.bar();
|
||||
return 0;
|
||||
}
|
23
gcc/testsuite/g++.dg/lookup/using38.C
Normal file
23
gcc/testsuite/g++.dg/lookup/using38.C
Normal file
@ -0,0 +1,23 @@
|
||||
// { dg-do compile }
|
||||
// PR c++/6936
|
||||
|
||||
struct Baser
|
||||
{
|
||||
enum { j, i }; // { dg-error "inaccessible" }
|
||||
};
|
||||
|
||||
struct Base : Baser
|
||||
{
|
||||
static void j();
|
||||
static void i();
|
||||
};
|
||||
|
||||
struct Derv : Base
|
||||
{
|
||||
using Baser::j;
|
||||
private:
|
||||
using Baser::i;
|
||||
};
|
||||
|
||||
int k = Derv::j;
|
||||
int l = Derv::i; // { dg-error "context" }
|
63
gcc/testsuite/g++.dg/lookup/using39.C
Normal file
63
gcc/testsuite/g++.dg/lookup/using39.C
Normal file
@ -0,0 +1,63 @@
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
int f() { return 1; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct B : A<T>
|
||||
{
|
||||
int f() { return 2; }
|
||||
|
||||
using A<T>::f;
|
||||
void g()
|
||||
{
|
||||
if (A<T>::f() != 1 )
|
||||
__builtin_abort();
|
||||
|
||||
if( B<T>::f() != 2 )
|
||||
__builtin_abort();
|
||||
|
||||
if( this->f() != 2 )
|
||||
__builtin_abort();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct C
|
||||
{
|
||||
int h( int i ) { return 1; }
|
||||
int h( double d ) { return 2; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct D : private C<T>
|
||||
{
|
||||
using C<T>::h;
|
||||
int h( char c ) { return 0; }
|
||||
int h() { return 3; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
B<int> b;
|
||||
b.g();
|
||||
b.f();
|
||||
b.A<int>::f();
|
||||
b.B<int>::f();
|
||||
|
||||
D<int> d;
|
||||
if( d.h( 'a' ) != 0 )
|
||||
__builtin_abort();
|
||||
|
||||
if( d.h( 3 ) != 1 )
|
||||
__builtin_abort();
|
||||
|
||||
if( d.h( 3.14 ) != 2 )
|
||||
__builtin_abort();
|
||||
|
||||
if( d.h() != 3 )
|
||||
__builtin_abort();
|
||||
}
|
28
gcc/testsuite/g++.dg/lookup/using40.C
Normal file
28
gcc/testsuite/g++.dg/lookup/using40.C
Normal file
@ -0,0 +1,28 @@
|
||||
// { dg-do compile }
|
||||
|
||||
struct Base
|
||||
{
|
||||
void f();
|
||||
typedef int type;
|
||||
struct Type {};
|
||||
int i;
|
||||
static int j;
|
||||
};
|
||||
|
||||
struct A : Base
|
||||
{
|
||||
using Base::f; // { dg-message "previous declaration" }
|
||||
using Base::f; // { dg-error "redeclaration" }
|
||||
|
||||
using Base::type; // { dg-message "previous declaration" }
|
||||
using Base::type; // { dg-error "redeclaration" }
|
||||
|
||||
using Base::Type; // { dg-message "previous declaration" }
|
||||
using Base::Type; // { dg-error "redeclaration" }
|
||||
|
||||
using Base::i; // { dg-message "previous declaration" }
|
||||
using Base::i; // { dg-error "redeclaration" }
|
||||
|
||||
using Base::j; // { dg-message "previous declaration" }
|
||||
using Base::j; // { dg-error "redeclaration" }
|
||||
};
|
21
gcc/testsuite/g++.dg/lookup/using41.C
Normal file
21
gcc/testsuite/g++.dg/lookup/using41.C
Normal file
@ -0,0 +1,21 @@
|
||||
// { dg-do compile }
|
||||
|
||||
template <class T>
|
||||
struct Base
|
||||
{
|
||||
void f();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct A : Base<T>
|
||||
{
|
||||
using Base<T>::f; // { dg-message "previous declaration" }
|
||||
using Base<T>::f; // { dg-error "redeclaration" }
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct B : Base<T>, Base<U>
|
||||
{
|
||||
using Base<T>::f;
|
||||
using Base<U>::f;
|
||||
};
|
26
gcc/testsuite/g++.dg/lookup/using42.C
Normal file
26
gcc/testsuite/g++.dg/lookup/using42.C
Normal file
@ -0,0 +1,26 @@
|
||||
// PR c++/30195
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
struct B
|
||||
{
|
||||
void foo(T) {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct Out
|
||||
{
|
||||
struct D : B<T>, B<double>
|
||||
{
|
||||
using B<T>::foo;
|
||||
using B<double>::foo;
|
||||
void bar() { foo(3); }
|
||||
};
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Out<int>::D x;
|
||||
x.bar();
|
||||
return 0;
|
||||
}
|
28
gcc/testsuite/g++.dg/lookup/using44.C
Normal file
28
gcc/testsuite/g++.dg/lookup/using44.C
Normal file
@ -0,0 +1,28 @@
|
||||
// PR c++/30195
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
struct B
|
||||
{
|
||||
void foo(char) { __builtin_abort(); }
|
||||
void foo(short) { __builtin_abort(); }
|
||||
void foo(T) {}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct Out
|
||||
{
|
||||
struct D : B<T>, B<double>
|
||||
{
|
||||
using B<T>::foo;
|
||||
using B<double>::foo;
|
||||
void bar() { foo(3); }
|
||||
};
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Out<int>::D x;
|
||||
x.bar();
|
||||
return 0;
|
||||
}
|
33
gcc/testsuite/g++.dg/lookup/using45.C
Normal file
33
gcc/testsuite/g++.dg/lookup/using45.C
Normal file
@ -0,0 +1,33 @@
|
||||
// PR c++/30195
|
||||
// { dg-do run }
|
||||
|
||||
template <class T>
|
||||
struct A
|
||||
{
|
||||
int f(int) { return 0; }
|
||||
int f(double) { return 1; }
|
||||
int f(char) { return 2; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct B : A<T>
|
||||
{
|
||||
using A<T>::f;
|
||||
int f(int) { return 3; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
B<int> b;
|
||||
if( b.f( 42 ) != 3 )
|
||||
__builtin_abort();
|
||||
|
||||
if( b.f( 3.14 ) != 1 )
|
||||
__builtin_abort();
|
||||
|
||||
if( b.f( 'a' ) != 2 )
|
||||
__builtin_abort();
|
||||
|
||||
if( b.A<int>::f( 42 ) != 0 )
|
||||
__builtin_abort();
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
struct A
|
||||
{
|
||||
int i; // { dg-error "conflicts" }
|
||||
int i; // { dg-message "previous" }
|
||||
A() i() {} // { dg-error "declaration" }
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
template <class R>
|
||||
struct A {
|
||||
static int _test; // { dg-error "" }
|
||||
static int _test; // { dg-message "" }
|
||||
static int _test; // { dg-error "" }
|
||||
};
|
||||
template <class R> int A<R>::_test = 0;
|
||||
|
@ -12,7 +12,7 @@ template <typename T> struct A
|
||||
|
||||
template <typename T> struct B
|
||||
{
|
||||
typedef int xxx; // { dg-error "" }
|
||||
typedef int xxx; // { dg-message "" }
|
||||
typedef T xxx; // { dg-error "" }
|
||||
typedef typename A<T>::type xxx; // { dg-error "" }
|
||||
typedef A<int>::type xxx; // { dg-error "" }
|
||||
|
@ -7,24 +7,25 @@
|
||||
|
||||
template <class T>
|
||||
struct Foo {
|
||||
int i; // { dg-error "Foo" }
|
||||
int i;
|
||||
};
|
||||
|
||||
struct Baz
|
||||
{
|
||||
int i; // { dg-error "Baz" }
|
||||
int i;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct Bar : public Foo<T>, Baz {
|
||||
using Foo<T>::i;
|
||||
using Baz::i;
|
||||
struct Bar : public Foo<T>, Baz
|
||||
{
|
||||
using Foo<T>::i; // { dg-message "previous declaration" }
|
||||
using Baz::i; // { dg-error "redeclaration" }
|
||||
|
||||
int foo () { return i; } // { dg-error "request for member" }
|
||||
int foo () { return i; }
|
||||
};
|
||||
|
||||
void foo (Bar<int> &bar)
|
||||
{
|
||||
bar.foo(); // { dg-message "required" }
|
||||
bar.foo();
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,11 @@
|
||||
class X {
|
||||
public:
|
||||
enum e {
|
||||
New // { dg-error "conflicts with previous" }
|
||||
New // { dg-message "previous" }
|
||||
, // { dg-error "comma at end" "" { target c++98 } }
|
||||
};
|
||||
|
||||
static int New(int); // { dg-error "declaration of" }
|
||||
static int New(int); // { dg-error "conflicts with a previous" }
|
||||
};
|
||||
|
||||
int main() {}
|
||||
|
@ -23,12 +23,12 @@ int global1 (); // { dg-error "" } xref for below
|
||||
int global1; // { dg-error "" } caught
|
||||
|
||||
struct struct_0 {
|
||||
int class_local (); // { dg-error "" }
|
||||
int class_local (); // { dg-message "" }
|
||||
int class_local; // { dg-error "" }
|
||||
};
|
||||
|
||||
struct struct_1 {
|
||||
int class_local; // { dg-error "" }
|
||||
int class_local; // { dg-message "" }
|
||||
int class_local (); // { dg-error "" }
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// { dg-do assemble }
|
||||
struct A {
|
||||
int a(); // { dg-error "" }
|
||||
int a(); // { dg-message "" }
|
||||
int a; // { dg-error "" }
|
||||
};
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
struct A {
|
||||
union {
|
||||
int a; // { dg-error "" } conflicts with previous declaration
|
||||
int a; // { dg-message "" } conflicts with previous declaration
|
||||
};
|
||||
int a; // { dg-error "" }
|
||||
};
|
||||
|
||||
struct B {
|
||||
int b; // { dg-error "" } conflicts with previous declaration
|
||||
int b; // { dg-message "" } conflicts with previous declaration
|
||||
union {
|
||||
int b; // { dg-error "" } duplicate member
|
||||
};
|
||||
@ -16,7 +16,7 @@ struct B {
|
||||
|
||||
struct C {
|
||||
union {
|
||||
int c; // { dg-error "" } conflicts with previous declaration
|
||||
int c; // { dg-message "" } conflicts with previous declaration
|
||||
};
|
||||
union {
|
||||
int c; // { dg-error "" } duplicate member
|
||||
|
@ -1,6 +1,6 @@
|
||||
// { dg-do assemble }
|
||||
struct X{
|
||||
void i();
|
||||
void i(int); // { dg-error "" }
|
||||
void i(int); // { dg-message "" }
|
||||
int i; // { dg-error "" } conflict
|
||||
};
|
||||
|
@ -8,13 +8,13 @@ typedef int I;
|
||||
// invalid.
|
||||
|
||||
struct A {
|
||||
typedef int I; // { dg-error "" }
|
||||
typedef int I; // { dg-message "" }
|
||||
typedef int I; // { dg-error "" }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct S {
|
||||
typedef int I; // { dg-error "" }
|
||||
typedef int I; // { dg-message "" }
|
||||
typedef int I; // { dg-error "" }
|
||||
};
|
||||
|
||||
|
@ -16,12 +16,12 @@ public:
|
||||
using B::b;
|
||||
};
|
||||
|
||||
class D2 : public B { // { dg-error "" } conflicting access specifications
|
||||
class D2 : public B {
|
||||
public:
|
||||
using B::a;
|
||||
using B::b;
|
||||
using B::b; // { dg-message "" } conflicting declaration
|
||||
|
||||
private:
|
||||
using B::b;
|
||||
using B::b; // { dg-error "" } conflicts
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user