diff mbox

[C++] PR 20420

Message ID 5034D3FE.9020109@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Aug. 22, 2012, 12:43 p.m. UTC
Hi,

yesterday I had a look to this old PR and noticed that we are almost 
doing already the right thing for the original testcase: we are for 
classes, but we ICE (something recent) for enums. The latter issue seems 
easy to fix: handle specially enums at the beginning of 
supplement_binding_1 only when the comment says, that is in templates 
(otherwise we hit an assert in dependent_type_p).

Then, Comment #4 in the audit trail added a case of duplicate using 
declaration which we should also reject, involving VAR_DECLs at function 
scope (C++11 7.3.3/10). Seems also easy to fix, by checking the return 
value of validate_nonmember_using_decl at the beginning of 
do_local_using_decl and erroring out if it's null.

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////////
/cp
2012-08-22  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/20420
	* name-lookup.c (supplement_binding_1): Handle specially enums
	only in class templates. 
	(do_local_using_decl): Enforce 7.3.3/10 about duplicate using
	declarations at function scope.

/testsuite
2012-08-22  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/20420
	* g++.dg/lookup/using53.C: New.

Comments

Jason Merrill Aug. 22, 2012, 2:09 p.m. UTC | #1
On 08/22/2012 08:43 AM, Paolo Carlini wrote:
> yesterday I had a look to this old PR and noticed that we are almost
> doing already the right thing for the original testcase: we are for
> classes, but we ICE (something recent) for enums. The latter issue seems
> easy to fix: handle specially enums at the beginning of
> supplement_binding_1 only when the comment says, that is in templates
> (otherwise we hit an assert in dependent_type_p).

Which assert?  The underlying type ought to be set by the time we see a 
using, and it shouldn't be a TEMPLATE_TYPE_PARM.

> Then, Comment #4 in the audit trail added a case of duplicate using
> declaration which we should also reject, involving VAR_DECLs at function
> scope (C++11 7.3.3/10). Seems also easy to fix, by checking the return
> value of validate_nonmember_using_decl at the beginning of
> do_local_using_decl and erroring out if it's null.

Let's put the error in validate_nonmember_using_decl with the other errors.

Jason
Paolo Carlini Aug. 22, 2012, 2:14 p.m. UTC | #2
Hi,

On 08/22/2012 04:09 PM, Jason Merrill wrote:
> On 08/22/2012 08:43 AM, Paolo Carlini wrote:
>> yesterday I had a look to this old PR and noticed that we are almost
>> doing already the right thing for the original testcase: we are for
>> classes, but we ICE (something recent) for enums. The latter issue seems
>> easy to fix: handle specially enums at the beginning of
>> supplement_binding_1 only when the comment says, that is in templates
>> (otherwise we hit an assert in dependent_type_p).
>
> Which assert?  The underlying type ought to be set by the time we see 
> a using, and it shouldn't be a TEMPLATE_TYPE_PARM.
Here:

   if (!processing_template_decl)
     {
       /* If we are not processing a template, then nobody should be
      providing us with a dependent type.  */
       gcc_assert (type);
       gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto 
(type));
       return false;
     }

type is NULL_TREE. Makes sense?
>
>> Then, Comment #4 in the audit trail added a case of duplicate using
>> declaration which we should also reject, involving VAR_DECLs at function
>> scope (C++11 7.3.3/10). Seems also easy to fix, by checking the return
>> value of validate_nonmember_using_decl at the beginning of
>> do_local_using_decl and erroring out if it's null.
>
> Let's put the error in validate_nonmember_using_decl with the other 
> errors.
Ok. Indeed, I wanted to do that, but was annoyed that we cannot assume 
we are in a function, because validate_nonmember_using_decl is also 
called by do_toplevel_using_decl. I suppose I should use 
at_function_scope_p () then.

Paolo.
Paolo Carlini Aug. 22, 2012, 2:23 p.m. UTC | #3
Hi.

