[cfe-dev] RFC: [MSVC] Late parsing of in-class defined member functions in template classes after instantiation for better compatibility.

Alexey Bataev via cfe-dev cfe-dev at lists.llvm.org
Fri May 20 10:36:23 PDT 2016


Motivation
=========
Currently clang in MSVC compatibility mode has many troubles with MS provided headers (ATL / WTL), which use template classes.
MSVC actively uses unqualified lookup in dependent bases, lookup at the instantiation point (non-dependent names may be resolved on things declared later) etc. and all this stuff is the main cause of incompatibility between clang and MSVC.
Clang tries to emulate MSVC behavior but it may fail in many cases. For example:

template <class T>
struct S : public T {
       S(T) {}
       S() {}
       void foo() {
             S<T> bar(baz);
       }
};

struct S1 {
       int baz;
};

S<S1> s;

Similar code exists in WTL header files (for example, atlctrlx.h, atlctrlw.h etc.). Clang fails with the following messages:

test.cpp:6:12: error: unknown type name 'baz'
  S<T> bar(baz);
           ^
test.cpp:6:11: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
  S<T> bar(baz);
          ^~~~~
test.cpp:6:12: note: add a pair of parentheses to declare a variable
  S<T> bar(baz);

In addition, it may produce invalid AST from MSVC point of view:

typedef int baz;
template <class T>
struct S : public T {
       S() {}
       S(int) {}
       void foo() {
             S<T> bar(baz);
             ++bar.barz;
       }
};

struct S1 {
       static int baz;
       int barz;
};
int S1::baz = 0;

S<S1> s;

int main() {
       s.foo();
       return 0;
}

test.cpp:8:8: error: member reference base type 'S<S1> (baz)' (aka 'S<S1> (int)') is not a structure or union
  ++bar.barz;
    ~~~^~~~~
test.cpp:21:5: note: in instantiation of member function 'S<S1>::foo' requested here
  s.foo();

Though these examples are not "quite correct" but required for MSVC compatibility and parsing system headers.

Proposed solution
==============
It seems the only truly universal and generic solution would be to perform parsing of in-class defined member functions during instantiation of template classes (in MSVC compatibility mode only).
To do this clang could store lexed tokens for member functions definitions within ClassTemplateDecl for later parsing during template instantiation.
It will allow resolving many possible issues with lookup in dependent base classes and removing many already existing MSVC-specific hacks/workarounds from the clang code.

Please kindly provide feedback for the proposal stated above; we (Intel compiler team) plan to handle implementation to reach full clang compatibility with ATL / WTL headers and improve MSVC compatibility in general.
--

Best regards,
Alexey Bataev
=============
Software Engineer
Intel Compiler Team
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160520/cf95077c/attachment.html>


More information about the cfe-dev mailing list