Bug 14513 - Friend name injection problem (implicit declaration)
Summary: Friend name injection problem (implicit declaration)
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3.2
: P2 normal
Target Milestone: 4.0.0
Assignee: Kriang Lerdsuwanakij
URL:
Keywords: accepts-invalid, patch
Depends on:
Blocks: c++-lookup, c++-name-lookup 16995
  Show dependency treegraph
 
Reported: 2004-03-10 15:42 UTC by The Written Word
Modified: 2005-01-13 14:55 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 2.95.3 3.1 3.3 4.0.0
Last reconfirmed: 2004-06-09 01:04:33


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description The Written Word 2004-03-10 15:42:54 UTC
In the process of compiling KDE 3.2 on IRIX 6.5 and Tru64 UNIX 5.1
with the respective vendor C++ compilers, I ran into a namespace
issue. Consider the following:
   
$ cat a.h
class KMAcctImap;
   
namespace KIO {
  class Job {
  public:
    int b;
  };
}
   
namespace KMail {
  class ImapJob {
    friend class KMAcctImap;
  public:
    ImapJob();

  private:
    KIO::Job *mJob;
  };
}

$ cat b.cpp
namespace KIO {
  class Job;
}
namespace KMail {
  class ImapJob;
}
using KMail::ImapJob;

class KMAcctImap
{
  friend class KMail::ImapJob;

public:
  void test (void);
};

#include "a.h"

void KMAcctImap::test (void) {
  ImapJob *f = new ImapJob ();

  if (f->mJob)
    int b;
}

Compile results with different compilers:
  (Solaris Sun One 8 compiler)
    $ CC -c b.cpp
    "b.cpp", line 22: Error: mJob is not accessible from KMAcctImap::test().
    1 Error(s) detected.
  (HP-UX C++ compiler)
    $ aCC -c b.cpp
    Error 182: "b.cpp", line 22 # "void KMAcctImap::test()" cannot access
    private
        member "KIO::Job *KMail::ImapJob::mJob".
          if (f->mJob)
              ^^^^^^^
  (IRIX C++ compiler)
    $ CC -c b.cpp
    cc-1238 CC: ERROR File = b.cpp, Line = 22
      The member "KMail::ImapJob::mJob" is inaccessible.

        if (f->mJob)
               ^
  (IBM C++ compiler)
    $ xlC -c b.cpp
    [success]
  (Tru64 UNIX C++ compiler)
    $ cxx -c b.cpp
    cxx: Error: b.cpp, line 22: member "KMail::ImapJob::mJob" is inaccessible
      if (f->mJob)
    ---------^
  (GCC 3.3.2 with some patches from 3.3.3 merged in)
    $ g++ -c b.cpp
    [success]

I can cause a successful compile by changing:
  namespace KMail {
    class ImapJob {
      friend class KMAcctImap;
to:
  namespace KMail {
    class ImapJob {
      friend class ::KMAcctImap;
                   ^^

Based on http://gcc.gnu.org/ml/gcc/2004-03/msg00499.html, GCC is incorrect.
Comment 1 Andrew Pinski 2004-03-10 15:53:03 UTC
Confirmed.
Comment 2 Wolfgang Bangerth 2004-03-10 16:24:00 UTC
OK, so here's what happens:  
------------  
struct S {  
    void test (void);  
};  
  
namespace NS {  
  class X {  
      friend class S;  
      static int *i;  
  };  
}  
  
void S::test () {  
  NS::X::i;  
}  
---------------  
gcc thinks the 'friend class S' declaration refers to class ::S and thus  
allows the access in S::test. All the other compilers seem to believe  
that the friend declaration refer to a yet-to-be-declared class NS::S,  
and therefore don't allow access in ::S::test. I have yet to understand  
what the standard really says in this respect. Kriang?  
  
W.  
Comment 3 Gabriel Dos Reis 2004-03-10 19:55:20 UTC
Subject: Re:  Friend name injection problem (implicit declaration)

"bangerth at dealii dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| OK, so here's what happens:  
| ------------  
| struct S {  
|     void test (void);  
| };  
|   
| namespace NS {  
|   class X {  
|       friend class S;  
|       static int *i;  
|   };  
| }  
|   
| void S::test () {  
|   NS::X::i;  
| }  
| ---------------  
| gcc thinks the 'friend class S' declaration refers to class ::S and thus  
| allows the access in S::test. All the other compilers seem to believe  
| that the friend declaration refer to a yet-to-be-declared class NS::S,  
| and therefore don't allow access in ::S::test. I have yet to understand  
| what the standard really says in this respect. Kriang?  

I'm not Kriang but I'm going to answer.  Yes, GCC's behaviour is
wrong.  Compilers that reject the code are right.  See the explanation
I gave in the link pointed to in the original report.  If you want
chapter and verse, see somewhere in 7.3.1.x for namespace members that
talk about friend declarations.

-- Gaby
Comment 4 Kriang Lerdsuwanakij 2004-09-04 12:47:56 UTC
Looking at friend class injection bugs.
Comment 5 Kriang Lerdsuwanakij 2004-10-17 14:08:54 UTC
Patches submitted.  Both patches are required to fix this bug.

  http://gcc.gnu.org/ml/gcc-patches/2004-10/msg01321.html
  http://gcc.gnu.org/ml/gcc-patches/2004-10/msg01372.html
Comment 6 Kriang Lerdsuwanakij 2004-11-12 17:03:43 UTC
One more patch is required.  And libjava problem has to be fixed before this bug
is revisited.
Comment 7 Kriang Lerdsuwanakij 2004-11-19 10:09:57 UTC
Last part is submitted:
  http://gcc.gnu.org/ml/gcc-patches/2004-11/msg01495.html
This one together with earlier parts fix the bug.
Comment 8 GCC Commits 2004-11-25 16:55:42 UTC
Subject: Bug 14513

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	lerdsuwa@gcc.gnu.org	2004-11-25 16:55:34

Modified files:
	gcc/cp         : ChangeLog name-lookup.c name-lookup.h decl.c 
	                 cp-tree.h parser.c pt.c rtti.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/lookup: friend2.C 
	gcc/testsuite/g++.dg/template: friend31.C 

Log message:
	Friend class name lookup 2/n, PR c++/14513, c++/15410
	* name-lookup.c (lookup_name_real): Simplify.
	(lookup_type_scope): Add SCOPE parameter.  Handle friend class
	lookup.
	* name-lookup.h (tag_scope): New enum type.
	(lookup_type_scope): Adjust declaration.
	* decl.c (lookup_and_check_tag, xref_tag, xref_tag_from_type):
	Change bool parameter GLOBALIZED to TAG_SCOPE parameter SCOPE.
	(start_enum): Likewise.  Add assertion test that NAME is
	IDENTIFIER_NODE.  Use anonymous name for dummy ENUMERAL_TYPE in
	case of error.
	* cp-tree.h (xref_tag, xref_tag_from_type): Adjust declarations.
	* parser.c (cp_parser_elaborated_type_specifier,
	cp_parser_class_head): Adjust call to xref_tag.
	* pt.c (lookup_template_class, instantiate_class_template):
	Likewise.
	* rtti.c (init_rtti_processing, build_dynamic_cast_1,
	tinfo_base_init, emit_support_tinfos): Likewise.
	
	* g++.dg/lookup/friend2.C: New test.
	* g++.dg/template/friend31.C: Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4496&r2=1.4497
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.c.diff?cvsroot=gcc&r1=1.93&r2=1.94
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.h.diff?cvsroot=gcc&r1=1.30&r2=1.31
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl.c.diff?cvsroot=gcc&r1=1.1332&r2=1.1333
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&r1=1.1072&r2=1.1073
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.281&r2=1.282
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.947&r2=1.948
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/rtti.c.diff?cvsroot=gcc&r1=1.203&r2=1.204
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4646&r2=1.4647
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/lookup/friend2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/friend31.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 9 Kriang Lerdsuwanakij 2004-11-25 17:05:00 UTC
Fixed in the mainline.
Comment 10 Andrew Pinski 2005-01-12 19:47:07 UTC
*** Bug 19403 has been marked as a duplicate of this bug. ***
Comment 11 Giovanni Bajo 2005-01-13 00:37:04 UTC
Kriang, would you please add a note to changes.html about this? I am sure it is 
going to surprise many many people.
Comment 12 Kriang Lerdsuwanakij 2005-01-13 14:55:00 UTC
It is already described in changes.html:

  When declaring a friend class using an unqualified name, classes outside
  the innermost non-class scope are not searched ...