diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:47:56 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:47:56 +0000 | 
| commit | 5e20cdd81c44a443562a09007668ffdf76c455af (patch) | |
| tree | dbbd4047878da71c1a706e26ce05b4e7791b14cc /lib/Sema/SemaCodeComplete.cpp | |
| parent | d5f23b0b7528b5c3caed1ba14f897cc4aaa9e3c3 (diff) | |
Notes
Diffstat (limited to 'lib/Sema/SemaCodeComplete.cpp')
| -rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 440 | 
1 files changed, 287 insertions, 153 deletions
| diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 48bdd2a7d82c..18d352ba829b 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/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); | 
