This is an archive of the discontinued LLVM Phabricator instance.

[MSVC] Improved late parsing of template functions.
Needs ReviewPublic

Authored by ABataev on Jul 28 2016, 9:47 PM.

Details

Summary

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. Patch tries to improve compatibility between clang and MSVC. Each time a new instantiation of the function is required, a new copy of the original templated function is created and the body of original function is parsed in the context of this new copy. If unqualified lookup is detected, patch tries to find the required name in the instantiated context. Also, if the original template function is instantiated, but not used, its body is not parsed and not instantiated (it emulates MSVC behavior).
Patch significantly improves compatibility with ATL/WTL headers, but does not solve troubles with unqualified lookup in dependent bases in default initializers of members, types of member functions/data members and default values of function arguments. This must be fixed later.

Diff Detail

Event Timeline

ABataev updated this revision to Diff 66077.Jul 28 2016, 9:47 PM
ABataev retitled this revision from to [MSVC] Improved late parsing of template functions..
ABataev updated this object.
ABataev added reviewers: rnk, rsmith, majnemer.
ABataev added subscribers: cfe-commits, andreybokhanko.
EricWF added a subscriber: EricWF.Oct 12 2016, 8:25 AM
majnemer added inline comments.Oct 12 2016, 10:50 AM
lib/Sema/SemaLookup.cpp
1044–1070

This looks a lot like forallBases, any chance it could be reused?

ABataev added inline comments.Oct 14 2016, 6:53 AM
lib/Sema/SemaLookup.cpp
1044–1070

Yes, they are very similar, but forallBases() is a bit different. It checks that the provided callback returns true for all bases. In this case I need a single match, while other bases may not match. That's why I can't reuse forallBases().

rnk edited edge metadata.Nov 16 2016, 4:19 PM

If I understand correctly, this patch takes template function patterns, copies them into instantiated context, parses them in that context, and then instantiates them in that context. The key difference is that today's fdelayed-template-parsing doesn't parse the body of the function in the instantiation context. It just allows access to names at global scope that were encountered after the template pattern.

So, if I run -ast-dump, do I end up seeing both the pattern and the fully instantiated function with this patch?

This patch removes a lot of warnings from our tests. We lose a lot of our ability to diagnose MSVC-isms with this approach. I wonder if there's a better way to do delayed template parsing the way we were before, but make the template arguments available during lookup.

In D22955#598081, @rnk wrote:

If I understand correctly, this patch takes template function patterns, copies them into instantiated context, parses them in that context, and then instantiates them in that context. The key difference is that today's fdelayed-template-parsing doesn't parse the body of the function in the instantiation context. It just allows access to names at global scope that were encountered after the template pattern.

So, if I run -ast-dump, do I end up seeing both the pattern and the fully instantiated function with this patch?

This patch removes a lot of warnings from our tests. We lose a lot of our ability to diagnose MSVC-isms with this approach. I wonder if there's a better way to do delayed template parsing the way we were before, but make the template arguments available during lookup.

In D22955#598081, @rnk wrote:

If I understand correctly, this patch takes template function patterns, copies them into instantiated context, parses them in that context, and then instantiates them in that context. The key difference is that today's fdelayed-template-parsing doesn't parse the body of the function in the instantiation context. It just allows access to names at global scope that were encountered after the template pattern.

Yes, you're right.

So, if I run -ast-dump, do I end up seeing both the pattern and the fully instantiated function with this patch?

No, you will see only instantiated function.

This patch removes a lot of warnings from our tests. We lose a lot of our ability to diagnose MSVC-isms with this approach. I wonder if there's a better way to do delayed template parsing the way we were before, but make the template arguments available during lookup.

Yes, this is the price we should pay for better MSVC compatibility. I tried several different solutions before ended up with this one and have to say this one is the best I was able to find.

ABataev removed a reviewer: erichkeane.
ABataev edited subscribers, added: erichkeane; removed: andreybokhanko.