summaryrefslogtreecommitdiff
path: root/dist
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@qt.io>2017-07-11 11:17:36 +0200
committerNikolai Kosjar <nikolai.kosjar@qt.io>2017-07-13 13:23:35 +0000
commitf2041c788144c8625ce264e35e5e813676868d6c (patch)
treec704ad272862a7919cb2dd62257a415231d0a7d9 /dist
parente88fcdbdb6ae7cc19d2ea47e06e5f65c77b4baf7 (diff)
downloadqt-creator-f2041c788144c8625ce264e35e5e813676868d6c.tar.gz
Clang: Add patch fixing crash in completion
...with overloads. https://bugs.llvm.org/show_bug.cgi?id=31093 Change-Id: I2f177794d8d84c91b5bc47da38a3a6c90f8d8d55 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'dist')
-rw-r--r--dist/clang/patches/D30248_Fix-crash-in-member-access-code-completion-with-implicit-base.patch126
1 files changed, 126 insertions, 0 deletions
diff --git a/dist/clang/patches/D30248_Fix-crash-in-member-access-code-completion-with-implicit-base.patch b/dist/clang/patches/D30248_Fix-crash-in-member-access-code-completion-with-implicit-base.patch
new file mode 100644
index 0000000000..b8e0afab2e
--- /dev/null
+++ b/dist/clang/patches/D30248_Fix-crash-in-member-access-code-completion-with-implicit-base.patch
@@ -0,0 +1,126 @@
+diff --git a/tools/clang/lib/Sema/SemaCodeComplete.cpp b/tools/clang/lib/Sema/SemaCodeComplete.cpp
+index f4b51a19c2..f4b35fd408 100644
+--- a/tools/clang/lib/Sema/SemaCodeComplete.cpp
++++ b/tools/clang/lib/Sema/SemaCodeComplete.cpp
+@@ -4066,7 +4066,10 @@ void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) {
+ UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
+ TemplateArgs = &TemplateArgsBuffer;
+ }
+- SmallVector<Expr *, 12> ArgExprs(1, UME->getBase());
++
++ // Add the base as first argument (use a nullptr if the base is implicit).
++ SmallVector<Expr *, 12> ArgExprs(
++ 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
+ ArgExprs.append(Args.begin(), Args.end());
+ UnresolvedSet<8> Decls;
+ Decls.append(UME->decls_begin(), UME->decls_end());
+diff --git a/tools/clang/lib/Sema/SemaOverload.cpp b/tools/clang/lib/Sema/SemaOverload.cpp
+index 40d6e910f1..19547237ac 100644
+--- a/tools/clang/lib/Sema/SemaOverload.cpp
++++ b/tools/clang/lib/Sema/SemaOverload.cpp
+@@ -6051,31 +6051,44 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
+ for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
+ NamedDecl *D = F.getDecl()->getUnderlyingDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+- if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
++ 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.
+ AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
+- cast<CXXMethodDecl>(FD)->getParent(),
+- Args[0]->getType(), Args[0]->Classify(Context),
+- Args.slice(1), CandidateSet,
++ cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
++ ObjectClassification, Args.slice(1), CandidateSet,
+ SuppressUserConversions, PartialOverloading);
+- else
++ } else {
+ AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet,
+ SuppressUserConversions, PartialOverloading);
++ }
+ } else {
+ FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
+ if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
+- !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
++ !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->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.
+ AddMethodTemplateCandidate(FunTmpl, F.getPair(),
+- cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
+- ExplicitTemplateArgs,
+- Args[0]->getType(),
+- Args[0]->Classify(Context), Args.slice(1),
+- CandidateSet, SuppressUserConversions,
++ cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
++ ExplicitTemplateArgs, ObjectType, ObjectClassification,
++ Args.slice(1), CandidateSet, SuppressUserConversions,
+ PartialOverloading);
+- else
++ } else {
+ AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
+ ExplicitTemplateArgs, Args,
+ CandidateSet, SuppressUserConversions,
+ PartialOverloading);
++ }
+ }
+ }
+ }
+diff --git a/tools/clang/test/CodeCompletion/member-access.cpp b/tools/clang/test/CodeCompletion/member-access.cpp
+index 8f772c0652..8528e18649 100644
+--- a/tools/clang/test/CodeCompletion/member-access.cpp
++++ b/tools/clang/test/CodeCompletion/member-access.cpp
+@@ -27,16 +27,31 @@ public:
+
+ void test(const Proxy &p) {
+ p->
+- // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
+- // CHECK-CC1: Base1 : Base1::
+- // CHECK-CC1: member1 : [#int#][#Base1::#]member1
+- // CHECK-CC1: member1 : [#int#][#Base2::#]member1
+- // CHECK-CC1: member2 : [#float#][#Base1::#]member2
+- // CHECK-CC1: member3
+- // CHECK-CC1: member4
+- // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
+- // CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
+- // CHECK-CC1: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
+- // CHECK-CC1: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
+- // CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
+-
++}
++
++struct Foo {
++ void foo() const;
++ static void foo(bool);
++};
++
++struct Bar {
++ void foo(bool param) {
++ Foo::foo( );// unresolved member expression with an implicit base
++ }
++};
++
++// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:29:6 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
++// CHECK-CC1: Base1 : Base1::
++// CHECK-CC1: member1 : [#int#][#Base1::#]member1
++// CHECK-CC1: member1 : [#int#][#Base2::#]member1
++// CHECK-CC1: member2 : [#float#][#Base1::#]member2
++// CHECK-CC1: member3
++// CHECK-CC1: member4
++// CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#float#>)
++// CHECK-CC1: memfun1 : [#void#][#Base3::#]memfun1(<#double#>)[# const#]
++// CHECK-CC1: memfun1 (Hidden) : [#void#]Base2::memfun1(<#int#>)
++// CHECK-CC1: memfun2 : [#void#][#Base3::#]memfun2(<#int#>)
++// CHECK-CC1: memfun3 : [#int#]memfun3(<#int#>)
++
++// Make sure this also doesn't crash
++// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:39:14 %s