[PATCH] PR13236 - Microsoft compatibility: support __super specifier to access members of base classes

Reid Kleckner rnk at google.com
Mon Jul 14 17:28:43 PDT 2014


On Mon, Jul 14, 2014 at 4:57 PM, Nikola Smiljanic <popizdeh at gmail.com>
wrote:

> On Tue, Jul 15, 2014 at 9:27 AM, Reid Kleckner <rnk at google.com> wrote:
>
>> I think their documentation is trying to warn the user that it won't work
>> if you use it in a class template.
>>
>
> I find you interpretation a bit of a stretch :) To me it means exactly
> what it says even though they don't implement it that way. Note that Aarons
> example with dependent base does work so this seems to break only if the
> base class is a template parameter.
>
> template <typename T>
> struct Base {
>   void foo();
> };
>
> template <typename T>
> struct Derived : Base<T> {
>   void bar() {
>     __super::foo();
>   }
> };
>

Yes, but this is because they will do lookup into base classes that are
implicit specializations of known templates.  For example, I could
introduce a specialization of Base<int> that defines foo as something else,
and they would do the wrong thing.

The reason that they would specifically bless __super in member functions
instead of class bodies is because they never appear to parse member
function bodies without first performing token substitution.  They do
appear to parse class bodies, so they can't handle __super when there are
bases that they need to look into.  Clang, on the other hand, always parses
both class bodies and method bodies before instantiation.


> I was also trying to figure out what you meant by "instantiate a template
> with a non-type template parameter using __super" and came up with this
> insanity:
>
> struct Base {
>   enum Enumerator {
>     One, Two
>   };
>
>   template <Enumerator e>
>   struct Inner {};
> };
>
> struct Derived : Base
> {
>   Inner<__super::One> x;
>   __super::Inner<Two> y;
> };
>
> First member declaration is ok but not the second one. It does work if you
> replace __super with Base. I can't say I understand their rules and that's
> why I suggested implementing __super only inside member functions as their
> documentation suggests.
>

Huh.  I actually had something like the 'x' declaration in mind.  I thought
it would tickle the relevant part of our mangler when we are mangling
nested-name-specifiers.  If you make that mangler case unreachable, does
the 'x' decl hit it?

Maybe try something with real decls, like:
struct A { int h(); };
template <int (A::*MP)()> struct X { static void f() {} };
struct B : A { static void g(); };
void B::g() {
  X<&__super::h>::f();
}

We should try to mangle __super while comping the name of
X<&__super::h>::f().

I'm not sure what to do with the 'y' decl case.  We could try to do
something, but if it's too hard, I'm OK with giving up and forbidding
__super outside of member functions.


> I think we need to do some overload resolution.  MSVC resolves __super to
>> B in this case:
>> struct A { void foo(int); };
>> struct B { void foo(short); };
>> struct C : A, B {
>>   void foo(short x) {
>>     __super::foo(x);
>>   }
>> };
>>
>> And they error out if you s/short/int/.
>>
>
> No surprises here, besides that I don't know how to exactly do this.
> Hopefully Richard will point me in the right direction. I had a look at
> OverloadCandidateSet and Sema::addOverloadCandidate but I couldn't figure
> out where to get argument expressions from.
>

I should look at the code again, but I was hoping this would fall right out
of the way you split the lookup.  :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140714/dbb2e875/attachment.html>


More information about the cfe-commits mailing list