Author: d0k Date: Thu Oct 26 01:41:28 2017 New Revision: 316646 URL: http://llvm.org/viewvc/llvm-project?rev=316646&view=rev Log: Fix overloaded static functions in SemaCodeComplete
https://bugs.llvm.org/show_bug.cgi?id=33904 Happens when static function is accessed via the class variable. That leads to incorrect overloads number because the variable is considered as the first argument. struct Bar { static void foo(); static void foo(int); }; int main() { Bar b; b.foo(/*complete here*/); // did not work before Bar::foo(/*complete here*/); // worked fine } Patch by Ivan Donchevskii! Differential Revision: https://reviews.llvm.org/D36390 Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaCodeComplete.cpp cfe/trunk/lib/Sema/SemaOverload.cpp cfe/trunk/test/Index/complete-call.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=316646&r1=316645&r2=316646&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Oct 26 01:41:28 2017 @@ -2707,7 +2707,8 @@ public: OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, bool SuppressUserConversions = false, - bool PartialOverloading = false); + bool PartialOverloading = false, + bool FirstArgumentIsBase = false); void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=316646&r1=316645&r2=316646&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original) +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Oct 26 01:41:28 2017 @@ -4396,9 +4396,11 @@ void Sema::CodeCompleteCall(Scope *S, Ex ArgExprs.append(Args.begin(), Args.end()); UnresolvedSet<8> Decls; Decls.append(UME->decls_begin(), UME->decls_end()); + const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, /*SuppressUsedConversions=*/false, - /*PartialOverloading=*/true); + /*PartialOverloading=*/true, + FirstArgumentIsBase); } else { FunctionDecl *FD = nullptr; if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) Modified: cfe/trunk/lib/Sema/SemaOverload.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=316646&r1=316645&r2=316646&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) +++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Oct 26 01:41:28 2017 @@ -6343,24 +6343,36 @@ void Sema::AddFunctionCandidates(const U OverloadCandidateSet& CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, - bool PartialOverloading) { + bool PartialOverloading, + bool FirstArgumentIsBase) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + ArrayRef<Expr *> FunctionArgs = Args; if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { QualType ObjectType; Expr::Classification ObjectClassification; - if (Expr *E = Args[0]) { - // Use the explit base to restrict the lookup: - ObjectType = E->getType(); - ObjectClassification = E->Classify(Context); - } // .. else there is an implit base. + if (Args.size() > 0) { + if (Expr *E = Args[0]) { + // Use the explit base to restrict the lookup: + ObjectType = E->getType(); + ObjectClassification = E->Classify(Context); + } // .. else there is an implit base. + FunctionArgs = Args.slice(1); + } AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), cast<CXXMethodDecl>(FD)->getParent(), ObjectType, - ObjectClassification, Args.slice(1), CandidateSet, + ObjectClassification, FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); } else { - AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, + // Slice the first argument (which is the base) when we access + // static method as non-static + if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && + !isa<CXXConstructorDecl>(FD)))) { + assert(cast<CXXMethodDecl>(FD)->isStatic()); + FunctionArgs = Args.slice(1); + } + AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); } } else { Modified: cfe/trunk/test/Index/complete-call.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-call.cpp?rev=316646&r1=316645&r2=316646&view=diff ============================================================================== --- cfe/trunk/test/Index/complete-call.cpp (original) +++ cfe/trunk/test/Index/complete-call.cpp Thu Oct 26 01:41:28 2017 @@ -94,6 +94,24 @@ int main() { s.foo_7(42,); } +struct Bar { + static void foo_1(); + void foo_1(float); + static void foo_1(int); +}; + +void test() { + Bar::foo_1(); + Bar b; + b.foo_1(); +} + +struct Bar2 : public Bar { + Bar2() { + Bar::foo_1(); + } +}; + // RUN: c-index-test -code-completion-at=%s:47:9 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) // CHECK-CC1: Completion contexts: @@ -803,3 +821,46 @@ int main() { // CHECK-CC59-NEXT: Class name // CHECK-CC59-NEXT: Nested name specifier // CHECK-CC59-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:104:14 %s | FileCheck -check-prefix=CHECK-CC60 %s +// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC60: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC60: Completion contexts: +// CHECK-CC60-NEXT: Any type +// CHECK-CC60-NEXT: Any value +// CHECK-CC60-NEXT: Enum tag +// CHECK-CC60-NEXT: Union tag +// CHECK-CC60-NEXT: Struct tag +// CHECK-CC60-NEXT: Class name +// CHECK-CC60-NEXT: Nested name specifier +// CHECK-CC60-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:106:11 %s | FileCheck -check-prefix=CHECK-CC61 %s +// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC61: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC61: Completion contexts: +// CHECK-CC61-NEXT: Any type +// CHECK-CC61-NEXT: Any value +// CHECK-CC61-NEXT: Enum tag +// CHECK-CC61-NEXT: Union tag +// CHECK-CC61-NEXT: Struct tag +// CHECK-CC61-NEXT: Class name +// CHECK-CC61-NEXT: Nested name specifier +// CHECK-CC61-NEXT: Objective-C interface + +// RUN: c-index-test -code-completion-at=%s:111:16 %s | FileCheck -check-prefix=CHECK-CC62 %s +// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC62: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC62: Completion contexts: +// CHECK-CC62-NEXT: Any type +// CHECK-CC62-NEXT: Any value +// CHECK-CC62-NEXT: Enum tag +// CHECK-CC62-NEXT: Union tag +// CHECK-CC62-NEXT: Struct tag +// CHECK-CC62-NEXT: Class name +// CHECK-CC62-NEXT: Nested name specifier +// CHECK-CC62-NEXT: Objective-C interface + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits