Closed
Bug 43311
Opened 24 years ago
Closed 22 years ago
AIX xlC 5.0 compiler issue: friend 'prototype'
Categories
(SeaMonkey :: Build Config, defect, P3)
Tracking
(Not tracked)
RESOLVED
FIXED
mozilla0.9.8
People
(Reporter: jdunn, Assigned: jdunn)
References
Details
Attachments
(6 files, 1 obsolete file)
275 bytes,
text/plain
|
Details | |
3.08 KB,
text/plain
|
Details | |
16.00 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
1.69 KB,
patch
|
jag+mozilla
:
superreview+
asa
:
approval+
|
Details | Diff | Splinter Review |
466 bytes,
patch
|
Details | Diff | Splinter Review | |
646 bytes,
patch
|
jag+mozilla
:
superreview+
asa
:
approval+
|
Details | Diff | Splinter Review |
The AIX xlC 5.0 compiler is having issues with having 'friend' declarations that also double for 'prototyping'. In this case I get the following error: "friend.cpp", line 10.7: 1540-0040 (S) The text "function" is unexpected. "B" may be undeclared or ambiguous. Since this is a compiler issue, this bug is aplace holder.
Comment 3•24 years ago
|
||
Problem recreated and submitted to the IBM compiler team.
Comment 4•24 years ago
|
||
For tracking purposes: IBM PMR #79946 -519-000
Comment 5•24 years ago
|
||
Changed to PMR 85012 -519-000
Comment 6•24 years ago
|
||
Not seen with gcc or IBM 3.6.6 compiler. The problem is still being worked. A work-around is to pre-declare B. Is this acceptable for the time being? -------- #include <stdio.h> class B; // pre-declare B class A { public: A() { a=1; } private: friend class B; B function(); int a; }; class B { public: B() { b = 0; aptr = '\0'; } private: A *aptr; int b; }; B A::function() { B *temp = new B; return *temp; } ---------
Comment 7•24 years ago
|
||
Defect #160229.
Comment 8•24 years ago
|
||
Hmmm. I can see how your compiler could legitimately complain that at the point of B function(); |B| is still an incomplete type, and hence can't be used in this way. However, for a compliant compiler, the name |B| should now be in scope because of the earlier |friend| declaration. Many compilers get this wrong, and don't treat a local |friend| declaration as a forward declaration. This is probably your trouble. Declaring |class B;| above the entire class that wishes it to be a |friend| might fix the error you're currently seeing, but would most likely resolve to the incomplete type error I would have expected in the first place. Your example can easily be made to compile by re-ordering the declarations ... so I don't know if this is a good case for your real problem. E.g., class A; class B { public: B() : b(0), aptr(0) { } private: A* aptr; // pointer to an incomplete type is OK int b; }; class A { public: A() : a(1) { } private: B function(); // B not incomplete, OK to use int a; }; B A::function() { B* temp = new B; return *temp; } I know your example was just quick and dirty, but I don't understand why you would initialize a pointer to be the conversion of a character. How does your example differ from the real case that would prevent you from avoiding the trouble entirely by re-ordering the declarations?
Comment 9•24 years ago
|
||
oops, I left out the |friend| decl; which I don't think is actually needed in your example anyway (even though it's the point of your example).
Assignee | ||
Comment 10•24 years ago
|
||
The work around suggested has been used to get around this. However, it is annoying and since I had opened other VA5.0 (xlC) bugs, I figured I would open this one too. The example is down and dirty that mimics what I have seen in mozilla code. The example itself is silly and is not meant to do anything other than show the compiler bug. The key point to this and the other VA5.0 bugs is too show that the compiler is not currently up to task to build mozilla and I wanted to list all of the issues I found. I have had problems in the past getting permission to go in and re-order statements just to fix a 'AIX' issue. It would be much easier to have a compiler that didn't exhibit these problems.
Comment 11•24 years ago
|
||
scc wasn't cced on this so he didn't see jdunn's latest comment. scc - apparently, this problem exists in some Mozilla files, so if you believe the code is incorrect, then mozilla does need to be fixed. jdunn, can you give specific examples of mozilla files with this problem?
Assignee | ||
Comment 12•24 years ago
|
||
Not without doing a 5.0 build and right now I am not setup to do it... One key is that we can workaround this. The other key is that my original attachment, shows the problem so that the compiler people can fix this. So if we ever decide to move to the new compiler (there are lots of other bigger issues then just this... we can deal with the workarounds...
Comment 13•24 years ago
|
||
I have engaged the compiler people on this issue as well as the two other AIX VisualAge 5 C++ issues, bugs 43315 and 43306. A compiler defect (160229) was opened for this problem and was subsequently closed by the compiler team as "user error", since the friend declaration does not implicitly declare the class. I am following up on this, because my understanding was that, in Bjarne Stroustrup's words, "A friend class must be previously declared in an enclosing scope or defined in the non-class scope immediately enclosing the class that is declaring it a friend." (Quote taken from the 2000 edition of "The C++ Programming Language".) This implies that the code in the testcase should work, since the friend class is defined within "the non-class scope immediately enclosing the class that is declaring it a friend". It is possible that the standard varies slightly from this or that there is some subtlety which has eluded me, but I am asking for a clarification from the compiler team, which I will copy into the text of this bug.
Assignee | ||
Comment 14•24 years ago
|
||
Thanks! If the compiler team still say no, they are right, then please ask them to cite where in the standard that they are quoting from. With the quote, I can go to engineers and say, HERE, your code is wrong, here is the solution, let me check it in. Without a quote from the standard... I can't do squat.
Comment 15•24 years ago
|
||
I am currently discussing this with our compiler team, who have pointed to the relevant reference in the standard, section 7.3.1.2, paragraph 3: "If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship)."
Comment 16•24 years ago
|
||
Comment 17•24 years ago
|
||
This compile error occurs when the compile of xpcom/base/nsWeakReference.cpp is attempted. The error message is: "nsWeakReference.h", line 53.22: 1540-0040 (S) The text "*" is unexpected. "nsWeakReference" may be undeclared or ambiguous.
Comment 18•24 years ago
|
||
It seems that the VisualAge 5 C++ compiler is behaving correctly here according to the standard. We should definitely resolve this with a code change in Mozilla. I was a little fuzzy on exactly how the construct in question violated the standard, so the VisualAge C++ compiler team provided me with the following more precise explanation of why this usage is incorrect in terms of the standard: The particular example being discussed is included below. The error given is that function is unexpected. I will try to explain the history behind this and why this is an error. #include <stdio.h> class A { public: A() { a=1; } private: friend class B; B function(); int a; }; class B { public: B() { b = 0; aptr = '\0'; } private: A *aptr; int b; }; B A::function() { B *temp = new B; return *temp; } First, the history. In the working drafts of the standard, it used to be that a friend declaration of a class also implicitly declared a class in global scope if it did not already exist in global scope. Version 3.6.6 of IBM's compilers worked this way, as do many current versions of C++ compilers offered by other vendors. When a friend declaration was encountered, the name of the class being nominated for friendship was looked up and matched if it existed. If it did not, it would be declared in the global scope. Thus, the name would be found in the next declaration because the lookup for B would find the name in global scope. This was changed in the final standard. The reference in the standard is 7.3.1.2, paragraph 3. "If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship)." What this means is that when a class is nominated for friendship, the name of the class is looked up in the current scope. If it is not found, it is looked up in the enclosing scopes, until it is found or the global namespace is reached. Essentially, normal name lookup is performed. If it is not found (as is the case here), the rules in the quotation given apply. The name is declared in the innermost enclosing namespace. The name is not visible until a matching declaration is provided. Thus, the name B is not found, resulting in the error. Note that the error even suggests that B may be undeclared.
Comment 19•24 years ago
|
||
The class |nsWeakReference| needs to be forward declared before the class |nsSupportsWeakReference|, that's all. The compiler is right to refuse this code. Most compilers get this wrong, and find |nsWeakReference| in spite of the standard, as this was the draft standard defined behavior, as pointed out above.
Assignee | ||
Comment 20•23 years ago
|
||
This patch will fix all the friend issues. Declaring something friend doesn't mean that it has been declared or prototyped. The new xlC compiler is just very strict in this case, so in order for something to be used it needs to be "declared/prototyped" in addition to being made a "friend". Additionally, if it is "declared/prototyped" the default args need to be set in the prototype and NOT in the friend accessor
Assignee | ||
Comment 21•23 years ago
|
||
updating bug, adding a bunch of people on the CC list. I am looking for a r= and hopefully a sr= (but since this is a "build" issue and shouldn't change any code... I don't think it is needed, but I cc'd a bunch of people to get there thoughts)
Target Milestone: --- → mozilla0.9.8
Comment 22•23 years ago
|
||
Cc'ing dbaron, who is a C++ language guru (in my book, anyway). David, could you look at the latest patch and jdunn's comments this year, and bless or curse? Thanks, /be
Comment on attachment 64132 [details] [diff] [review] New patch to fix all the offending "friend" issues IIRC (all the online copies of the C++ standard have disappeared) this compiler is wrong, but the workaround won't really hurt anything, so I don't object (although people will probably re-break this a bit). I think the example used in comment #6 led scc to think this was a different problem from what it really is. r=dbaron
Attachment #64132 -
Flags: review+
Comment 24•23 years ago
|
||
From "The C++ Programming Language, Third Edition", section 11.5.1: <quote> 11.5.1 Finding Friends Like a member declaration, a friend declaration does not introduce a name into an enclosing scope. For example: class Matrix { friend class Xform; friend Matrix invert(const Matrix&); //.. } Xform x; // error: no Xform in scope Matrix (*p)(const Matrix&) = &invert; // error: no invert() in scope For large programs and large classes, it is nice that a class doesn't ``quietly'' add names to its enclosing scope. For a template class that can be instantiated in many different contexts (Chapter 13), this is very important. A friend class must be previously declared in an enclosing scope or defined in the non-class scope immediately enclosing the class that is declaring it a friend. For example: class X { /* ... */ }; // Y's friend namespace N { class Y { friend class X; friend class Z; friend class AE; }; class Z { /* ... */ }; // Y's friend } class AE { /* ... */ }; // not a friend of Y </quote> This seems to suggest that the following is also the case, since B is declared in the non-class scope immediately enclosing A: class A { friend class B; }; class B { /* ... */ }; // friend of A
Assignee | ||
Comment 25•23 years ago
|
||
*** Bug 72190 has been marked as a duplicate of this bug. ***
Assignee | ||
Comment 26•23 years ago
|
||
fix checked in
Status: ASSIGNED → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
Comment 27•23 years ago
|
||
Fixes for several files have been checked in, but the problem has reoccurred in other files. Therefore, the standard question should really be settled to make it easier to handle new similar problems. In an earlier note in comment #18, the standard was quoted that explains why the behavior of the new AIX compiler is standard conform. Scott Collins agreed in comment #19. David Baron states in comment #23 that the compiler is wrong. David, if you think the compiler is wrong, could you please explain why the quoted standard does not apply, and why the example in comment #6 does not address the real problem. I would like to get the opinion of the compiler group that develops the compiler, but to do this I need more specifics. Thank you very much.
Comment 28•23 years ago
|
||
To quote from comment 18: "If a friend declaration in a non-local class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship)." // innermost enclosing namespace is the global scope class A // non-local class { friend class B; // friend declaration in a non-local class, first declaration } class B // matching declaration for friend class B, provided in "that namespace" { } So the way I see it, the compiler is wrong and this code is fine, but perhaps I'm misinterpreting something (for I am not a c++ language lawyer).
Assignee | ||
Comment 29•23 years ago
|
||
I am attaching a very simple testcase that shows the current set of problems. ---- friend.cpp : xlC -c friend.cpp ---- class A { public: A(void); private: friend int NS_SomeFunc(int a); }; A::A(void) { int rc = NS_SomeFunc(10); return; } int NS_SomeFunc(int a) { return 1; } ---- Error message "friend.cpp", line 11.12: 1540-0274 (S) The name lookup for "NS_SomeFunc" did not find a declaration. "friend.cpp", line 15.5: 1540-1298 (I) "int NS_SomeFunc(int)" needs to be declared in the containing scope to be found by name lookup.
I can't clearly find a normative passage in the C++ spec that states this behavior is wrong (or states the contrary), but there are *examples* in the C++ spec that I don't think would compile on this compiler, and I think the examples at least make the intentions of the spec authors clear. Does the compiler compile this example from 11.4? class X { int a; friend void friend_set(X*, int); public: void member_set(int); }; void friend_set(X* p, int i) { p->a = i; } void X::member_set(int i) { a = i; } void f() { X obj; friend_set(&obj,10); obj.member_set(10); }
Assignee | ||
Comment 31•23 years ago
|
||
Your example does compile...
Comment 32•23 years ago
|
||
class A { public: A(void); private: friend int NS_SomeFunc(int a); }; int NS_SomeFunc(int a) { return 1; } A::A(void) { int rc = NS_SomeFunc(10); return; } How about the above? (So your code, but the actual call and the definition switched).
Assignee | ||
Comment 33•23 years ago
|
||
Your latest test does compile... since you are declaring " int NS_SomeFunc(int a) " before it is being used.
Comment 34•23 years ago
|
||
Ah, so the issue is that |friend class foopy;| doesn't declare |foopy| as a class. Time to re-read all comments here with that in mind. So, it does seem that the new compiler is correct.
Section 11.4, clause 9 of the C++ standard says this would be the correct behavior for *local* classes, but the fact that it restricts that statement to local classes suggests that it's not correct for other ones. However, I can't find any explicit statement to the contrary. attachment 64132 [details] [diff] [review] shows that there are problems with both friend functions and friend classes.
Assignee | ||
Comment 36•23 years ago
|
||
From my #29 comment: I put my "friend.cpp" into Comeau's online compiler http://www.comeaucomputing.com/tryitout/ after it was suggested to me from someone else. ----------------------------------------------------------------- Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION Copyright 1988-2001 Comeau Computing. All rights reserved. MODE:strict errors C++ "14100.c", line 10: error: identifier "NS_SomeFunc" is undefined int rc = NS_SomeFunc(10); ^
Comment 37•23 years ago
|
||
Waldemar, can you shed any light here? Thanks, /be
Comment 38•23 years ago
|
||
I looked over all of the comments above and looked at the relevant sections of the standard. It's clear to me that the compiler is correct, given the quote mentioned in comment 15 and comment 18. I couldn't say it better than as stated in comment 18. The one remaining dissenting opinion mentions a clause that does not apply here and covers a different issue: Comment 35 mentions section 11.4, clause 9. This clause is not relevant here because it deals only with what happens when you declare a class *inside a function*. This is a really bizarre thing to do -- it's a holdover from old C -- and C++ restricts what you can do there. In particular, 11.4:9 states that when looking for functions or classes to be made into friends, you *cannot* look outside the enclosing function into the namespace or global scope. See the example in 11.4:9. Outside a local class (i.e. a class defined inside a function), the friend declaration *can* look into global and namespace scopes and either find or declare things there. As stated in 7.3.1.2, paragraph 3, these declarations are not visible until they are declared outside a friend clause.
Comment 39•23 years ago
|
||
There are two more places in the code where the friend function needs to be declared (as of Mozilla 0.9.8). Here is a patch fixing the last two remaining problems.
Comment 40•22 years ago
|
||
Here is the most recent fix that cleans up all the remaining friend issues with the AIX v5 compiler.
Attachment #68206 -
Attachment is obsolete: true
Comment 41•22 years ago
|
||
Comment on attachment 72806 [details] [diff] [review] Friend fixes for latest trunk build sr=jag
Attachment #72806 -
Flags: superreview+
Comment 42•22 years ago
|
||
Comment on attachment 72806 [details] [diff] [review] Friend fixes for latest trunk build a=asa (on behalf of drivers) for checkin to the 1.0 trunk
Attachment #72806 -
Flags: approval+
Assignee | ||
Comment 43•22 years ago
|
||
Fix checked in
Comment 44•22 years ago
|
||
One more fix needed after the checkin for Bug 127097.
Assignee | ||
Comment 45•22 years ago
|
||
reopening to fix latest issue (see #44)
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Assignee | ||
Comment 46•22 years ago
|
||
Jag mentioned that no one should include nsString2.h instead they should include nsString.h. Switching this fixes the compile issue.
Comment 47•22 years ago
|
||
Comment on attachment 75600 [details] [diff] [review] alternative patch to 73249 with jag's r= you have a=asa for checkin to the 1.0 trunk. scc says this is a good thing so I'm 'pre-approving'.
Attachment #75600 -
Flags: approval+
Comment 48•22 years ago
|
||
Comment on attachment 75600 [details] [diff] [review] alternative patch to 73249 r=/sr=jag
Attachment #75600 -
Flags: superreview+
Assignee | ||
Comment 49•22 years ago
|
||
dbaron checked in the fix... marking fixed (may this bug never be re-opened again...)
Status: REOPENED → RESOLVED
Closed: 23 years ago → 22 years ago
Resolution: --- → FIXED
Updated•20 years ago
|
Product: Browser → Seamonkey
You need to log in
before you can comment on or make changes to this bug.
Description
•