morloc-project / morloc

A typed, polyglot, functional language
GNU General Public License v3.0
195 stars 4 forks source link

C++ Template Issues #14

Closed Zach1031 closed 1 year ago

Zach1031 commented 2 years ago

Compiling morloc code that uses cppbase produces template errors.

Example: Running morloc make foo.loc in argument-form-1-c produces the following error:

System call failed at (runSysCommand):
 cmd> g++ --std=c++11 -o pool-cpp.out pool.cpp  -I/Users/zachdefazio/.morloc/src/cppbase
 msg>
pool.cpp:164:26: error: template parameter redefines default argument
template<std::size_t I = 0, class... Rs>
                         ^
pool.cpp:48:26: note: previous default template argument defined here
template<std::size_t I = 0, class... Rs>
                         ^
pool.cpp:169:26: error: template parameter redefines default argument
template<std::size_t I = 0, class... Rs>
                         ^
pool.cpp:52:26: note: previous default template argument defined here
template<std::size_t I = 0, class... Rs>
                         ^
2 errors generated.

The errors occurred on macOS 10.13.6 using gcc version 10.0.0:

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
arendsee commented 2 years ago

Thanks for the report @Zach1031. Can you pull the latest morloclib/cppbase and run make and then ./a.out. This should tell you 6 tests successfully passed.

This will at least help me narrow down where the problem is.

All the morloc tests pass fine on my MacOS v10.14.6 with gcc version info of

Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Zach1031 commented 2 years ago

All the tests ran successfully:

[doctest] doctest version is "2.4.0"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases:      2 |      2 passed |      0 failed |      0 skipped
[doctest] assertions:      6 |      6 passed |      0 failed |
[doctest] Status: SUCCESS!

I'm not sure what the issue is, it could be something on my end.

arendsee commented 2 years ago

Well, that narrows it down, I'll keep looking into it. That test didn't include any C++ code that was generated by morloc, but at least it shows your C++ environment is working.

arendsee commented 2 years ago

What is the git hash for the version of morloc you have locally?

arendsee commented 2 years ago

OK, I was wrong earlier. I hadn't retested it on my MacOS computer. So the tests only pass on my Linux machine. On my Mac, I do get the same error you get.

arendsee commented 2 years ago

It ended up being a Clang versus GNU C Compiler issue. See the commit message.

arendsee commented 2 years ago

Soooooo, the solution above fixes the problem for Clang but breaks it for GCC.

Here was the original code:

template<std::size_t I = 0, class... Rs>
inline typename std::enable_if<I == sizeof...(Rs), std::string>::type
  _serialize_tuple(std::tuple<Rs...> x);

template<std::size_t I = 0, class... Rs>
inline typename std::enable_if<I < sizeof...(Rs), std::string>::type
  _serialize_tuple(std::tuple<Rs...> x);

...

template<std::size_t I = 0, class... Rs>
inline typename std::enable_if<I == sizeof...(Rs), std::string>::type
  _serialize_tuple(std::tuple<Rs...> x)
  { return ""; }

template<std::size_t I = 0, class... Rs>
inline typename std::enable_if<I < sizeof...(Rs), std::string>::type
  _serialize_tuple(std::tuple<Rs...> x)
  {
    return serialize(std::get<I>(x)) + "," + _serialize_tuple<I + 1, Rs...>(x);
  }

Note that the default I = 0 is set in both the prototype and the function implementation. This is what Clang was complaining about. I fixed the problem for Clang by removing the default in the prototype.

But now GCC complains, raising the following inscrutable error message in the test serial-form-9-c:

$ g++ --std=c++11 -o pool-cpp.out pool.cpp  -I/home/z/.morloc/src/cppbase

System call failed at (runSysCommand):
 cmd> g++ --std=c++11 -o pool-cpp.out pool.cpp  -I/home/z/.morloc/src/cppbase
 msg>
pool.cpp: In instantiation of ‘std::string serialize(std::tuple<_Tps ...>, std::tuple<_Tps ...>) [with A = {std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::vector<mlc_Person_1, std::allocator<mlc_Person_1> >}; std::string = std::__cxx11::basic_string<char>]’:
pool.cpp:542:31:   required from here
pool.cpp:180:27: error: no matching function for call to ‘_serialize_tuple(std::tuple<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::vector<mlc_Person_1, std::allocator<mlc_Person_1> > >&)’
  180 |     ss << _serialize_tuple(x);
      |           ~~~~~~~~~~~~~~~~^~~
pool.cpp:166:3: note: candidate: ‘template<long unsigned int I, class ... Rs> typename std::enable_if<(I == sizeof... (Rs)), std::__cxx11::basic_string<char> >::type _serialize_tuple(std::tuple<_Elements ...>)’
  166 |   _serialize_tuple(std::tuple<Rs...> x)
      |   ^~~~~~~~~~~~~~~~
pool.cpp:166:3: note:   template argument deduction/substitution failed:
pool.cpp:180:27: note:   couldn’t deduce template parameter ‘I’
  180 |     ss << _serialize_tuple(x);
      |           ~~~~~~~~~~~~~~~~^~~
pool.cpp:171:3: note: candidate: ‘template<long unsigned int I, class ... Rs> typename std::enable_if<(I < sizeof... (Rs)), std::__cxx11::basic_string<char> >::type _serialize_tuple(std::tuple<_Elements ...>)’
  171 |   _serialize_tuple(std::tuple<Rs...> x)
      |   ^~~~~~~~~~~~~~~~
pool.cpp:171:3: note:   template argument deduction/substitution failed:
pool.cpp:180:27: note:   couldn’t deduce template parameter ‘I’
  180 |     ss << _serialize_tuple(x);

I can fix the problem for GCC by simply removing the two prototypes altogether.

Now, the question is, does it work with Clang?