diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-07-11 11:17:36 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2017-07-13 13:23:35 +0000 |
commit | f2041c788144c8625ce264e35e5e813676868d6c (patch) | |
tree | c704ad272862a7919cb2dd62257a415231d0a7d9 /dist | |
parent | e88fcdbdb6ae7cc19d2ea47e06e5f65c77b4baf7 (diff) | |
download | qt-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.patch | 126 |
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 |