diff options
Diffstat (limited to 'gcc/cp/name-lookup.c')
-rw-r--r-- | gcc/cp/name-lookup.c | 139 |
1 files changed, 101 insertions, 38 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 044a97f7157..7f6b8cdcf29 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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; - - if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)) + tree target_bval = strip_using_decl (bval); + tree target_decl = strip_using_decl (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) |