Closed
Bug 43306
Opened 25 years ago
Closed 24 years ago
AIX xlC 5.0 compiler issue : nsDerviedSafe
Categories
(SeaMonkey :: Build Config, defect, P3)
Tracking
(Not tracked)
RESOLVED
FIXED
People
(Reporter: jdunn, Assigned: jdunn)
References
Details
Attachments
(1 file)
|
1.12 KB,
text/plain
|
Details |
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...
adding Mike to the cc list, since the os/2 compiler will probably have same
problem
Comment 4•25 years ago
|
||
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;
}
Comment 5•25 years ago
|
||
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
Updated•21 years ago
|
Product: Browser → Seamonkey
You need to log in
before you can comment on or make changes to this bug.
Description
•