Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
A class using-declaration followed by a class definition is not a
redefinition, but a conflict of two different kinds of declaration.
PR c++/115806
gcc/cp/ChangeLog:
* decl.cc (lookup_and_check_tag): Strip using here...
* name-lookup.cc (lookup_elaborated_type): ...not here.
gcc/testsuite/ChangeLog:
* g++.dg/lookup/using29.C: Adjust diagnostics.
* g++.dg/lookup/using68.C: Likewise.
* g++.dg/modules/using-19_b.C: Likewise.
* g++.dg/lookup/using53.C: Remove xfails.
---
gcc/cp/decl.cc | 14 ++++++++++++++
gcc/cp/name-lookup.cc | 12 ++++++------
gcc/testsuite/g++.dg/lookup/using29.C | 4 ++--
gcc/testsuite/g++.dg/lookup/using53.C | 18 ++++++++----------
gcc/testsuite/g++.dg/lookup/using68.C | 6 +++---
gcc/testsuite/g++.dg/modules/using-19_b.C | 4 ++--
6 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 067ae20c828..24c5f0337b9 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -18490,6 +18490,20 @@ lookup_and_check_tag (enum tag_types tag_code, tree
name,
|| (how != TAG_how::CURRENT_ONLY && DECL_TEMPLATE_TEMPLATE_PARM_P
(decl)))
decl = DECL_TEMPLATE_RESULT (decl);
+ if (TREE_CODE (decl) == USING_DECL)
+ {
+ tree u = decl;
+ decl = strip_using_decl (decl);
+ if (how == TAG_how::CURRENT_ONLY)
+ {
+ auto_diagnostic_group _;
+ error ("%qD conflicts with a previous declaration", name);
+ inform (location_of (u), "previous declaration %qD", u);
+ inform (location_of (decl), "%qD declared here", decl);
+ return error_mark_node;
+ }
+ }
+
if (TREE_CODE (decl) != TYPE_DECL)
/* Found not-a-type. */
return NULL_TREE;
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index f89f5643d86..183ea403ef8 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8492,7 +8492,7 @@ lookup_elaborated_type (tree name, TAG_how how)
typedef struct C {} C;
correctly. */
- if (tree type = strip_using_decl (iter->type))
+ if (tree type = iter->type)
{
if (qualify_lookup (type, LOOK_want::TYPE)
&& (how != TAG_how::CURRENT_ONLY
@@ -8508,7 +8508,7 @@ lookup_elaborated_type (tree name, TAG_how how)
}
else
{
- tree value = strip_using_decl (iter->value);
+ tree value = iter->value;
if (qualify_lookup (value, LOOK_want::TYPE)
&& (how != TAG_how::CURRENT_ONLY
|| !INHERITED_VALUE_BINDING_P (iter)))
@@ -8548,7 +8548,7 @@ lookup_elaborated_type (tree name, TAG_how how)
if (bind)
{
/* If this is the kind of thing we're looking for, we're done. */
- if (tree type = strip_using_decl (MAYBE_STAT_TYPE (bind)))
+ if (tree type = MAYBE_STAT_TYPE (bind))
{
if (how != TAG_how::HIDDEN_FRIEND)
/* No longer hidden. */
@@ -8556,7 +8556,7 @@ lookup_elaborated_type (tree name, TAG_how how)
return type;
}
- else if (tree decl = strip_using_decl (MAYBE_STAT_DECL (bind)))
+ else if (tree decl = MAYBE_STAT_DECL (bind))
{
if (qualify_lookup (decl, LOOK_want::TYPE))
{
@@ -8637,10 +8637,10 @@ lookup_elaborated_type (tree name, TAG_how how)
}
if (type && qualify_lookup (type, LOOK_want::TYPE))
- return strip_using_decl (type);
+ return type;
if (bind && qualify_lookup (bind, LOOK_want::TYPE))
- return strip_using_decl (bind);
+ return bind;
}
if (!module_purview_p ())
diff --git a/gcc/testsuite/g++.dg/lookup/using29.C
b/gcc/testsuite/g++.dg/lookup/using29.C
index 697a654aacb..e11f39c5840 100644
--- a/gcc/testsuite/g++.dg/lookup/using29.C
+++ b/gcc/testsuite/g++.dg/lookup/using29.C
@@ -51,7 +51,7 @@ struct I2 : H
struct J
{
- struct type {}; // { dg-message "previous" }
+ struct type {}; // { dg-message "here" }
};
struct K : J
@@ -63,7 +63,7 @@ struct K : J
struct L : J
{
using J::type;
- struct type {}; // { dg-error "redefinition" }
+ struct type {}; // { dg-error "conflicts" }
};
struct M
diff --git a/gcc/testsuite/g++.dg/lookup/using53.C
b/gcc/testsuite/g++.dg/lookup/using53.C
index 8279c73bfc4..e6a82243715 100644
--- a/gcc/testsuite/g++.dg/lookup/using53.C
+++ b/gcc/testsuite/g++.dg/lookup/using53.C
@@ -1,23 +1,21 @@
// PR c++/20420
-// FIXME: These error messages aren't great, rather than multiple definition
-// we should talk about conflicting declarations with the using-decl.
class B
{
protected:
- enum E { E1, E2, E3 }; // { dg-message "previous" }
- struct S { int i; E e; }; // { dg-message "previous" }
+ enum E { E1, E2, E3 }; // { dg-message "here" }
+ struct S { int i; E e; }; // { dg-message "here" }
};
class D : private B
{
public:
- using B::E;
- using B::S;
+ using B::E; // { dg-message "previous" }
+ using B::S; // { dg-message "previous" }
private:
- enum E {}; // { dg-error "multiple definition" }
- struct S {}; // { dg-error "redefinition" }
+ enum E {}; // { dg-error "conflicts" }
+ struct S {}; // { dg-error "conflicts" }
};
template<typename T>
@@ -32,11 +30,11 @@ template<typename T>
class DT : private BT<T>
{
public:
- using BT<T>::E; // { dg-message "previous" "PR c++/115806" { xfail *-*-* }
}
+ using BT<T>::E; // { dg-message "previous" }
using BT<T>::S; // { dg-message "previous" }
private:
- enum E {}; // { dg-error "conflicts" "PR c++/115806" { xfail *-*-* } }
+ enum E {}; // { dg-error "conflicts" }
struct S {}; // { dg-error "conflicts" }
};
diff --git a/gcc/testsuite/g++.dg/lookup/using68.C
b/gcc/testsuite/g++.dg/lookup/using68.C
index 6eb2be5c19c..aa9cdea1d15 100644
--- a/gcc/testsuite/g++.dg/lookup/using68.C
+++ b/gcc/testsuite/g++.dg/lookup/using68.C
@@ -1,7 +1,7 @@
// { dg-do compile }
-struct S {}; // { dg-message "previous" }
+struct S {}; // { dg-message "here" }
void foo() {
- using ::S;
- struct S {}; // { dg-error "redefinition" }
+ using ::S; // { dg-message "previous" }
+ struct S {}; // { dg-error "conflicts" }
}
diff --git a/gcc/testsuite/g++.dg/modules/using-19_b.C
b/gcc/testsuite/g++.dg/modules/using-19_b.C
index dbe8d9f3c01..9f738d0310a 100644
--- a/gcc/testsuite/g++.dg/modules/using-19_b.C
+++ b/gcc/testsuite/g++.dg/modules/using-19_b.C
@@ -3,8 +3,8 @@
import M;
namespace exposed {
- struct S {}; // { dg-error "redefinition" }
- enum E { x }; // { dg-error "multiple definition" }
+ struct S {}; // { dg-error "conflicts" }
+ enum E { x }; // { dg-error "conflicts" }
int e(); // { dg-error "redeclared" }
int f; // { dg-error "redeclared" }
}
base-commit: f73ad52c42f610dea1027342134d7ba624a291f9
--
2.55.0