forked from OSchip/llvm-project
[Sema] Fix overloaded static functions for templates
Apply almost the same fix as https://reviews.llvm.org/D36390 but for templates. Differential Revision: https://reviews.llvm.org/D43453 llvm-svn: 335211
This commit is contained in:
parent
a465188500
commit
f83cfda02b
|
@ -6370,8 +6370,12 @@ 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;
|
||||
|
||||
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;
|
||||
|
@ -6380,46 +6384,40 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
|
|||
// 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);
|
||||
}
|
||||
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;
|
||||
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.
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,26 @@ 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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue