summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2018-09-11 15:02:18 +0000
committerKadir Cetinkaya <kadircet@google.com>2018-09-11 15:02:18 +0000
commit84774c3ae3df8c71e0beffaf8553ac79f179fea5 (patch)
treed133c0734d7f80b3bdacfa2e16120708b4a228dc
parent98e4a5ca110e2e24ceb5d67873f935f8c82166bb (diff)
downloadbcm5719-llvm-84774c3ae3df8c71e0beffaf8553ac79f179fea5.tar.gz
bcm5719-llvm-84774c3ae3df8c71e0beffaf8553ac79f179fea5.zip
[CodeCompletion] Enable signature help when initializing class/struct/union members.
Summary: Factors out member decleration gathering and uses it in parsing to call signature help. Doesn't support signature help for base class constructors, the code was too coupled with diagnostic handling, but still can be factored out but just needs more afford. Reviewers: sammccall, ilya-biryukov, ioeric Reviewed By: ilya-biryukov Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D51917 llvm-svn: 341949
-rw-r--r--clang/include/clang/Sema/Sema.h12
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp16
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp19
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp41
-rw-r--r--clang/test/CodeCompletion/ctor-initializer.cpp24
5 files changed, 95 insertions, 17 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9e54f212114..f48623b4edc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4568,6 +4568,11 @@ private:
// of a ComparisonCategoryType enumerator.
llvm::SmallBitVector FullyCheckedComparisonCategories;
+ ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase);
+
public:
/// Lookup the specified comparison category types in the standard
/// library, an check the VarDecls possibly returned by the operator<=>
@@ -10254,6 +10259,12 @@ public:
SourceLocation Loc,
ArrayRef<Expr *> Args,
SourceLocation OpenParLoc);
+ QualType ProduceCtorInitMemberSignatureHelp(Scope *S, Decl *ConstructorDecl,
+ CXXScopeSpec SS,
+ ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs,
+ IdentifierInfo *II,
+ SourceLocation OpenParLoc);
void CodeCompleteInitializer(Scope *S, Decl *D);
void CodeCompleteReturn(Scope *S);
void CodeCompleteAfterIf(Scope *S);
@@ -10794,7 +10805,6 @@ struct LateParsedTemplate {
/// The template function declaration to be late parsed.
Decl *D;
};
-
} // end namespace clang
namespace llvm {
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 17dd2461227..a86f7ed8642 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3449,6 +3449,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+ // FIXME: Add support for signature help inside initializer lists.
ExprResult InitList = ParseBraceInitializer();
if (InitList.isInvalid())
return true;
@@ -3466,7 +3467,20 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// Parse the optional expression-list.
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
- if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
+ if (Tok.isNot(tok::r_paren) &&
+ ParseExpressionList(ArgExprs, CommaLocs, [&] {
+ QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index addddd8a849..4af36db2e56 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4586,6 +4586,25 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
}
+QualType Sema::ProduceCtorInitMemberSignatureHelp(
+ Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
+ ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
+ if (!CodeCompleter)
+ return QualType();
+
+ CXXConstructorDecl *Constructor =
+ dyn_cast<CXXConstructorDecl>(ConstructorDecl);
+ if (!Constructor)
+ return QualType();
+ // FIXME: Add support for Base class constructors as well.
+ if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
+ Constructor->getParent(), SS, TemplateTypeTy, II))
+ return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
+ MemberDecl->getLocation(), ArgExprs,
+ OpenParLoc);
+ return QualType();
+}
+
void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
if (!VD) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index dbca30aa43b..37a5b7b7f6d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -3777,6 +3777,22 @@ private:
}
+ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+ CXXScopeSpec &SS,
+ ParsedType TemplateTypeTy,
+ IdentifierInfo *MemberOrBase) {
+ if (SS.getScopeRep() || TemplateTypeTy)
+ return nullptr;
+ DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
+ if (Result.empty())
+ return nullptr;
+ ValueDecl *Member;
+ if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
+ (Member = dyn_cast<IndirectFieldDecl>(Result.front())))
+ return Member;
+ return nullptr;
+}
+
/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
@@ -3820,21 +3836,16 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
// of a single identifier refers to the class member. A
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
- if (!SS.getScopeRep() && !TemplateTypeTy) {
- // Look for a member, first.
- DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
- if (!Result.empty()) {
- ValueDecl *Member;
- if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
- (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) {
- if (EllipsisLoc.isValid())
- Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
- << MemberOrBase
- << SourceRange(IdLoc, Init->getSourceRange().getEnd());
-
- return BuildMemberInitializer(Member, Init, IdLoc);
- }
- }
+
+ // Look for a member, first.
+ if (ValueDecl *Member = tryLookupCtorInitMemberDecl(
+ ClassDecl, SS, TemplateTypeTy, MemberOrBase)) {
+ if (EllipsisLoc.isValid())
+ Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
+ << MemberOrBase
+ << SourceRange(IdLoc, Init->getSourceRange().getEnd());
+
+ return BuildMemberInitializer(Member, Init, IdLoc);
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
diff --git a/clang/test/CodeCompletion/ctor-initializer.cpp b/clang/test/CodeCompletion/ctor-initializer.cpp
index e1a0d143687..2eff48a4a0c 100644
--- a/clang/test/CodeCompletion/ctor-initializer.cpp
+++ b/clang/test/CodeCompletion/ctor-initializer.cpp
@@ -64,3 +64,27 @@ struct B {
// CHECK-CC8: COMPLETION: Pattern : member2(<#args#>
int member1, member2;
};
+
+struct Base2 {
+ Base2(int);
+};
+
+struct Composition1 {
+ Composition1() : b2_elem() {}
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:73:28 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // CHECK-CC9: OVERLOAD: Base2(<#int#>)
+ // CHECK-CC9: OVERLOAD: Base2(<#const Base2 &#>)
+ // CHECK-CC9-NOT: OVERLOAD: Composition1
+ Composition1(Base2);
+ Base2 b2_elem;
+};
+
+struct Composition2 {
+ Composition2() : c1_elem(Base2(1)) {}
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:84:34 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:84:34 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++98 -code-completion-at=%s:84:35 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ // RUN: %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:84:35 %s -o - | FileCheck -check-prefix=CHECK-CC9 %s
+ Composition1 c1_elem;
+};
OpenPOWER on IntegriCloud