diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 12 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 19 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 41 | ||||
| -rw-r--r-- | clang/test/CodeCompletion/ctor-initializer.cpp | 24 |
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; +}; |

