diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2018-04-17 10:09:50 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2018-04-20 12:56:32 +0000 |
commit | 96a2c7633cc020bef7ad38a57094dc1287f1aceb (patch) | |
tree | 759793349575aeb44a325762f994d811c1ea99ab | |
parent | 6cf3d21e004e99cb7d8f8314b3b6103f2e8a5482 (diff) |
Fix completion involving overloaded static functions for templates
--------------------------------------------------------------------------
* https://reviews.llvm.org/D43453
--------------------------------------------------------------------------
Apply almost the same fix as D36390 but for templates.
Change-Id: I80b44d69898237f2f2b4310bc330120b7dfc49a8
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 79 | ||||
-rw-r--r-- | test/Index/complete-call.cpp | 49 |
2 files changed, 88 insertions, 40 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f2b1963df1..93b5070c83 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6366,57 +6366,56 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, 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 (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, FunctionArgs, CandidateSet, - SuppressUserConversions, PartialOverloading); - } else { - // 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 { - FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); - if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && - !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) { - QualType ObjectType; - Expr::Classification ObjectClassification; + ArrayRef<Expr *> FunctionArgs = Args; + + FunctionTemplateDecl *FunTmpl = nullptr; + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + + const bool IsTemplate = FD ? false : true; + if (IsTemplate) { + FunTmpl = cast<FunctionTemplateDecl>(D); + FD = FunTmpl->getTemplatedDecl(); + } + + if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { + QualType ObjectType; + Expr::Classification ObjectClassification; + 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); + } + if (IsTemplate) AddMethodTemplateCandidate( FunTmpl, F.getPair(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), ExplicitTemplateArgs, ObjectType, ObjectClassification, - Args.slice(1), CandidateSet, SuppressUserConversions, + FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); - } else { - AddTemplateOverloadCandidate(FunTmpl, F.getPair(), - ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions, - PartialOverloading); + else + AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), + cast<CXXMethodDecl>(FD)->getParent(), ObjectType, + ObjectClassification, FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); + } else { + // 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); } + if (IsTemplate) + AddTemplateOverloadCandidate( + FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, + CandidateSet, SuppressUserConversions, PartialOverloading); + else + AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); } } } diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp index ca116485ac..35f2009066 100644 --- a/test/Index/complete-call.cpp +++ b/test/Index/complete-call.cpp @@ -112,6 +112,33 @@ struct Bar2 : public Bar { } }; +struct BarTemplates { + static void foo_1() {} + void foo_1(float) {} + static void foo_1(int) {} + + template<class T1, class T2> + static void foo_1(T1 a, T2 b) { a + b; } + + template<class T1, class T2> + void foo_1(T1 a, T2 b, float c) { a + b + c; } + + template<class T1, class T2> + static void foo_1(T2 a, int b, T1 c) { a + b + c; } +}; + +void testTemplates() { + BarTemplates::foo_1(); + BarTemplates b; + b.foo_1(); +} + +struct Bar2Template : public BarTemplates { + Bar2Template() { + BarTemplates::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: @@ -864,3 +891,25 @@ struct Bar2 : public Bar { // CHECK-CC62-NEXT: Nested name specifier // CHECK-CC62-NEXT: Objective-C interface +// RUN: c-index-test -code-completion-at=%s:131:23 %s | FileCheck -check-prefix=CHECK-CC63 %s +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC63: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:133:11 %s | FileCheck -check-prefix=CHECK-CC64 %s +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC64: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) + +// RUN: c-index-test -code-completion-at=%s:138:25 %s | FileCheck -check-prefix=CHECK-CC65 %s +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter float}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter int}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T1 a}{Comma , }{Placeholder T2 b}{Comma , }{Placeholder float c}{RightParen )} (1) +// CHECK-CC65: OverloadCandidate:{ResultType void}{Text foo_1}{LeftParen (}{CurrentParameter T2 a}{Comma , }{Placeholder int b}{Comma , }{Placeholder T1 c}{RightParen )} (1) |