antekone
antekone

Reputation: 2115

Forcing clang to generate compilation error on this snippet of C++ code

I have this invalid code:

class X {
public:
    virtual void func() = 0;
};

class JustDeclared {
    X missing();
};


int main() { return 0; }

It doesn't compile under gcc because it's impossible to create an instance of an abstract class X, and exactly this has been declared as a return value of the JustDeclared::missing() method.

But clang++ and Visual Studio compile this snippet without problems. I suspect that it's due to simply stripping out unused part of the AST before the actual compilation.

But is it possible to enable some "pedantic" mode that will force clang to generate an error for this snippet?

Upvotes: 3

Views: 439

Answers (1)

dfrib
dfrib

Reputation: 73176

Up until C++14, and in the original release of C++17, this is considered a bug in both Clang and MSVC, for Clang (see below) and likely for MSVC due to abstract class type diagnostics being performed at the time of function definition rather than at (first) function declaration (contrary to ISO standard rules). As is covered by this related Q&A which branched off from this question, however, as of C++20 and P0929R2 Clang and MSVC are actually correct to accept the program, whereas GCC is incorrect to reject it. As specified in P0636R3, P0929R2 should be considered a defect report in C++17.


All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.

Standarese behaviour up until C++17

As per [class.abstract]/3 [emphasis mine]

An abstract class shall not be used as a parameter type, as a function return type, or as the type of an explicit conversion. Pointers and references to an abstract class can be declared. [ Example:

shape x;           // error: object of abstract class
shape* p;          // OK
shape f();         // error
void g(shape);     // error
shape& h(shape&);  // OK

 — end example ]

an abstract class may not be used as a function return type, and thus your program is ill-formed, even if JustDeclared is not used.

For Clang, this is bug report

which has been dormant since 2016. An attempt to fix the bug was submitted in 2014:

which identified the same non-compliance with the standard as quoted above [emphasis mine]:

...

Attached patch contains the implementation of a fix for PR18393[1]. According to standard "An abstract class shall not be used as a parameter type, as a function return type, or as the type of an explicit conversion" (class.abstract $10.4.3).

Currently, checking if type isn't abstract class is done when method is defined, but I don't see any reason why clang shouldn't do it as early as possible, in this case, when function/method is declared. Test also attached.

...

The patch, however, is yet to be completed, and arguably seems dead in the water.


But is it possible to enable some "pedantic" mode that will force clang to generate an error for this snippet?

As covered above, for C++20 as well as C++17 (defect backporting) Clang is actually correct to accept the program. Thus, even if this was a bug up until C++14 (and the non-defect-ported C++17), the bug report above is likely to be deprecated as the standard has, as of P0929R2, changed into what was previously the buggy behaviour of Clang.

Note that If you not just declare but also define JustDeclared::missing(), Clang will correctly diagnose the program as ill-formed, by violation of [class.abstract]/3, which also holds for C++20 (/after applying P0929R2).

Upvotes: 4

Related Questions