Closed Bug 43306 Opened 25 years ago Closed 24 years ago

AIX xlC 5.0 compiler issue : nsDerviedSafe

Categories

(SeaMonkey :: Build Config, defect, P3)

Other
AIX
defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: jdunn, Assigned: jdunn)

References

Details

Attachments

(1 file)

The AIX port can't get certain nsDerviedSafe<>.gets to work, the compiler complains with the following error: "reinterpretcast.cpp", line 62.15: 1540-0207 (S) No common type found for operands with type "nsDerivedSafe<nsIAtom> *" and "nsIAtom *". This is a placeholder
updating...
Blocks: 18688
Status: NEW → ASSIGNED
QA Contact: granrose → jdunn
Target Milestone: --- → M30
adding Mike to the cc list, since the os/2 compiler will probably have same problem
Here's the word from the VisualAge compiler team: The problem has nothing to do with the reinterpret cast and is an issue with template instantiation. The problem can be shown in the following reduction: =================================================================== class A { }; struct B { static A* ap; }; template <class T> class C : public T { }; template <class T> struct D { C<T>* get() { } }; int blah(void) { D<A> dp; if (dp.get() == B::ap) return 3; } When D is instantiated with A The member function D<A>::get() returns a pointer to C<A> this DOES NOT require that C<A> be instantiated. Without instantiating C<A> there is no way to discover tht C<A> is a derived class of A so the standard pointer conversion of derived to base class pointer is not known. The workaround is to add an explicit instantiation of C<A>: template class C<A>; or in the original test case: template class nsDerivedSafe<nsIAtom>; =================================================================== The defect has not been returned as invalid yet because there is some concern that the standard is inconsistent and we have posted a question to the standards committee concerning this problem. There are several rules stating when a template should and should not be instantiated. According to these rules, the compiler does the correct thing -- it does not do an instantiation and produces an error. That said, there is a catch-all phrase in the standard indicating that an instantiation should be done if the instantiation can affect the semantics of a program. This phrase implies that the instantiation should be done, but it contradicts the other areas of the standard dealing with when an instantiation should be done. Until we have clarification indicating that our interpretation is incorrect, we will not be changing our code because we believe that our interpretation is correct. Here's the explanation and workaround specifically addressing the testcase in question: The problem is that when nsCOMPtr is instantiated with nsIAtom, the member function nsCOMPtr<nsIAtom)::get() returns a pointer to nsDerivedSafe<nsIAtom>. This does not require that nsDerivedSave<nsIAtom> be instantiated. Without instantiatng this, there is no way to discvover that nsDerivedSafe<nsIAtom> is a derived class of nsIAtom so that the standard pointer conversion of derived class to base class is not known. While we realize that this probably worked with every other compiler out there, and that it did used to work with 366 ppak2 compiler, we are not sure if this is a valid construct. This is because of the following clause in ANSI 14.7.1:1 "... the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined type [not required here] or when the completeness of the class type EFFECTS THE SEMANTICS OF THE PROGRAM." [emphasis mine] It is the second part of the Or that is subject to interpretation. We are sending a request to ANSI for a ruling on this. Here is a workaround which will not impact other compilers. It only adds one explicit instantiation line. class nsISupports { }; class nsIAtom : public nsISupports { }; class nsXULAtoms { public: static nsIAtom* treeitem; }; template <class T> class nsDerivedSafe : public T { private: void operator delete( void*, int ); nsDerivedSafe<T>& operator=( const T& ); }; //this is the only line added to explicitly instantiate it template class nsDerivedSafe<nsIAtom>; class nsCOMPtr_base { public: nsCOMPtr_base(nsISupports* rawPtr = 0) : mRawPtr(rawPtr) { } ~nsCOMPtr_base(); protected: nsISupports* mRawPtr; }; template <class T> class nsCOMPtr : private nsCOMPtr_base { public: nsCOMPtr() : nsCOMPtr_base(0) { } nsCOMPtr(T* aRawPtr) : nsCOMPtr_base(aRawPtr) { }; nsDerivedSafe<T>* get() const { return reinterprafe<T>* operator->() const { {}; return get(); } nsDerivedSafe<T>& operator*() const { {}; return *get(); } }; int blah(void) { nsCOMPtr<nsIAtom> pTag; if (pTag.get() != nsXULAtoms::treeitem) int a = 2; return 3; }
The experience of building this with the AIX VisualAge 5 C++ compiler has led me to the following conclusion: The hack I suggested above (explicit instantiation of nsDerivedSafe for each class) makes a mess due to the number of classes involved. The workaround made sense for the testcase Jim provided above, but not in the context of the Mozilla build. I have worked around this problem by replacing references to nsDerivedSafe<T> in the template classes with the actual type, T. Though functional, this may not be ideal. I noticed, in working on this problem, that there is a comment in nsDerivedSafe (as well as nsGetterAddRefs and already_AddRefed, also in nsCOMPtr.h) which reads "This type should be a nested class inside |nsCOMPtr<T>|." Do we know if there is a reason that these types are _not_ nested classes within nsCOMPtr<T>?
Fixed with the xlC 5.1 (2/01) version the compiler
Status: ASSIGNED → RESOLVED
Closed: 24 years ago
Resolution: --- → FIXED
oops xlC/vacpp 5.0.x and not 5.1
Product: Browser → Seamonkey
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: