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

Aaron Ballman aaron.ballman at gmail.com
Fri Jul 11 08:44:58 PDT 2014


On Fri, Jul 11, 2014 at 12:57 AM, Nikola Smiljanić <popizdeh at gmail.com> wrote:
> Hi aaron.ballman, rnk, rsmith,
>
> This is a re-based version of Martin's patch from the bug report with few minor changes by me.
>
> I don't think that we have to implement this feature identically to msvc, but I'm not opposed to it. I'd like to implement it in such a way that allows us to compile MFC code that depends on it. With that said here are some open questions.
>
>   - MSDN says that __super can't be used with using declarations but current patch doesn't emit a diagnostic in this case. I'd say that we don't have to because since msvc doesn't allow this there's no code written that does it.

I would weakly prefer to diagnose. I don't think we want to implement
an MSVC language extension in such a way that it then can't be used in
MSVC itself.

>   - MSDN says that all accessible base class methods are considered during overload resolution with best one being selected. This is different from normal C++ rules where ordinary name lookup results in ambiguity. Current patch doesn't implement this logic (second test case fails) but similarly to my previous observation we might not need it as MFC doesn't use multiple inheritance. Client's might run into this issue in their classes, but in that case they can fix the code and move away from this extension.

I think we should attempt to be as compatible as is reasonable with MSVC. Eg)

#include <stdio.h>

struct Base1 {
  void foo(double) { ::printf("Base1::foo\n"); }
};

struct Middle {
  void foo(int) { ::printf("Middle::foo\n"); }
};

struct Derived : public Middle, public Base1 {
  void foo() {
    ::printf("Derived::foo\n");
    __super::foo(1.0);
  }
};

int main(void) {
  Derived D;
  D.foo();
}

This compiles in MSVC and outputs Derived::foo\nBase1::foo()\n, but
causes an assert with this patch.

E:\llvm\2013>clang "E:\Aaron Ballman\Documents\Visual Studio
2013\Projects\Cpp Tester\Cpp Tester\main.cpp"
Assertion failed: !R.empty() && !R.isAmbiguous(), file
E:\llvm\llvm\tools\clang\lib\Sema\SemaExprMember.cpp, line 1714

I'm pretty sure we all agree an assert isn't ideal. ;-) But I still
think this code is reasonable to support. Does it require feats of
heroics to implement support?

Other things I noticed in terms of compilation differences:

template <typename Ty>
struct Base {
  void foo() { ::printf("Base::foo\n"); }
};

template <typename Ty>
struct Derived : public Base<Ty> {
  void foo() {
    __super::foo();
  }
};

int main(void) {
  Derived<int> D;
  D.foo();
}

This compiles in MSVC, but yields:
E:\Aaron Ballman\Documents\Visual Studio 2013\Projects\Cpp Tester\Cpp
Tester\main.cpp:26:14: error:
      no member named 'foo' in 'Derived'
    __super::foo();
             ^
The following code has less than ideal diagnostics:

struct Base {};

struct Derived : public Base {
  void foo() {
    __super::nothing();
  }
};

E:\Aaron Ballman\Documents\Visual Studio 2013\Projects\Cpp Tester\Cpp
Tester\main.cpp:34:14: error:
      no member named 'nothing' in 'Derived'
    __super::nothing();
             ^

I can do more actual review of the code when I have some cycles to
spare for it, I just wanted to bring these points up before I lost
track of them.

Thank you for working on this!

~Aaron




More information about the cfe-commits mailing list