In Microsoft mode, if we are inside a template class member function and we can't resolve a function call then create a type-dependent CallExpr even if the function has no type dependent arguments. The goal is to postpone name lookup to instantiation time to be able to search into type dependent base classes.
With this patch in, clang will generate only 37 errors (down from 212) when parsing a typical MFC source file.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139210 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 076602f..cbcbef9 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1456,6 +1456,8 @@
CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>(
CurMethod->getInstantiatedFromMemberFunction());
if (DepMethod) {
+ if (getLangOptions().Microsoft)
+ diagnostic = diag::warn_found_via_dependent_bases_lookup;
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
QualType DepThisType = DepMethod->getThisType(Context);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 6f3b1aa..4f36189 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -8289,9 +8289,22 @@
// If we found nothing, try to recover.
// BuildRecoveryCallExpr diagnoses the error itself, so we just bail
// out if it fails.
- if (CandidateSet.empty())
+ if (CandidateSet.empty()) {
+ // In Microsoft mode, if we are inside a template class member function then
+ // create a type dependent CallExpr. The goal is to postpone name lookup
+ // to instantiation time to be able to search into type dependent base
+ // classes.
+ if (getLangOptions().Microsoft && CurContext->isDependentContext() &&
+ isa<CXXMethodDecl>(CurContext)) {
+ CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, NumArgs,
+ Context.DependentTy, VK_RValue,
+ RParenLoc);
+ CE->setTypeDependent(true);
+ return Owned(CE);
+ }
return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs,
RParenLoc, /*EmptyLookup=*/true);
+ }
OverloadCandidateSet::iterator Best;
switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {