diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp | 440 |
1 files changed, 287 insertions, 153 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index 48bdd2a..18d352b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -495,7 +495,6 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, AsNestedNameSpecifier = false; ND = ND->getUnderlyingDecl(); - unsigned IDNS = ND->getIdentifierNamespace(); // Skip unnamed entities. if (!ND->getDeclName()) @@ -503,7 +502,7 @@ bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, // Friend declarations and declarations introduced due to friends are never // added as results. - if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)) + if (ND->getFriendObjectKind() == Decl::FOK_Undeclared) return false; // Class template (partial) specializations are never added as results. @@ -800,8 +799,8 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(RecordTy)); - DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName); - for (DeclContext::lookup_const_iterator I = Ctors.begin(), + DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); + for (DeclContext::lookup_iterator I = Ctors.begin(), E = Ctors.end(); I != E; ++I) { R.Declaration = *I; @@ -2018,7 +2017,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, if (SemaRef.getLangOpts().C11) { // _Alignof Builder.AddResultTypeChunk("size_t"); - if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition()) + if (SemaRef.PP.isMacroDefined("alignof")) Builder.AddTypedTextChunk("alignof"); else Builder.AddTypedTextChunk("_Alignof"); @@ -2086,15 +2085,14 @@ static void AddResultTypeChunk(ASTContext &Context, Result.getAllocator())); } -static void MaybeAddSentinel(ASTContext &Context, +static void MaybeAddSentinel(Preprocessor &PP, const NamedDecl *FunctionOrMethod, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { - if (Context.getLangOpts().ObjC1 && - Context.Idents.get("nil").hasMacroDefinition()) + if (PP.getLangOpts().ObjC1 && PP.isMacroDefined("nil")) Result.AddTextChunk(", nil"); - else if (Context.Idents.get("NULL").hasMacroDefinition()) + else if (PP.isMacroDefined("NULL")) Result.AddTextChunk(", NULL"); else Result.AddTextChunk(", (void*)0"); @@ -2118,8 +2116,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) { return Result; } -static std::string FormatFunctionParameter(ASTContext &Context, - const PrintingPolicy &Policy, +static std::string FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, bool SuppressName = false, bool SuppressBlock = false) { @@ -2218,7 +2215,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) { if (I) Params += ", "; - Params += FormatFunctionParameter(Context, Policy, Block.getParam(I), + Params += FormatFunctionParameter(Policy, Block.getParam(I), /*SuppressName=*/false, /*SuppressBlock=*/true); @@ -2248,7 +2245,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, } /// \brief Add function parameter chunks to the given code completion string. -static void AddFunctionParameterChunks(ASTContext &Context, +static void AddFunctionParameterChunks(Preprocessor &PP, const PrintingPolicy &Policy, const FunctionDecl *Function, CodeCompletionBuilder &Result, @@ -2266,7 +2263,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, Result.getCodeCompletionTUInfo()); if (!FirstParameter) Opt.AddChunk(CodeCompletionString::CK_Comma); - AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true); + AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true); Result.AddOptionalChunk(Opt.TakeString()); break; } @@ -2279,9 +2276,8 @@ static void AddFunctionParameterChunks(ASTContext &Context, InOptional = false; // Format the placeholder string. - std::string PlaceholderStr = FormatFunctionParameter(Context, Policy, - Param); - + std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); + if (Function->isVariadic() && P == N - 1) PlaceholderStr += ", ..."; @@ -2296,7 +2292,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, if (Proto->getNumParams() == 0) Result.AddPlaceholderChunk("..."); - MaybeAddSentinel(Context, Function, Result); + MaybeAddSentinel(PP, Function, Result); } } @@ -2309,7 +2305,11 @@ static void AddTemplateParameterChunks(ASTContext &Context, unsigned Start = 0, bool InDefaultArg = false) { bool FirstParameter = true; - + + // Prefer to take the template parameter names from the first declaration of + // the template. + Template = cast<TemplateDecl>(Template->getCanonicalDecl()); + TemplateParameterList *Params = Template->getTemplateParameters(); TemplateParameterList::iterator PEnd = Params->end(); if (MaxParameters) @@ -2572,11 +2572,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } if (Kind == RK_Macro) { - const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); - assert(MD && "Not a macro?"); - const MacroInfo *MI = MD->getMacroInfo(); - assert((!MD->isDefined() || MI) && "missing MacroInfo for define"); - + const MacroInfo *MI = PP.getMacroInfo(Macro); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Macro->getName())); @@ -2651,7 +2647,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); Result.AddChunk(CodeCompletionString::CK_LeftParen); - AddFunctionParameterChunks(Ctx, Policy, Function, Result); + AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); @@ -2705,7 +2701,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, // Add the function parameters Result.AddChunk(CodeCompletionString::CK_LeftParen); - AddFunctionParameterChunks(Ctx, Policy, Function, Result); + AddFunctionParameterChunks(PP, Policy, Function, Result); Result.AddChunk(CodeCompletionString::CK_RightParen); AddFunctionTypeQualsToCompletionString(Result, Function); return Result.TakeString(); @@ -2766,7 +2762,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, std::string Arg; if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) - Arg = FormatFunctionParameter(Ctx, Policy, *P, true); + Arg = FormatFunctionParameter(Policy, *P, true); else { (*P)->getType().getAsStringInternal(Arg, Policy); Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) @@ -2797,7 +2793,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddPlaceholderChunk(", ..."); } - MaybeAddSentinel(Ctx, Method, Result); + MaybeAddSentinel(PP, Method, Result); } return Result.TakeString(); @@ -2812,73 +2808,115 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } +/// \brief Add function overload parameter chunks to the given code completion +/// string. +static void AddOverloadParameterChunks(ASTContext &Context, + const PrintingPolicy &Policy, + const FunctionDecl *Function, + const FunctionProtoType *Prototype, + CodeCompletionBuilder &Result, + unsigned CurrentArg, + unsigned Start = 0, + bool InOptional = false) { + bool FirstParameter = true; + unsigned NumParams = Function ? Function->getNumParams() + : Prototype->getNumParams(); + + for (unsigned P = Start; P != NumParams; ++P) { + if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + // Optional sections are nested. + AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt, + CurrentArg, P, /*InOptional=*/true); + Result.AddOptionalChunk(Opt.TakeString()); + return; + } + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(CodeCompletionString::CK_Comma); + + InOptional = false; + + // Format the placeholder string. + std::string Placeholder; + if (Function) + Placeholder = FormatFunctionParameter(Policy, Function->getParamDecl(P)); + else + Placeholder = Prototype->getParamType(P).getAsString(Policy); + + if (P == CurrentArg) + Result.AddCurrentParameterChunk( + Result.getAllocator().CopyString(Placeholder)); + else + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); + } + + if (Prototype && Prototype->isVariadic()) { + CodeCompletionBuilder Opt(Result.getAllocator(), + Result.getCodeCompletionTUInfo()); + if (!FirstParameter) + Opt.AddChunk(CodeCompletionString::CK_Comma); + + if (CurrentArg < NumParams) + Opt.AddPlaceholderChunk("..."); + else + Opt.AddCurrentParameterChunk("..."); + + Result.AddOptionalChunk(Opt.TakeString()); + } +} + CodeCompletionString * CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( - unsigned CurrentArg, - Sema &S, - CodeCompletionAllocator &Allocator, - CodeCompletionTUInfo &CCTUInfo) const { + unsigned CurrentArg, Sema &S, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo, + bool IncludeBriefComments) const { PrintingPolicy Policy = getCompletionPrintingPolicy(S); // FIXME: Set priority, availability appropriately. CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); FunctionDecl *FDecl = getFunction(); - AddResultTypeChunk(S.Context, Policy, FDecl, Result); - const FunctionProtoType *Proto + const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(getFunctionType()); if (!FDecl && !Proto) { // Function without a prototype. Just give the return type and a // highlighted ellipsis. const FunctionType *FT = getFunctionType(); - Result.AddTextChunk(GetCompletionTypeString(FT->getReturnType(), S.Context, - Policy, Result.getAllocator())); + Result.AddResultTypeChunk(Result.getAllocator().CopyString( + FT->getReturnType().getAsString(Policy))); Result.AddChunk(CodeCompletionString::CK_LeftParen); Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); Result.AddChunk(CodeCompletionString::CK_RightParen); return Result.TakeString(); } - - if (FDecl) + + if (FDecl) { + if (IncludeBriefComments && CurrentArg < FDecl->getNumParams()) + if (auto RC = S.getASTContext().getRawCommentForAnyRedecl( + FDecl->getParamDecl(CurrentArg))) + Result.addBriefComment(RC->getBriefText(S.getASTContext())); + AddResultTypeChunk(S.Context, Policy, FDecl, Result); Result.AddTextChunk( - Result.getAllocator().CopyString(FDecl->getNameAsString())); - else - Result.AddTextChunk(Result.getAllocator().CopyString( + Result.getAllocator().CopyString(FDecl->getNameAsString())); + } else { + Result.AddResultTypeChunk( + Result.getAllocator().CopyString( Proto->getReturnType().getAsString(Policy))); + } Result.AddChunk(CodeCompletionString::CK_LeftParen); - unsigned NumParams = FDecl ? FDecl->getNumParams() : Proto->getNumParams(); - for (unsigned I = 0; I != NumParams; ++I) { - if (I) - Result.AddChunk(CodeCompletionString::CK_Comma); - - std::string ArgString; - QualType ArgType; - - if (FDecl) { - ArgString = FDecl->getParamDecl(I)->getNameAsString(); - ArgType = FDecl->getParamDecl(I)->getOriginalType(); - } else { - ArgType = Proto->getParamType(I); - } - - ArgType.getAsStringInternal(ArgString, Policy); - - if (I == CurrentArg) - Result.AddChunk(CodeCompletionString::CK_CurrentParameter, - Result.getAllocator().CopyString(ArgString)); - else - Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); - } - - if (Proto && Proto->isVariadic()) { - Result.AddChunk(CodeCompletionString::CK_Comma); - if (CurrentArg < NumParams) - Result.AddTextChunk("..."); - else - Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); - } + AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result, + CurrentArg); Result.AddChunk(CodeCompletionString::CK_RightParen); - + return Result.TakeString(); } @@ -2990,8 +3028,9 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { - if (IncludeUndefined || M->first->hasMacroDefinition()) { - if (MacroInfo *MI = M->second->getMacroInfo()) + auto MD = PP.getMacroDefinition(M->first); + if (IncludeUndefined || MD) { + if (MacroInfo *MI = MD.getMacroInfo()) if (MI->isUsedForHeaderGuard()) continue; @@ -3816,7 +3855,74 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) { return false; } -void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { +typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; + +static void mergeCandidatesWithResults(Sema &SemaRef, + SmallVectorImpl<ResultCandidate> &Results, + OverloadCandidateSet &CandidateSet, + SourceLocation Loc) { + if (!CandidateSet.empty()) { + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort( + CandidateSet.begin(), CandidateSet.end(), + [&](const OverloadCandidate &X, const OverloadCandidate &Y) { + return isBetterOverloadCandidate(SemaRef, X, Y, Loc); + }); + + // Add the remaining viable overload candidates as code-completion results. + for (auto &Candidate : CandidateSet) + if (Candidate.Viable) + Results.push_back(ResultCandidate(Candidate.Function)); + } +} + +/// \brief Get the type of the Nth parameter from a given set of overload +/// candidates. +static QualType getParamType(Sema &SemaRef, + ArrayRef<ResultCandidate> Candidates, + unsigned N) { + + // Given the overloads 'Candidates' for a function call matching all arguments + // up to N, return the type of the Nth parameter if it is the same for all + // overload candidates. + QualType ParamType; + for (auto &Candidate : Candidates) { + if (auto FType = Candidate.getFunctionType()) + if (auto Proto = dyn_cast<FunctionProtoType>(FType)) + if (N < Proto->getNumParams()) { + if (ParamType.isNull()) + ParamType = Proto->getParamType(N); + else if (!SemaRef.Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getParamType(N).getNonReferenceType())) + // Otherwise return a default-constructed QualType. + return QualType(); + } + } + + return ParamType; +} + +static void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, + MutableArrayRef<ResultCandidate> Candidates, + unsigned CurrentArg, + bool CompleteExpressionWithCurrentArg = true) { + QualType ParamType; + if (CompleteExpressionWithCurrentArg) + ParamType = getParamType(SemaRef, Candidates, CurrentArg); + + if (ParamType.isNull()) + SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); + else + SemaRef.CodeCompleteExpression(S, ParamType); + + if (!Candidates.empty()) + SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg, + Candidates.data(), + Candidates.size()); +} + +void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { if (!CodeCompleter) return; @@ -3825,7 +3931,7 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { // results. We may want to revisit this strategy in the future, // e.g., by merging the two kinds of results. - Expr *Fn = (Expr *)FnIn; + // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || @@ -3838,92 +3944,120 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { SourceLocation Loc = Fn->getExprLoc(); OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - // FIXME: What if we're calling something that isn't a function declaration? - // FIXME: What if we're calling a pseudo-destructor? - // FIXME: What if we're calling a member function? - - typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; SmallVector<ResultCandidate, 8> Results; Expr *NakedFn = Fn->IgnoreParenCasts(); - if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) + if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) AddOverloadedCallCandidates(ULE, Args, CandidateSet, - /*PartialOverloading=*/ true); - else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { - FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); - if (FDecl) { - if (!getLangOpts().CPlusPlus || - !FDecl->getType()->getAs<FunctionProtoType>()) - Results.push_back(ResultCandidate(FDecl)); + /*PartialOverloading=*/true); + else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; + if (UME->hasExplicitTemplateArgs()) { + UME->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + SmallVector<Expr *, 12> ArgExprs(1, UME->getBase()); + ArgExprs.append(Args.begin(), Args.end()); + UnresolvedSet<8> Decls; + Decls.append(UME->decls_begin(), UME->decls_end()); + AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else { + FunctionDecl *FD = nullptr; + if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); + else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FD) { // We check whether it's a resolved function declaration. + if (!getLangOpts().CPlusPlus || + !FD->getType()->getAs<FunctionProtoType>()) + Results.push_back(ResultCandidate(FD)); else - // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, - CandidateSet, false, /*PartialOverloading*/true); + AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + + } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { + // If expression's type is CXXRecordDecl, it may overload the function + // call operator, so we check if it does and add them as candidates. + // A complete type is needed to lookup for member function call operators. + if (!RequireCompleteType(Loc, NakedFn->getType(), 0)) { + DeclarationName OpName = Context.DeclarationNames + .getCXXOperatorName(OO_Call); + LookupResult R(*this, OpName, Loc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + R.suppressDiagnostics(); + SmallVector<Expr *, 12> ArgExprs(1, NakedFn); + ArgExprs.append(Args.begin(), Args.end()); + AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } + } else { + // Lastly we check whether expression's type is function pointer or + // function. + QualType T = NakedFn->getType(); + if (!T->getPointeeType().isNull()) + T = T->getPointeeType(); + + if (auto FP = T->getAs<FunctionProtoType>()) { + if (!TooManyArguments(FP->getNumParams(), Args.size(), + /*PartialOverloading=*/true) || + FP->isVariadic()) + Results.push_back(ResultCandidate(FP)); + } else if (auto FT = T->getAs<FunctionType>()) + // No prototype and declaration, it may be a K & R style function. + Results.push_back(ResultCandidate(FT)); } } - - QualType ParamType; - - if (!CandidateSet.empty()) { - // Sort the overload candidate set by placing the best overloads first. - std::stable_sort( - CandidateSet.begin(), CandidateSet.end(), - [&](const OverloadCandidate &X, const OverloadCandidate &Y) { - return isBetterOverloadCandidate(*this, X, Y, Loc); - }); - // Add the remaining viable overload candidates as code-completion reslults. - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), - CandEnd = CandidateSet.end(); - Cand != CandEnd; ++Cand) { - if (Cand->Viable) - Results.push_back(ResultCandidate(Cand->Function)); - } - - // From the viable candidates, try to determine the type of this parameter. - for (unsigned I = 0, N = Results.size(); I != N; ++I) { - if (const FunctionType *FType = Results[I].getFunctionType()) - if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) - if (Args.size() < Proto->getNumParams()) { - if (ParamType.isNull()) - ParamType = Proto->getParamType(Args.size()); - else if (!Context.hasSameUnqualifiedType( - ParamType.getNonReferenceType(), - Proto->getParamType(Args.size()) - .getNonReferenceType())) { - ParamType = QualType(); - break; - } - } - } - } else { - // Try to determine the parameter type from the type of the expression - // being called. - QualType FunctionType = Fn->getType(); - if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) - FunctionType = Ptr->getPointeeType(); - else if (const BlockPointerType *BlockPtr - = FunctionType->getAs<BlockPointerType>()) - FunctionType = BlockPtr->getPointeeType(); - else if (const MemberPointerType *MemPtr - = FunctionType->getAs<MemberPointerType>()) - FunctionType = MemPtr->getPointeeType(); - - if (const FunctionProtoType *Proto - = FunctionType->getAs<FunctionProtoType>()) { - if (Args.size() < Proto->getNumParams()) - ParamType = Proto->getParamType(Args.size()); + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size(), + !CandidateSet.empty()); +} + +void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, + ArrayRef<Expr *> Args) { + if (!CodeCompleter) + return; + + // A complete type is needed to lookup for constructors. + if (RequireCompleteType(Loc, Type, 0)) + return; + + CXXRecordDecl *RD = Type->getAsCXXRecordDecl(); + if (!RD) { + CodeCompleteExpression(S, Type); + return; + } + + // FIXME: Provide support for member initializers. + // FIXME: Provide support for variadic template constructors. + + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); + + for (auto C : LookupConstructors(RD)) { + if (auto FD = dyn_cast<FunctionDecl>(C)) { + AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) { + AddTemplateOverloadCandidate(FTD, + DeclAccessPair::make(FTD, C->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } - if (ParamType.isNull()) - CodeCompleteOrdinaryName(S, PCC_Expression); - else - CodeCompleteExpression(S, ParamType); - - if (!Results.empty()) - CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), - Results.size()); + SmallVector<ResultCandidate, 8> Results; + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size()); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { @@ -4981,7 +5115,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, // an action, e.g., // IBAction)<#selector#>:(id)sender if (DS.getObjCDeclQualifier() == 0 && !IsParameter && - Context.Idents.get("IBAction").hasMacroDefinition()) { + PP.isMacroDefined("IBAction")) { CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo(), CCP_CodePattern, CXAvailability_Available); |