summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaOverload.cpp80
-rw-r--r--test/Index/complete-call.cpp68
2 files changed, 98 insertions, 50 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 89cb9b53a4..b1df8f6232 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -6363,63 +6363,61 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
/// the overload candidate set.
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
ArrayRef<Expr *> Args,
- OverloadCandidateSet& CandidateSet,
+ OverloadCandidateSet &CandidateSet,
TemplateArgumentListInfo *ExplicitTemplateArgs,
bool SuppressUserConversions,
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 (Args.size() > 0) {
- if (Expr *E = Args[0]) {
- // Use the explicit 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 = dyn_cast<FunctionTemplateDecl>(D);
+ FunctionDecl *FD =
+ FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D);
+
+ if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) {
+ QualType ObjectType;
+ Expr::Classification ObjectClassification;
+ if (Args.size() > 0) {
if (Expr *E = Args[0]) {
// Use the explicit base to restrict the lookup:
ObjectType = E->getType();
ObjectClassification = E->Classify(Context);
- } // .. else there is an implit base.
+ } // .. else there is an implicit base.
+ FunctionArgs = Args.slice(1);
+ }
+ if (FunTmpl) {
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);
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
+ ObjectClassification, FunctionArgs, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
+ }
+ } else {
+ // This branch handles both standalone functions and static methods.
+
+ // 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 (FunTmpl) {
+ 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..84189a2aab 100644
--- a/test/Index/complete-call.cpp
+++ b/test/Index/complete-call.cpp
@@ -109,12 +109,39 @@ void test() {
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:
+ }
+};
+
+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:
// CHECK-CC1-NEXT: Any type
// CHECK-CC1-NEXT: Any value
// CHECK-CC1-NEXT: Enum tag
@@ -860,7 +887,30 @@ struct Bar2 : public Bar {
// 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
+// CHECK-CC62-NEXT: Class name
+// 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)