Archived

This forum has been archived. Please start a new discussion on GitHub.

weird template compilation error on solaris

I am trying to compile Slice on Solaris using Forte 6.2. It fails to compile Grammar.cpp due to some weird template problem. I wonder if anyone else could shed some light on this please. Here is the error msg:

"Grammar.y", line 1394: Error: Cannot assign std::pair<IceUtil::Handle<Slice::Builtin>, std::string>
to std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string> without "std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string>::operator=(const std::pair<IceUtil::Handle<Slice::SyntaxTreeB
ase>, std::string>&)";.
"Grammar.y", line 1404: Error: Cannot assign std::pair<IceUtil::Handle<Slice::Builtin>, std::string>
to std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string> without "std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string>::operator=(const std::pair<IceUtil::Handle<Slice::SyntaxTreeB
ase>, std::string>&)";.

It looks to me like it thinks there is no assignment operator defined for the Handle class (but there is). This may be a Forte compiler bug. I note that Handle.h has a fix for a Win32 template problem in this area. This fix does not work for Forte.

Any ideas?

Andrew M.

Comments

  • Re: weird template compilation error on solaris
    Originally posted by marlowa
    I am trying to compile Slice on Solaris using Forte 6.2. It fails to compile Grammar.cpp due to some weird template problem. I wonder if anyone else could shed some light on this please. Here is the error msg:

    "Grammar.y", line 1394: Error: Cannot assign std::pair<IceUtil::Handle<Slice::Builtin>, std::string>
    to std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string> without "std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string>::operator=(const std::pair<IceUtil::Handle<Slice::SyntaxTreeB
    ase>, std::string>&)";.
    "Grammar.y", line 1404: Error: Cannot assign std::pair<IceUtil::Handle<Slice::Builtin>, std::string>
    to std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string> without "std::pair<IceUtil::Handle<Slice::SyntaxTreeBase>, std::string>::operator=(const std::pair<IceUtil::Handle<Slice::SyntaxTreeB
    ase>, std::string>&)";.
    Andrew M.

    I have more information on the problem. I get such a compilation error for every attempt to assign a make_pair to basestring->v. I believe that this is because v is not of the type pair<A,B>, which raises the question "why does GCC compile it?". I am not sure what this code is doing but if there is some sort of implicit conversion going on with GCC then why is make_pair even being called?

    regards,

    Andrew M.
  • mes
    mes California
    Hi Andrew,

    I'm pretty sure this is an STL issue. We obviously don't have problems compiling this code on our supported platforms, which certainly don't push the state of the art as far as C++ compliance is concerned (at least in the case of Visual C++).

    The definition of std:: pair in GCC 3.2's built-in STL contains the following constructor:
    template <class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
    
    If I comment out this constructor, GCC reports errors similar to yours.

    I'm assuming you are using Forte's built-in STL. Can you check the definition of std:: pair and see if it contains a constructor similar to the one above?

    If not, you might consider using STLport instead.

    Take care,
    - Mark
  • Originally posted by mes
    Hi Andrew,

    I'm pretty sure this is an STL issue. We obviously don't have problems compiling this code on our supported platforms, which certainly don't push the state of the art as far as C++ compliance is concerned (at least in the case of Visual C++).

    The definition of std:: pair in GCC 3.2's built-in STL contains the following constructor:

    template <class _U1, class _U2>
    pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
    
    If I comment out this constructor, GCC reports errors similar to yours.

    I'm assuming you are using Forte's built-in STL. Can you check the definition of std:: pair and see if it contains a constructor similar to the one above?

    If not, you might consider using STLport instead.

    Take care,
    - Mark

    I have verified that this is indeed an STL issue but I cannot use STLport. This is because I will be linking with third-party components that were not built with STlport. Also I think you will find that it is very common in commercial Solaris development environments to just use the Forte STL.

    The central issue here is defect 181, filed by Andrew Koenig in 1999. Koenig points out that the std says that the arguments to make_pair are references, which means that make_pair can make a non-obvious pair. Consider this code:

    #include <iostream>
    #include <string>
    #include <utility>

    struct A
    {
    int fred;
    };

    struct B : public A
    {
    };

    int main()
    {
    A a;
    B b;
    std::string str = "hello";
    std::pair<A,std::string> apair;

    apair = make_pair(b, str);

    std::cout << "sizeof-a = " << sizeof(a)
    << ", sizeof-b = " << sizeof(b)
    << ", sizeof pair = " << sizeof(apair)
    << ", sizeof make_pair = " << sizeof(make_pair(b, str))
    << std::endl;
    return 0;
    }

    The line
    apair = make_pair(b, str);
    is making a pair of type pair<B,string> and assigning it to a pair<A,string>
    Defect 181 says that this is wrong. The use of references and the fact that B inherits from A, is what makes it work for GNU. The GNU header file even has a comment about this saying that it works according to the defect being fixed. However, the macro _GLIBCPP_RESOLVE_LIB_DEFECTS is used to control this and it is on by default, which makes the code compile.

    IMO the defect report is correct which means we can expect the language to be fixed at some point. Forte is working as if the std has already been fixed. Strictly speaking ths makes it non-conformant but I think that's right in this case because to be conformant would be to suffer the defect.

    It is hard for me to fix Slice/Grammar.y given that it is relying on the presence of this defect. It also works at runtime because like the code example above, the derived class is sufficiently similar for things not to matter.

    Regards,

    Andrew
  • mes
    mes California
    As usual, thanks for the detective work. We'll look at this issue.

    - Mark
  • Originally posted by mes
    As usual, thanks for the detective work. We'll look at this issue.

    - Mark

    I couldn't rest until I had solved this one. It now builds on Solaris. Here's how I did it and what the issues are:

    The problem is that std::pair::make_pair takes arguments by reference which means you can pass in derived classes and they 'decay' to base class references before being copied by value. Defect 181 points this out and says that the arguments should be by value not reference. Forte fixes defect 181, GCC does not. One day this defect will probably be addressed by the std and when it is, GCC will no longer be in compliance. The trouble is, in the case of the slice compiler, the first argument is a smart pointer where it is ok to have the reference behaviour.

    I have written a template class which I have called grammar_pair. It is like std::pair but with defect 181 deliberately selected. I have changed the slice compiler to use this class instead of std::pair. The fixed files are attached as a compressed tarball.

    This is not ideal, IMO. I think there are two roots for a proper fix:

    1) Consider adding something like
    grammar_pair to boost for inclusion into the next std.
    This means at the next revision of the std std::pair will not work
    for slice but there will be another class that does.

    2) Alter slice so that it can use std::pair as is. This is non-trivial.
    I tried to do this last night but the problem is the class that is
    used at the bottom of the inheritance hierachy is SyntaxTreeBase
    but it is a concrete class. Type inherits from it and is abstract.
    The code uses a mixture of Type and SyntaxTreeBase as base
    classes such that moving the abstract stuff into SyntaxTreeBase
    breaks alot of things.

    I would go for option 1. Will the Ice developers take this up with the boost community? If not then I can see it being either option 2 or my hack.

    Regards,

    Andrew M.