Clang: Fix crash in connect() statement

With this patch ClangCodeModel can properly
handle static overloads together with non-static ones.

Code completion still might crash - requires another patch.

Task-number: QTCREATORBUG-19184
Change-Id: I12f0e8cb56b3bed3f5ca1f7a9fe4ca3932b78125
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-02-19 08:36:12 +01:00
parent 41efaf1253
commit b90f2fb251
2 changed files with 157 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2707,7 +2707,8 @@
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,
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4396,9 +4396,11 @@
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))
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -6343,24 +6343,36 @@
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 {
--- a/test/Index/complete-call.cpp
+++ b/test/Index/complete-call.cpp
@@ -94,6 +94,24 @@
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 @@
// 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
+

View File

@@ -112,3 +112,12 @@ Significantly reduces problems when saving a header file on Windows.
Builds Clazy as an LLVM part and forces link for Clazy plugin registry entry.
##### 200_D36390_Fix-overloaded-static-functions-in-SemaCodeComplete.patch
* <https://reviews.llvm.org/D36390>
* <https://bugs.llvm.org/show_bug.cgi?id=33904>
Fix overloaded static functions in SemaCodeComplete
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.