From: Nick Lewycky Date: Tue, 6 Jul 2010 19:51:49 +0000 (+0000) Subject: Fix multiple emission of the this-> fixit for each instantiation by fixing the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03d98c5d592d74ae97aa3f93f80441b64960e4b6;p=clang Fix multiple emission of the this-> fixit for each instantiation by fixing the AST during the instantiation. Fixes PR7417! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107690 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index c8294109fc..cbbaa1d64e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2793,6 +2793,7 @@ public: const CXXMethodDecl *Old); bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); + //===--------------------------------------------------------------------===// // C++ Access Control // @@ -3562,6 +3563,12 @@ public: /// to implement it anywhere else. ActiveTemplateInstantiation LastTemplateInstantiationErrorContext; + /// \brief The stack of calls expression undergoing template instantiation. + /// + /// The top of this stack is used by a fixit instantiating unresolved + /// function calls to fix the AST to match the textual change it prints. + llvm::SmallVector CallsUndergoingInstantiation; + /// \brief A stack object to be created when performing template /// instantiation. /// diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bfcf25fb94..8b7c689ae2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -869,8 +869,8 @@ static void DiagnoseInstanceReference(Sema &SemaRef, /// Diagnose an empty lookup. /// /// \return false if new lookup candidates were found -bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, - LookupResult &R, CorrectTypoContext CTC) { +bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectTypoContext CTC) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -886,7 +886,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - for (DeclContext *DC = SS.isEmpty()? CurContext : 0; + for (DeclContext *DC = SS.isEmpty() ? CurContext : 0; DC; DC = DC->getParent()) { if (isa(DC)) { LookupQualifiedName(R, DC); @@ -903,11 +903,29 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // Give a code modification hint to insert 'this->'. // TODO: fixit for inserting 'Base::' in the other cases. // Actually quite difficult! - if (isInstance) + if (isInstance) { Diag(R.getNameLoc(), diagnostic) << Name << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); - else + + UnresolvedLookupExpr *ULE = cast( + CallsUndergoingInstantiation.back()->getCallee()); + CXXMethodDecl *DepMethod = cast( + CurMethod->getInstantiatedFromMemberFunction()); + QualType DepThisType = DepMethod->getThisType(Context); + CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(), + DepThisType, false); + TemplateArgumentListInfo TList; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TList); + CXXDependentScopeMemberExpr *DepExpr = + CXXDependentScopeMemberExpr::Create( + Context, DepThis, DepThisType, true, SourceLocation(), + ULE->getQualifier(), ULE->getQualifierRange(), NULL, Name, + R.getNameLoc(), &TList); + CallsUndergoingInstantiation.back()->setCallee(DepExpr); + } else { Diag(R.getNameLoc(), diagnostic) << Name; + } // Do we really want to note all of these? for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index cc9f600215..9e454bc0f2 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -620,6 +620,14 @@ namespace { QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL, QualType ObjectType); + + Sema::OwningExprResult TransformCallExpr(CallExpr *CE) { + getSema().CallsUndergoingInstantiation.push_back(CE); + OwningExprResult Result = + TreeTransform::TransformCallExpr(CE); + getSema().CallsUndergoingInstantiation.pop_back(); + return move(Result); + } }; }