From: Hans Wennborg Date: Thu, 11 Jun 2015 21:21:57 +0000 (+0000) Subject: [ms] Do lookup in dependent base classes also when overload resolution fails (PR23810) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9f6e65403db1d44653708fb581b2a61479633b52;p=clang [ms] Do lookup in dependent base classes also when overload resolution fails (PR23810) This patch does two things in order to enable compilation of the problematic code in PR23810: 1. In Sema::buildOverloadedCallSet, it postpones lookup for MS mode when no viable candidate is found in the overload set. Previously, lookup would only be postponed here if the overload set was empty. 2. Make BuildRecoveryCallExpr call Sema::DiagnoseEmptyLookup under more circumstances. There is a comment in DiagnoseTwoPhaseLookup that says "Don't diagnose names we find in classes; we get much better diagnostics for these from DiagnoseEmptyLookup." The problem was that DiagnoseEmptyLookup might not get called later, and we failed to recover. Differential Revision: http://reviews.llvm.org/D10369 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@239558 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9d87a103ac..117ca135a2 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -10507,7 +10507,8 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS, LookupResult &R, OverloadCandidateSet::CandidateSetKind CSK, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef Args) { + ArrayRef Args, + bool *DoDiagnoseEmptyLookup = nullptr) { if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) return false; @@ -10524,6 +10525,8 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, // Don't diagnose names we find in classes; we get much better // diagnostics for these from DiagnoseEmptyLookup. R.clear(); + if (DoDiagnoseEmptyLookup) + *DoDiagnoseEmptyLookup = true; return false; } @@ -10673,15 +10676,16 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); + bool DoDiagnoseEmptyLookup = EmptyLookup; if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, OverloadCandidateSet::CSK_Normal, - ExplicitTemplateArgs, Args) && - (!EmptyLookup || - SemaRef.DiagnoseEmptyLookup( - S, SS, R, - MakeValidator(SemaRef, dyn_cast(Fn), Args.size(), - ExplicitTemplateArgs != nullptr, AllowTypoCorrection), - ExplicitTemplateArgs, Args))) + ExplicitTemplateArgs, Args, + &DoDiagnoseEmptyLookup) && + (!DoDiagnoseEmptyLookup || SemaRef.DiagnoseEmptyLookup( + S, SS, R, + MakeValidator(SemaRef, dyn_cast(Fn), Args.size(), + ExplicitTemplateArgs != nullptr, AllowTypoCorrection), + ExplicitTemplateArgs, Args))) return ExprError(); assert(!R.empty() && "lookup results empty despite recovery"); @@ -10746,26 +10750,28 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, // functions, including those from argument-dependent lookup. AddOverloadedCallCandidates(ULE, Args, *CandidateSet); - // If we found nothing, try to recover. - // BuildRecoveryCallExpr diagnoses the error itself, so we just bail - // out if it fails. - 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 (getLangOpts().MSVCCompat && CurContext->isDependentContext() && - (isa(CurContext) || isa(CurContext))) { - CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, - Context.DependentTy, VK_RValue, - RParenLoc); + if (getLangOpts().MSVCCompat && CurContext->isDependentContext() && + (isa(CurContext) || isa(CurContext))) { + + OverloadCandidateSet::iterator Best; + if (CandidateSet->empty() || + CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best) == + OR_No_Viable_Function) { + // 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. + CallExpr *CE = new (Context) CallExpr( + Context, Fn, Args, Context.DependentTy, VK_RValue, RParenLoc); CE->setTypeDependent(true); *Result = CE; return true; } - return false; } + if (CandidateSet->empty()) + return false; + UnbridgedCasts.restore(); return false; } diff --git a/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 62451081c3..90e9f0a48a 100644 --- a/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -547,3 +547,19 @@ struct E : D XXX x; // expected-error {{unknown type name}} }; } + +namespace PR23810 { +void f(int); +struct Base { + void f(); // expected-note{{must qualify identifier to find this declaration in dependent base class}} +}; +template struct Template : T { + void member() { + f(); // expected-warning {{found via unqualified lookup into dependent bases}} + } +}; +void test() { + Template x; + x.member(); // expected-note{{requested here}} +}; +}