Clang vs gcc in abstract class handling at compile time

One of these issues of the nlohmann / json open-source library caught my attention.

I have a minimal reproduction of the case when it does not compile with a small version of the gcc desktop (4.8, 4.9, also tried 5+), but it compiles well with mac clang and Android ndk gcc 4.9

#include <limits> struct base { virtual void foo() = 0; }; int main() { (void)numeric_limits<base>::is_signed; } 

GCC tries to instantiate std::numeric_limits with a base class instead of a derived one:

 /usr/include/c++/4.8/limits: In instantiation of 'struct std::numeric_limits<base>': main.cpp:11:94: required from here /usr/include/c++/4.8/limits:309:7: error: cannot allocate an object of abstract type 'base' min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } 

I'm not quite sure if this is a known compiler error (in case of failure) or a rule / relaxed rule (in case of success)

I tried to work with std::is_abstract , but this does not help, it seems that the evaluation of the "short circuit" does not occur in enable_if, and the error remains the same

My question mainly is not how to fix this for gcc, but in the weather it is a compiler error or a code error


Edit: Added a "more minimal" example without any standard library dependency:

 template <typename T> struct foo { static T bar(); static constexpr bool value = true; }; struct abstract { virtual ~abstract() = 0; }; int main() { (void) foo<abstract>::value; } 

Compiling on clang 3.9.0, but the gcc 7 snapshot throws an error for the invalid return type foo<abstract>::bar .


Edit2: I am a little surprised that my original question was edited without my consent, I didn’t know that SO allows this :) Thanks for the help, although I think it brought a bit of confusion and incorrect answers, mainly because the text and code no longer connected

+6
source share
1 answer

No , this is not a mistake. This is just a bad test.

Description

The only difference between GCC and clang in this case is how they handle template class functions:

  • GCC : they are all in one go.
  • clang : only the one that was used.

In our first example, the min() function is not called, so clang has no problem with it. GCC parses all the functions and finds that min() invalid.

In the second example, the same thing happens: bar() not called by anyone, and therefore clang is fine, as it is poorly formed. But again, GCC , the problem with it, although it was not used anywhere else in the program.

Good test

Saying something bad is not enough, let’s fix it: this example will fail with GCC and clang with almost the same error ( invalid abstract return type 'base' or allocating an object of abstract class type 'base' ).

 #include <limits> struct base { virtual void foo() = 0; }; int main() { (void)std::numeric_limits<base>::min(); } 
+1
source

Source: https://habr.com/ru/post/1012066/


All Articles