[PATCH] Add DiagnosticSuppressionScope RAII class

Brad King brad.king at kitware.com
Wed Oct 29 06:10:21 PDT 2014


On 10/28/2014 05:46 PM, Richard Smith wrote:
> Right; that's how the C++ standard says SFINAE works.

Sure, but I'm not performing a SFINAE test.  That's why SFINAETrap is not
sufficient.  I'm not trying to replace SFINAETrap.  I'm trying to provide
a new primitive that is useful to tools based on Clang to achieve things
that are currently not possible.

> if you suppress errors here, things will go wrong later
> (later tests which happen to look at validity of the same thing can
> get incorrect answers).

IIUC a declaration that has been marked invalid is considered to not exist
by such later tests.  See below.

> The problem is with a case like:
> 
> template<typename T> struct A {
>   A() { T::error; }
> };
> struct B : A<int> {};
> struct C : A<int> {};
> 
> Trying to create B::B() will trigger the instantiation of A<int>::A(),
> which will fail with a non-local error. We'll mark the function as invalid,
> and you'll determine that B::B() doesn't work. Then you'll try C::C(),
> which will *succeed*, because we'll silently skip A<int>::A() because we've
> already marked it invalid.

Clang calls setInvalidDecl on A::A() after failing to instantiate it for
B::B().  Then C::C() fails too because A::A() does not exist anymore.

I hacked my tool to take out the DiagnosticSuppressionScope for the
DefaultConstructor case and to print out a description of each implicit
member before attempting to define it.  The result on the above code is:

--------------------------------------------------------------------------
DefaultConstructor: B
test.cpp:2:9: error: type 'int' cannot be used prior to '::' because it has
      no members
  A() { T::error; }
        ^
test.cpp:4:8: note: in instantiation of member function 'A<int>::A' requested
      here
struct B : A<int> {};
       ^
DefaultConstructor: C
test.cpp:5:8: error: implicit default constructor for 'C' must explicitly
      initialize the base class 'A<int>' which does not have a default
      constructor
struct C : A<int> {};
       ^
--------------------------------------------------------------------------

One can see that both B::B() and C::C() get errors as desired.

Thanks,
-Brad




More information about the cfe-commits mailing list