forked from OSchip/llvm-project
[libclang] Fix crash in member access code completion with implicit base
If there is an unresolved member access AST node, and the base is implicit, do not access/use it for generating candidate overloads for code completion results. Fixes PR31093. llvm-svn: 298903
This commit is contained in:
parent
9f3eca96eb
commit
f1898cfa42
|
@ -4318,7 +4318,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());
|
||||
|
|
|
@ -6307,30 +6307,45 @@ 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, SuppressUserConversions,
|
||||
PartialOverloading);
|
||||
else
|
||||
cast<CXXMethodDecl>(FD)->getParent(), ObjectType,
|
||||
ObjectClassification, Args.slice(1), CandidateSet,
|
||||
SuppressUserConversions, PartialOverloading);
|
||||
} 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, PartialOverloading);
|
||||
else
|
||||
ExplicitTemplateArgs, ObjectType, ObjectClassification,
|
||||
Args.slice(1), CandidateSet, SuppressUserConversions,
|
||||
PartialOverloading);
|
||||
} else {
|
||||
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
|
||||
ExplicitTemplateArgs, Args,
|
||||
CandidateSet, SuppressUserConversions,
|
||||
PartialOverloading);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,17 @@ struct Test1 {
|
|||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -52,3 +63,6 @@ struct Test1 {
|
|||
|
||||
// Make sure this doesn't crash
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:36:7 %s -verify
|
||||
|
||||
// Make sure this also doesn't crash
|
||||
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:47:14 %s
|
||||
|
|
Loading…
Reference in New Issue