On 08/22/2012 04:14 PM, Paolo Carlini wrote:
> Hi,
>
> On 08/22/2012 04:09 PM, Jason Merrill wrote:
>> On 08/22/2012 08:43 AM, Paolo Carlini wrote:
>>> yesterday I had a look to this old PR and noticed that we are almost
>>> doing already the right thing for the original testcase: we are for
>>> classes, but we ICE (something recent) for enums. The latter issue 
>>> seems
>>> easy to fix: handle specially enums at the beginning of
>>> supplement_binding_1 only when the comment says, that is in templates
>>> (otherwise we hit an assert in dependent_type_p).
>>
>> Which assert?  The underlying type ought to be set by the time we see 
>> a using, and it shouldn't be a TEMPLATE_TYPE_PARM.
> Here:
>
>   if (!processing_template_decl)
>     {
>       /* If we are not processing a template, then nobody should be
>      providing us with a dependent type.  */
>       gcc_assert (type);
>       gcc_assert (TREE_CODE (type) != TEMPLATE_TYPE_PARM || is_auto 
> (type));
>       return false;
>     }
>
> type is NULL_TREE.
Like this:
#0  dependent_type_p (type=0x0) at 
/scratch/Gcc/svn-dirs/trunk/gcc/cp/pt.c:19020
#1  0x000000000073301f in supplement_binding_1 (binding=0x7ffff651c7f8, 
decl=0x7ffff6521cf0) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:448
#2  0x0000000000733a65 in supplement_binding (binding=0x7ffff651c7f8, 
decl=0x7ffff6521cf0) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:568
#3  0x000000000073e4e0 in push_class_level_binding_1 
(name=0x7ffff6534948, x=0x7ffff6521cf0) at 
/scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:3162
#4  0x000000000073e545 in push_class_level_binding (name=0x7ffff6534948, 
x=0x7ffff6521cf0) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:3180
#5  0x000000000073d753 in pushdecl_class_level (x=0x7ffff6521cf0) at 
/scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:2914
#6  0x00000000006d9538 in finish_member_declaration 
(decl=0x7ffff6521cf0) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/semantics.c:2668
#7  0x00000000007469c2 in pushtag_1 (name=0x7ffff6534948, 
type=0x7ffff6535498, scope=ts_current) at 
/scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:5787
#8  0x0000000000746d78 in pushtag (name=0x7ffff6534948, 
type=0x7ffff6535498, scope=ts_current) at 
/scratch/Gcc/svn-dirs/trunk/gcc/cp/name-lookup.c:5853
#9  0x0000000000570021 in start_enum (name=0x7ffff6534948, 
enumtype=0x7ffff6535498, underlying_type=0x0, scoped_enum_p=false, 
is_new=0x7fffffffd3f7) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/decl.c:12146
#10 0x0000000000658dfc in cp_parser_enum_specifier 
(parser=0x7ffff6534b00) at /scratch/Gcc/svn-dirs/trunk/gcc/cp/parser.c:14509

Paolo.
Paolo Carlini Aug. 22, 2012, 2:55 p.m. UTC | #4
. thus, in short, what is happening is that, for this testcase:

class B
{
protected:
   enum E { E1, E2, E3 };
};

class D : private B
{
public:
   using B::E;

private:
   enum E { };
};

we parse the new declaration enum E { }; and we reach 
supplement_binding_1 before setting the underlying type of the new 
declaration. The old declaration is fine, would not ICE dependent_type_p.

Paolo.
Jason Merrill Aug. 22, 2012, 3:13 p.m. UTC | #5
On 08/22/2012 10:55 AM, Paolo Carlini wrote:
> . thus, in short, what is happening is that, for this testcase:
>
> class B
> {
> protected:
>    enum E { E1, E2, E3 };
> };
>
> class D : private B
> {
> public:
>    using B::E;
>
> private:
>    enum E { };
> };
>
> we parse the new declaration enum E { }; and we reach
> supplement_binding_1 before setting the underlying type of the new
> declaration. The old declaration is fine, would not ICE dependent_type_p.

So with your change would we still ICE if D were a template?  It seems 
like what we should be checking for is null underlying type.

Jason
diff mbox

Patch

Index: testsuite/g++.dg/lookup/using53.C
===================================================================
--- testsuite/g++.dg/lookup/using53.C	(revision 0)
+++ testsuite/g++.dg/lookup/using53.C	(revision 0)
@@ -0,0 +1,31 @@ 
+// PR c++/20420
+
+class B
+{
+protected:
+  enum E { E1, E2, E3 };
+  struct S { int i; E e; };
+};
+
+class D : private B
+{
+public:
+  using B::E;       // { dg-message "previous" }
+  using B::S;       // { dg-message "previous" }
+
+private:
+  enum E {};        // { dg-error "conflicts" }
+  struct S {};      // { dg-error "conflicts" }
+};
+
+namespace N
+{
+  int i;
+}
+
+void
+f ()
+{
+  using N::i;
+  using N::i;       // { dg-error "declared" }
+}
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 190590)
+++ cp/name-lookup.c	(working copy)
@@ -441,7 +441,8 @@  supplement_binding_1 (cxx_binding *binding, tree d
 	     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
+	  || (processing_template_decl
+	      && 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)))
@@ -2581,7 +2582,12 @@  do_local_using_decl (tree decl, tree scope, tree n
 
   decl = validate_nonmember_using_decl (decl, scope, name);
   if (decl == NULL_TREE)
-    return;
+    {
+      /* C++11 7.3.3/10.  */
+      if (TREE_CODE (orig_decl) == VAR_DECL)
+	error ("%qD is already declared in this scope", name);
+      return;
+    }
 
   if (building_stmt_list_p ()
       && at_function_scope_p ())