summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2017-10-26 08:41:28 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2017-10-26 08:41:28 +0000
commit9bc9ee5d23d2b0b3c18dd86ce6b8aeae0aeb1bde (patch)
tree794ba22e9ee1bab313dbc29f76cbb828ed079a99
parente367d87861964e630d684b5780794c34fabf6a46 (diff)
downloadclang-9bc9ee5d23d2b0b3c18dd86ce6b8aeae0aeb1bde.tar.gz
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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316646 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaCodeComplete.cpp4
-rw-r--r--lib/Sema/SemaOverload.cpp28
-rw-r--r--test/Index/complete-call.cpp61
4 files changed, 86 insertions, 10 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index ba9b604ebc..a156e88da6 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -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,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 06246d469f..a0d8c9941e 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4396,9 +4396,11 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
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))
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 49e9126afc..8efb7c69d3 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -6343,24 +6343,36 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
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 {
diff --git a/test/Index/complete-call.cpp b/test/Index/complete-call.cpp
index 9750bd6f71..ca116485ac 100644
--- a/test/Index/complete-call.cpp
+++ b/test/Index/complete-call.cpp
@@ -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
+