Hi,
The problem here is that the use of an elaborated-type-specifier
(introduced via 'struct') does not find USING_DECLs, whereas it does
for a simple-type-specifier. That's caused by xref_tag (through
lookup_and_check_tag) that does not strip USING_DECLs and thus fails
to return a type when it happens to be the target of the USING_DECL.
Unfortunately, just stripping the USING_DECL in lookup_and_check_tag
does not really work because some diagnotic codes expect the
USING_DECL not to be stripped.
Consequently, I have fixed it by introcucing a new parameter to
xref_tag whose purpose is to know if stripping USING_DECLs is
desirable. Not very exciting to fix it this way, but that is the only
solution I managed to find.
Tested x86_64 linux without regressions. OK to commit to trunk ? And
branches after some weeks of incubation ?
gcc/cp/ChangeLog
2014-09-24 Fabien Chêne <[email protected]>
* cp-tree.h (xref_tag): Add a new bool parameter.
* parser.c (cp_parser_elaborated_type_specifier): Call xref_tag
with strip_using_p set to true.
(cp_parser_class_head): Call xref_tag with strip_using_p set to
false.
* rtti.c (init_rtti_processing): Likewise.
(build_dynamic_cast_1): Likewise.
(tinfo_base_init): Likewise.
(emit_support_tinfos): Likewise.
* lambda.c (begin_lambda_type): Likewise.
(vla_capture_type): Likewise.
* decl.c (lookup_and_check_tag): Add a new bool parameter. Strip
the USING_DECL if strip_using_p is set. Declare the variable t at
the use.
(xref_tag_1): Add a new bool parameter. Forward strip_using_p to
lookup_and_check_tag.
(xref_tag): Add a new bool parameter. Forward strip_using_p to
xref_tag_1.
(xref_tag_from_type): Call xref_tag with strip_using_p set to
false.
(start_enum): Call lookup_and_check_tag with strip_using_p set to
false. Call xref_tag with strip_using_p set to false.
gcc/testsuite/ChangeLog
2014-09-24 Fabien Chêne <[email protected]>
PR c++/56243
* g++.dg/lookup/using56.C: New.
--
Fabien
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (révision 209870)
+++ gcc/cp/parser.c (copie de travail)
@@ -15202,7 +15202,8 @@ cp_parser_elaborated_type_specifier (cp_
token->location,
/*declarator=*/NULL))
return error_mark_node;
- type = xref_tag (tag_type, identifier, ts, template_p);
+ type = xref_tag (tag_type, identifier, ts, template_p,
+ /*strip_using_p=*/true);
}
}
@@ -19930,7 +19931,7 @@ cp_parser_class_head (cp_parser* parser,
if (!id)
id = make_anon_name ();
type = xref_tag (class_key, id, /*tag_scope=*/ts_current,
- parser->num_template_parameter_lists);
+ parser->num_template_parameter_lists, false);
}
/* Indicate whether this class was declared as a `class' or as a
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (révision 209870)
+++ gcc/cp/cp-tree.h (copie de travail)
@@ -5245,7 +5245,8 @@ extern tree get_scope_of_declarator (co
extern void grok_special_member_properties (tree);
extern int grok_ctor_properties (const_tree, const_tree);
extern bool grok_op_properties (tree, bool);
-extern tree xref_tag (enum tag_types, tree, tag_scope, bool);
+extern tree xref_tag (enum tag_types, tree, tag_scope,
+ bool, bool);
extern tree xref_tag_from_type (tree, tree, tag_scope);
extern bool xref_basetypes (tree, tree);
extern tree start_enum (tree, tree, tree, bool, bool *);
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c (révision 209870)
+++ gcc/cp/decl.c (copie de travail)
@@ -92,7 +92,7 @@ static int typename_compare (const void
static tree local_variable_p_walkfn (tree *, int *, void *);
static tree record_builtin_java_type (const char *, int);
static const char *tag_name (enum tag_types);
-static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
+static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool, bool);
static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
static void maybe_deduce_size_from_array_init (tree, tree);
static void layout_var_decl (tree);
@@ -11944,9 +11944,9 @@ check_elaborated_type_specifier (enum ta
static tree
lookup_and_check_tag (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ tag_scope scope, bool template_header_p,
+ bool strip_using_p)
{
- tree t;
tree decl;
if (scope == ts_global)
{
@@ -11973,6 +11973,9 @@ lookup_and_check_tag (enum tag_types tag
&& DECL_TEMPLATE_TEMPLATE_PARM_P (decl))))
decl = DECL_TEMPLATE_RESULT (decl);
+ if (strip_using_p)
+ decl = strip_using_decl (decl);
+
if (decl && TREE_CODE (decl) == TYPE_DECL)
{
/* Look for invalid nested type:
@@ -12003,10 +12006,10 @@ lookup_and_check_tag (enum tag_types tag
class C *c2; // DECL_SELF_REFERENCE_P is true
}; */
- t = check_elaborated_type_specifier (tag_code,
- decl,
- template_header_p
- | DECL_SELF_REFERENCE_P (decl));
+ tree t = check_elaborated_type_specifier (tag_code,
+ decl,
+ template_header_p
+ | DECL_SELF_REFERENCE_P (decl));
return t;
}
else if (decl && TREE_CODE (decl) == TREE_LIST)
@@ -12036,7 +12039,8 @@ lookup_and_check_tag (enum tag_types tag
static tree
xref_tag_1 (enum tag_types tag_code, tree name,
- tag_scope orig_scope, bool template_header_p)
+ tag_scope orig_scope, bool template_header_p,
+ bool strip_using_p)
{
enum tree_code code;
tree t;
@@ -12072,7 +12076,8 @@ xref_tag_1 (enum tag_types tag_code, tre
t = NULL_TREE;
else
t = lookup_and_check_tag (tag_code, name,
- scope, template_header_p);
+ scope, template_header_p,
+ strip_using_p);
if (t == error_mark_node)
return error_mark_node;
@@ -12184,12 +12189,14 @@ xref_tag_1 (enum tag_types tag_code, tre
tree
xref_tag (enum tag_types tag_code, tree name,
- tag_scope scope, bool template_header_p)
+ tag_scope scope, bool template_header_p,
+ bool strip_using_p)
{
tree ret;
bool subtime;
subtime = timevar_cond_start (TV_NAME_LOOKUP);
- ret = xref_tag_1 (tag_code, name, scope, template_header_p);
+ ret = xref_tag_1 (tag_code, name, scope, template_header_p,
+ strip_using_p);
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
return ret;
}
@@ -12208,7 +12215,7 @@ xref_tag_from_type (tree old, tree id, t
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
- return xref_tag (tag_kind, id, scope, false);
+ return xref_tag (tag_kind, id, scope, false, false);
}
/* Create the binfo hierarchy for REF with (possibly NULL) base list
@@ -12490,7 +12497,8 @@ start_enum (tree name, tree enumtype, tr
if (!enumtype)
enumtype = lookup_and_check_tag (enum_type, name,
/*tag_scope=*/ts_current,
- /*template_header_p=*/false);
+ /*template_header_p=*/false,
+ /*strip_using_p=*/false);
/* In case of a template_decl, the only check that should be deferred
to instantiation time is the comparison of underlying types. */
@@ -12562,7 +12570,7 @@ start_enum (tree name, tree enumtype, tr
}
else
enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
- false);
+ false, false);
if (enumtype == error_mark_node)
return error_mark_node;
Index: gcc/cp/lambda.c
===================================================================
--- gcc/cp/lambda.c (révision 209870)
+++ gcc/cp/lambda.c (copie de travail)
@@ -138,7 +138,8 @@ begin_lambda_type (tree lambda)
type = xref_tag (/*tag_code=*/record_type,
name,
/*scope=*/ts_lambda,
- /*template_header_p=*/false);
+ /*template_header_p=*/false,
+ /*strip_using_p=*/false);
if (type == error_mark_node)
return error_mark_node;
}
@@ -416,7 +417,7 @@ static tree
vla_capture_type (tree array_type)
{
static tree ptr_id, max_id;
- tree type = xref_tag (record_type, make_anon_name (), ts_current, false);
+ tree type = xref_tag (record_type, make_anon_name (), ts_current, false, false);
xref_basetypes (type, NULL_TREE);
type = begin_class_definition (type);
if (!ptr_id)
Index: gcc/cp/rtti.c
===================================================================
--- gcc/cp/rtti.c (révision 209870)
+++ gcc/cp/rtti.c (copie de travail)
@@ -152,7 +152,7 @@ init_rtti_processing (void)
push_namespace (std_identifier);
type_info_type = xref_tag (class_type, get_identifier ("type_info"),
- /*tag_scope=*/ts_current, false);
+ /*tag_scope=*/ts_current, false, false);
pop_namespace ();
const_type_info_type_node
= cp_build_qualified_type (type_info_type, TYPE_QUAL_CONST);
@@ -731,7 +731,7 @@ build_dynamic_cast_1 (tree type, tree ex
push_abi_namespace ();
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
- /*tag_scope=*/ts_current, false);
+ /*tag_scope=*/ts_current, false, false);
tinfo_ptr = build_pointer_type
(cp_build_qualified_type
@@ -913,7 +913,7 @@ tinfo_base_init (tinfo_s *ti, tree targe
tree real_type;
push_abi_namespace ();
real_type = xref_tag (class_type, ti->name,
- /*tag_scope=*/ts_current, false);
+ /*tag_scope=*/ts_current, false, false);
pop_abi_namespace ();
if (!COMPLETE_TYPE_P (real_type))
@@ -1536,7 +1536,7 @@ emit_support_tinfos (void)
push_abi_namespace ();
bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"),
- /*tag_scope=*/ts_current, false);
+ /*tag_scope=*/ts_current, false, false);
pop_abi_namespace ();
if (!COMPLETE_TYPE_P (bltn_type))
return;
Index: gcc/testsuite/g++.dg/lookup/using54.C
===================================================================
--- gcc/testsuite/g++.dg/lookup/using54.C (révision 0)
+++ gcc/testsuite/g++.dg/lookup/using54.C (révision 0)
@@ -0,0 +1,16 @@
+// PR c++/60894
+
+struct B
+{
+ struct S {};
+};
+
+struct D : B
+{
+ using B::S;
+ void doIt(struct S&);
+};
+
+void D::doIt(struct S&)
+{
+}