// 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<=>
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);
/// The template function declaration to be late parsed.
Decl *D;
};
-
} // end namespace clang
namespace llvm {
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;
// 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;
}
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) {
}
+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,
// 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;
// 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;
+};