aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@gcc.gnu.org>2019-11-12 21:21:13 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2019-11-12 21:21:13 +0000
commit5c44cef5f5610e48cce17e8d085636c18f308363 (patch)
treec4bf6c5ddc18d6176e8364d4344586e831cd3a7e /gcc
parent3c72b04bf1b21ef6256844d06fd7e7b2db318eab (diff)
downloadgcc-5c44cef5f5610e48cce17e8d085636c18f308363.zip
gcc-5c44cef5f5610e48cce17e8d085636c18f308363.tar.gz
gcc-5c44cef5f5610e48cce17e8d085636c18f308363.tar.bz2
[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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/name-lookup.c244
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/using-enum-2.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/using-enum-3.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/using4.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/using7.C1
-rw-r--r--gcc/testsuite/g++.dg/template/using12.C2
-rw-r--r--gcc/testsuite/g++.dg/template/using18.C2
-rw-r--r--gcc/testsuite/g++.dg/template/using22.C8
10 files changed, 172 insertions, 119 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3742e71..bf50b1b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+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>
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d114c88..b399b4e 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5572093..a03b684 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+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
diff --git a/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C b/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
index 0738c80..faa3817 100644
--- a/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/using-enum-2.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C b/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
index edc1689..ecc4ddc 100644
--- a/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/using-enum-3.C
@@ -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 {
diff --git a/gcc/testsuite/g++.dg/lookup/using4.C b/gcc/testsuite/g++.dg/lookup/using4.C
index a6421c8..facb2b4 100644
--- a/gcc/testsuite/g++.dg/lookup/using4.C
+++ b/gcc/testsuite/g++.dg/lookup/using4.C
@@ -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" }
}
};
diff --git a/gcc/testsuite/g++.dg/lookup/using7.C b/gcc/testsuite/g++.dg/lookup/using7.C
index f774021..d92bf23 100644
--- a/gcc/testsuite/g++.dg/lookup/using7.C
+++ b/gcc/testsuite/g++.dg/lookup/using7.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/template/using12.C b/gcc/testsuite/g++.dg/template/using12.C
index cebfab1..0b65235 100644
--- a/gcc/testsuite/g++.dg/template/using12.C
+++ b/gcc/testsuite/g++.dg/template/using12.C
@@ -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" }
};
diff --git a/gcc/testsuite/g++.dg/template/using18.C b/gcc/testsuite/g++.dg/template/using18.C
index b4ef6df..caafdcf 100644
--- a/gcc/testsuite/g++.dg/template/using18.C
+++ b/gcc/testsuite/g++.dg/template/using18.C
@@ -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;
};
diff --git a/gcc/testsuite/g++.dg/template/using22.C b/gcc/testsuite/g++.dg/template/using22.C
index 9ea3d8a..041b5c1 100644
--- a/gcc/testsuite/g++.dg/template/using22.C
+++ b/gcc/testsuite/g++.dg/template/using22.C
@@ -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>