Commit 5c44cef5 by Nathan Sidwell

[C++ PATCH] Merge some using-decl handling

https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00971.html
	gcc/cp/
	* name-lookup.c (lookup_using_decl): New function, merged from ...
	(do_class_using_decl): ... here.  Call it.  And ...
	(finish_nonmember_using_decl): ... here.  Call it.

	gcc/testsuite/
	* g++.dg/cpp0x/using-enum-2.C: Adjust expected error text.
	* g++.dg/cpp0x/using-enum-3.C: Likewise.
	* g++.dg/lookup/using4.C: Likewise.
	* g++.dg/lookup/using7.C: Likewise.
	* g++.dg/template/using12.C: Likewise.
	* g++.dg/template/using18.C: Likewise.
	* g++.dg/template/using22.C: Likewise.

From-SVN: r278106
parent 3c72b04b
2019-11-12 Nathan Sidwell <nathan@acm.org>
* name-lookup.c (lookup_using_decl): New function, merged from ...
(do_class_using_decl): ... here. Call it. And ...
(finish_nonmember_using_decl): ... here. Call it.
2019-11-12 Martin Liska <mliska@suse.cz>
* name-lookup.c: Do not include params.h.
......@@ -5,9 +11,9 @@
2019-11-12 Martin Liska <mliska@suse.cz>
* name-lookup.c (namespace_hints::namespace_hints): Replace old parameter syntax
with the new one, include opts.h if needed. Use SET_OPTION_IF_UNSET
macro.
* name-lookup.c (namespace_hints::namespace_hints): Replace old
parameter syntax with the new one, include opts.h if needed. Use
SET_OPTION_IF_UNSET macro.
* typeck.c (comptypes): Likewise.
2019-11-12 Maciej W. Rozycki <macro@codesourcery.com>
......
......@@ -4584,102 +4584,166 @@ push_class_level_binding (tree name, tree x)
return ret;
}
/* Process "using SCOPE::NAME" in a class scope. Return the
USING_DECL created. */
/* Process and lookup a using decl SCOPE::lookup.name, filling in
lookup.values & lookup.type. Return true if ok. */
tree
do_class_using_decl (tree scope, tree name)
static bool
lookup_using_decl (tree scope, name_lookup &lookup)
{
if (name == error_mark_node)
return NULL_TREE;
tree current = current_scope ();
bool dependent_p = false;
if (!scope || !TYPE_P (scope))
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
/* Naming a namespace member. */
if (TYPE_P (current))
{
error ("using-declaration for non-member at class scope");
return false;
}
/* Make sure the name is not invalid */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("%<%T::%D%> names destructor", scope, name);
return NULL_TREE;
qualified_namespace_lookup (scope, &lookup);
}
/* Using T::T declares inheriting ctors, even if T is a typedef. */
if (MAYBE_CLASS_TYPE_P (scope)
&& (name == TYPE_IDENTIFIER (scope)
|| constructor_name_p (name, scope)))
else if (TREE_CODE (scope) == ENUMERAL_TYPE)
{
maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
name = ctor_identifier;
CLASSTYPE_NON_AGGREGATE (current_class_type) = true;
TYPE_HAS_USER_CONSTRUCTOR (current_class_type) = true;
error ("using-declaration may not name enumerator %<%E::%D%>",
scope, lookup.name);
return false;
}
/* Cannot introduce a constructor name. */
if (constructor_name_p (name, current_class_type))
else
{
error ("%<%T::%D%> names constructor in %qT",
scope, name, current_class_type);
return NULL_TREE;
}
/* Naming a class member. */
if (!TYPE_P (current))
{
error ("using-declaration for member at non-class scope");
return false;
}
/* From [namespace.udecl]:
/* Make sure the name is not invalid */
if (TREE_CODE (lookup.name) == BIT_NOT_EXPR)
{
error ("%<%T::%D%> names destructor", scope, lookup.name);
return false;
}
A using-declaration used as a member-declaration shall refer to a
member of a base class of the class being defined.
/* Using T::T declares inheriting ctors, even if T is a typedef. */
if (MAYBE_CLASS_TYPE_P (scope)
&& (lookup.name == TYPE_IDENTIFIER (scope)
|| constructor_name_p (lookup.name, scope)))
{
maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
lookup.name = ctor_identifier;
CLASSTYPE_NON_AGGREGATE (current) = true;
TYPE_HAS_USER_CONSTRUCTOR (current) = true;
}
/* Cannot introduce a constructor name. */
if (constructor_name_p (lookup.name, current))
{
error ("%<%T::%D%> names constructor in %qT",
scope, lookup.name, current);
return false;
}
In general, we cannot check this constraint in a template because
we do not know the entire set of base classes of the current
class type. Morover, if SCOPE is dependent, it might match a
non-dependent base. */
/* Member using decls finish processing when completing the
class. */
/* From [namespace.udecl]:
tree decl = NULL_TREE;
if (!dependent_scope_p (scope))
{
base_kind b_kind;
tree binfo = lookup_base (current_class_type, scope, ba_any, &b_kind,
tf_warning_or_error);
if (b_kind < bk_proper_base)
A using-declaration used as a member-declaration shall refer
to a member of a base class of the class being defined.
In general, we cannot check this constraint in a template
because we do not know the entire set of base classes of the
current class type. Morover, if SCOPE is dependent, it might
match a non-dependent base. */
dependent_p = dependent_scope_p (scope);
if (!dependent_p)
{
/* If there are dependent bases, scope might resolve at
instantiation time, even if it isn't exactly one of the
dependent bases. */
if (b_kind == bk_same_type || !any_dependent_bases_p ())
base_kind b_kind;
tree binfo = lookup_base (current, scope, ba_any, &b_kind,
tf_warning_or_error);
if (b_kind < bk_proper_base)
{
/* If there are dependent bases, scope might resolve at
instantiation time, even if it isn't exactly one of
the dependent bases. */
if (b_kind == bk_same_type || !any_dependent_bases_p ())
{
error_not_base_type (scope, current);
return false;
}
/* Treat as-if dependent. */
dependent_p = true;
}
else if (lookup.name == ctor_identifier && !binfo_direct_p (binfo))
{
error_not_base_type (scope, current_class_type);
return NULL_TREE;
error ("cannot inherit constructors from indirect base %qT",
scope);
return false;
}
else if (IDENTIFIER_CONV_OP_P (lookup.name)
&& dependent_type_p (TREE_TYPE (lookup.name)))
dependent_p = true;
else
lookup.value = lookup_member (binfo, lookup.name, 0,
false, tf_warning_or_error);
}
else if (name == ctor_identifier && !binfo_direct_p (binfo))
}
if (!dependent_p)
{
if (!lookup.value)
{
error ("cannot inherit constructors from indirect base %qT", scope);
return NULL_TREE;
error ("%qD has not been declared in %qE", lookup.name, scope);
return false;
}
else if (!IDENTIFIER_CONV_OP_P (name)
|| !dependent_type_p (TREE_TYPE (name)))
if (TREE_CODE (lookup.value) == TREE_LIST
/* We can (independently) have ambiguous implicit typedefs. */
|| (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
{
decl = lookup_member (binfo, name, 0, false, tf_warning_or_error);
if (!decl)
{
error ("no members matching %<%T::%D%> in %q#T", scope, name,
scope);
return NULL_TREE;
}
error ("reference to %qD is ambiguous", lookup.name);
print_candidates (TREE_CODE (lookup.value) == TREE_LIST
? lookup.value : lookup.type);
return false;
}
/* The binfo from which the functions came does not matter. */
if (BASELINK_P (decl))
decl = BASELINK_FUNCTIONS (decl);
if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
{
error ("using-declaration may not name namespace %qD", lookup.value);
return false;
}
}
tree value = build_lang_decl (USING_DECL, name, NULL_TREE);
USING_DECL_DECLS (value) = decl;
USING_DECL_SCOPE (value) = scope;
DECL_DEPENDENT_P (value) = !decl;
return true;
}
/* Process "using SCOPE::NAME" in a class scope. Return the
USING_DECL created. */
tree
do_class_using_decl (tree scope, tree name)
{
if (name == error_mark_node
|| scope == error_mark_node)
return NULL_TREE;
name_lookup lookup (name, 0);
if (!lookup_using_decl (scope, lookup))
return NULL_TREE;
tree found = lookup.value;
if (found && BASELINK_P (found))
/* The binfo from which the functions came does not matter. */
found = BASELINK_FUNCTIONS (found);
tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
USING_DECL_SCOPE (using_decl) = scope;
USING_DECL_DECLS (using_decl) = found;
DECL_DEPENDENT_P (using_decl) = !found;
return value;
return using_decl;
}
......@@ -5046,39 +5110,14 @@ void
finish_nonmember_using_decl (tree scope, tree name)
{
gcc_checking_assert (current_binding_level->kind != sk_class);
gcc_checking_assert (identifier_p (name));
name_lookup lookup (name, 0);
if (TREE_CODE (scope) != NAMESPACE_DECL)
{
error ("%qE is not a namespace or unscoped enum", scope);
return;
}
qualified_namespace_lookup (scope, &lookup);
if (!lookup.value)
{
error ("%qD has not been declared in %qE", name, scope);
return;
}
if (scope == error_mark_node || name == error_mark_node)
return;
if (TREE_CODE (lookup.value) == TREE_LIST
/* But we can (independently) have ambiguous implicit typedefs. */
|| (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
{
error ("reference to %qD is ambiguous", name);
print_candidates (TREE_CODE (lookup.value) == TREE_LIST
? lookup.value : lookup.type);
return;
}
name_lookup lookup (name, 0);
if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
{
error ("using-declaration may not name namespace %qD", lookup.value);
return;
}
if (!lookup_using_decl (scope, lookup))
return;
/* Emit debug info. */
if (!processing_template_decl)
......@@ -5106,7 +5145,7 @@ finish_nonmember_using_decl (tree scope, tree name)
}
else
{
tree using_decl = build_lang_decl (USING_DECL, name, NULL_TREE);
tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
USING_DECL_SCOPE (using_decl) = scope;
add_decl_expr (using_decl);
......@@ -5147,7 +5186,6 @@ finish_nonmember_using_decl (tree scope, tree name)
set_identifier_type_value (name, type);
}
}
}
/* Return the declarations that are members of the namespace NS. */
......
2019-11-12 Nathan Sidwell <nathan@acm.org>
* g++.dg/cpp0x/using-enum-2.C: Adjust expected error text.
* g++.dg/cpp0x/using-enum-3.C: Likewise.
* g++.dg/lookup/using4.C: Likewise.
* g++.dg/lookup/using7.C: Likewise.
* g++.dg/template/using12.C: Likewise.
* g++.dg/template/using18.C: Likewise.
* g++.dg/template/using22.C: Likewise.
2019-11-12 Segher Boessenkool <segher@kernel.crashing.org>
PR target/92449
......
......@@ -5,16 +5,16 @@ namespace A
{
enum class E { V };
using E::V; // { dg-error "not a namespace or unscoped enum" }
using E::V; // { dg-error "name enumerator" }
}
void foo()
{
using A::E::V; // { dg-error "not a namespace or unscoped enum" }
using A::E::V; // { dg-error "name enumerator" }
}
using A::E::V; // { dg-error "not a namespace or unscoped enum" }
using A::E::V; // { dg-error "name enumerator" }
enum class F { U };
using F::U; // { dg-error "not a namespace or unscoped enum" }
using F::U; // { dg-error "name enumerator" }
......@@ -4,7 +4,7 @@
void f ()
{
enum e { a };
using e::a; // { dg-error "not a namespace or unscoped enum" }
using e::a; // { dg-error "name enumerator" }
}
struct S {
......
......@@ -10,6 +10,6 @@ template <class T>
struct Bar : public Foo<T> {
void foo()
{
using Foo<T>::i; // { dg-error "not a namespace" }
using Foo<T>::i; // { dg-error "member at non-class scope" }
}
};
......@@ -6,7 +6,6 @@ template <typename T, bool=T::X> struct A
template <typename T> struct B : A<T> // { dg-error "incomplete" }
{
using A<T>::i; // { dg-error "incomplete" "incomplete" }
// { dg-error "using" "using" { target *-*-* } .-1 }
};
B<void> b; // { dg-message "required" }
......@@ -3,5 +3,5 @@ struct A {
template <typename T>
struct S : public A {
using A::operator(); // { dg-error "no member" }
using A::operator(); // { dg-error "has not been declared" }
};
......@@ -25,7 +25,7 @@ template <class T> struct B2 {};
template <class T>
struct C : B1, B2<T>
{
using B1::x; // { dg-error "no member" }
using B1::x; // { dg-error "has not been declared" }
using B2<T>::y;
using typename B2<T>::type;
};
......@@ -16,25 +16,25 @@ struct A
template <class T>
struct A<T>::B : A<T>
{
using A::nonexist; // { dg-error "no members matching" }
using A::nonexist; // { dg-error "has not been declared" }
};
template <class T>
struct A<T>::C : A
{
using A::nonexist; // { dg-error "no members matching" }
using A::nonexist; // { dg-error "has not been declared" }
};
template <class T>
struct A<T>::D : A<T>
{
using A<T>::nonexist; // { dg-error "no members matching" }
using A<T>::nonexist; // { dg-error "has not been declared" }
};
template <class T>
struct A<T>::E : A
{
using A<T>::nonexist; // { dg-error "no members matching" }
using A<T>::nonexist; // { dg-error "has not been declared" }
};
template <class T>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment