diff options
-rw-r--r-- | include/clang/Parse/Action.h | 12 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 6 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 31 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 72 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 163 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 191 | ||||
-rw-r--r-- | test/CodeCompletion/call.cpp | 22 |
8 files changed, 379 insertions, 139 deletions
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 06213ddf47..df85dfe8eb 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -2239,6 +2239,18 @@ public: /// \brief S the scope in which the case statement occurs. virtual void CodeCompleteCase(Scope *S) { } + /// \brief Code completion for a call. + /// + /// \brief S the scope in which the call occurs. + /// + /// \param Fn the expression describing the function being called. + /// + /// \param Args the arguments to the function call (so far). + /// + /// \param NumArgs the number of arguments in \p Args. + virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, + ExprTy **Args, unsigned NumArgs) { } + /// \brief Code completion for a C++ nested-name-specifier that precedes a /// qualified-id of some form. /// diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e1a6e7ad39..b9b17d24d1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -745,7 +745,11 @@ private: typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy; /// ParseExpressionList - Used for C/C++ (argument-)expression-list. - bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs); + bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs, + void (Action::*Completer)(Scope *S, void *Data, + ExprTy **Args, + unsigned NumArgs) = 0, + void *Data = 0); /// ParenParseOption - Control what ParseParenExpression will parse. enum ParenParseOption { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 156c84804f..d10e38cf68 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -899,8 +899,14 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) { Loc = ConsumeParen(); + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0); + ConsumeToken(); + } + if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs)) { + if (ParseExpressionList(ArgExprs, CommaLocs, &Action::CodeCompleteCall, + LHS.get())) { SkipUntil(tok::r_paren); return ExprError(); } @@ -1508,8 +1514,19 @@ Parser::OwningExprResult Parser::ParseStringLiteralExpression() { /// [C++] assignment-expression /// [C++] expression-list , assignment-expression /// -bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs) { +bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs, + void (Action::*Completer)(Scope *S, + void *Data, + ExprTy **Args, + unsigned NumArgs), + void *Data) { while (1) { + if (Tok.is(tok::code_completion)) { + if (Completer) + (Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size()); + ConsumeToken(); + } + OwningExprResult Expr(ParseAssignmentExpression()); if (Expr.isInvalid()) return true; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7fa546258e..4d8fd8d095 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -835,7 +835,8 @@ public: Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, - bool ForceRValue = false); + bool ForceRValue = false, + bool PartialOverloading = false); void AddFunctionCandidates(const FunctionSet &Functions, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -891,7 +892,11 @@ public: OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, - OverloadCandidateSet& CandidateSet); + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + OverloadCandidateSet& CandidateSet, + bool PartialOverloading = false); bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, const OverloadCandidate& Cand2); OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, @@ -904,6 +909,16 @@ public: bool Complain); void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); + void AddOverloadedCallCandidates(NamedDecl *Callee, + DeclarationName &UnqualifiedName, + bool &ArgumentDependentLookup, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading = false); + FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, DeclarationName UnqualifiedName, bool HasExplicitTemplateArgs, @@ -1670,6 +1685,16 @@ public: unsigned NumInitializers ); + void DeconstructCallFunction(Expr *FnExpr, + NamedDecl *&Function, + DeclarationName &Name, + NestedNameSpecifier *&Qualifier, + SourceRange &QualifierRange, + bool &ArgumentDependentLookup, + bool &HasExplicitTemplateArguments, + const TemplateArgument *&ExplicitTemplateArgs, + unsigned &NumExplicitTemplateArgs); + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -3635,6 +3660,8 @@ public: bool IsArrow); virtual void CodeCompleteTag(Scope *S, unsigned TagSpec); virtual void CodeCompleteCase(Scope *S); + virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, + ExprTy **Args, unsigned NumArgs); virtual void CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS, bool EnteringContext); virtual void CodeCompleteUsing(Scope *S); diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 52e7d0e005..757bb62711 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1070,6 +1070,78 @@ void Sema::CodeCompleteCase(Scope *S) { HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } +namespace { + struct IsBetterOverloadCandidate { + Sema &S; + + public: + explicit IsBetterOverloadCandidate(Sema &S) : S(S) { } + + bool + operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { + return S.isBetterOverloadCandidate(X, Y); + } + }; +} + +void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, + ExprTy **ArgsIn, unsigned NumArgs) { + if (!CodeCompleter) + return; + + Expr *Fn = (Expr *)FnIn; + Expr **Args = (Expr **)ArgsIn; + + // Ignore type-dependent call expressions entirely. + if (Fn->isTypeDependent() || + Expr::hasAnyTypeDependentArguments(Args, NumArgs)) + return; + + NamedDecl *Function; + DeclarationName UnqualifiedName; + NestedNameSpecifier *Qualifier; + SourceRange QualifierRange; + bool ArgumentDependentLookup; + bool HasExplicitTemplateArgs; + const TemplateArgument *ExplicitTemplateArgs; + unsigned NumExplicitTemplateArgs; + + DeconstructCallFunction(Fn, + Function, UnqualifiedName, Qualifier, QualifierRange, + ArgumentDependentLookup, HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs); + + + // 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? + + // Build an overload candidate set based on the functions we find. + OverloadCandidateSet CandidateSet; + AddOverloadedCallCandidates(Function, UnqualifiedName, + ArgumentDependentLookup, HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs, + Args, NumArgs, + CandidateSet, + /*PartialOverloading=*/true); + + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort(CandidateSet.begin(), CandidateSet.end(), + IsBetterOverloadCandidate(*this)); + + // Add the remaining viable overload candidates as code-completion reslults. + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) { + if (Cand->Viable) + Results.MaybeAddResult(Result(Cand->Function, 0), 0); + } + + HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); +} + void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS, bool EnteringContext) { if (!SS.getScopeRep() || !CodeCompleter) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 333cd35f89..3eed4fcde3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2734,6 +2734,96 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, return Invalid; } +/// \brief "Deconstruct" the function argument of a call expression to find +/// the underlying declaration (if any), the name of the called function, +/// whether argument-dependent lookup is available, whether it has explicit +/// template arguments, etc. +void Sema::DeconstructCallFunction(Expr *FnExpr, + NamedDecl *&Function, + DeclarationName &Name, + NestedNameSpecifier *&Qualifier, + SourceRange &QualifierRange, + bool &ArgumentDependentLookup, + bool &HasExplicitTemplateArguments, + const TemplateArgument *&ExplicitTemplateArgs, + unsigned &NumExplicitTemplateArgs) { + // Set defaults for all of the output parameters. + Function = 0; + Name = DeclarationName(); + Qualifier = 0; + QualifierRange = SourceRange(); + ArgumentDependentLookup = getLangOptions().CPlusPlus; + HasExplicitTemplateArguments = false; + + // If we're directly calling a function, get the appropriate declaration. + // Also, in C++, keep track of whether we should perform argument-dependent + // lookup and whether there were any explicitly-specified template arguments. + while (true) { + if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) + FnExpr = IcExpr->getSubExpr(); + else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { + // Parentheses around a function disable ADL + // (C++0x [basic.lookup.argdep]p1). + ArgumentDependentLookup = false; + FnExpr = PExpr->getSubExpr(); + } else if (isa<UnaryOperator>(FnExpr) && + cast<UnaryOperator>(FnExpr)->getOpcode() + == UnaryOperator::AddrOf) { + FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); + } else if (QualifiedDeclRefExpr *QDRExpr + = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) { + // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). + ArgumentDependentLookup = false; + Qualifier = QDRExpr->getQualifier(); + QualifierRange = QDRExpr->getQualifierRange(); + Function = dyn_cast<NamedDecl>(QDRExpr->getDecl()); + break; + } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { + Function = dyn_cast<NamedDecl>(DRExpr->getDecl()); + break; + } else if (UnresolvedFunctionNameExpr *DepName + = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { + Name = DepName->getName(); + break; + } else if (TemplateIdRefExpr *TemplateIdRef + = dyn_cast<TemplateIdRefExpr>(FnExpr)) { + Function = TemplateIdRef->getTemplateName().getAsTemplateDecl(); + if (!Function) + Function = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); + HasExplicitTemplateArguments = true; + ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); + NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); + + // C++ [temp.arg.explicit]p6: + // [Note: For simple function names, argument dependent lookup (3.4.2) + // applies even when the function name is not visible within the + // scope of the call. This is because the call still has the syntactic + // form of a function call (3.4.1). But when a function template with + // explicit template arguments is used, the call does not have the + // correct syntactic form unless there is a function template with + // that name visible at the point of the call. If no such name is + // visible, the call is not syntactically well-formed and + // argument-dependent lookup does not apply. If some such name is + // visible, argument dependent lookup applies and additional function + // templates may be found in other namespaces. + // + // The summary of this paragraph is that, if we get to this point and the + // template-id was not a qualified name, then argument-dependent lookup + // is still possible. + if ((Qualifier = TemplateIdRef->getQualifier())) { + ArgumentDependentLookup = false; + QualifierRange = TemplateIdRef->getQualifierRange(); + } + break; + } else { + // Any kind of name that does not refer to a declaration (or + // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). + ArgumentDependentLookup = false; + break; + } + } +} + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. /// This provides the location of the left/right parens and a list of comma /// locations. @@ -2808,67 +2898,15 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // If we're directly calling a function, get the appropriate declaration. // Also, in C++, keep track of whether we should perform argument-dependent // lookup and whether there were any explicitly-specified template arguments. - Expr *FnExpr = Fn; bool ADL = true; bool HasExplicitTemplateArgs = 0; const TemplateArgument *ExplicitTemplateArgs = 0; unsigned NumExplicitTemplateArgs = 0; - while (true) { - if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) - FnExpr = IcExpr->getSubExpr(); - else if (ParenExpr *PExpr = dyn_cast<ParenExpr>(FnExpr)) { - // Parentheses around a function disable ADL - // (C++0x [basic.lookup.argdep]p1). - ADL = false; - FnExpr = PExpr->getSubExpr(); - } else if (isa<UnaryOperator>(FnExpr) && - cast<UnaryOperator>(FnExpr)->getOpcode() - == UnaryOperator::AddrOf) { - FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { - // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). - ADL &= !isa<QualifiedDeclRefExpr>(DRExpr); - NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl()); - break; - } else if (UnresolvedFunctionNameExpr *DepName - = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { - UnqualifiedName = DepName->getName(); - break; - } else if (TemplateIdRefExpr *TemplateIdRef - = dyn_cast<TemplateIdRefExpr>(FnExpr)) { - NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl(); - if (!NDecl) - NDecl = TemplateIdRef->getTemplateName().getAsOverloadedFunctionDecl(); - HasExplicitTemplateArgs = true; - ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); - NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); - - // C++ [temp.arg.explicit]p6: - // [Note: For simple function names, argument dependent lookup (3.4.2) - // applies even when the function name is not visible within the - // scope of the call. This is because the call still has the syntactic - // form of a function call (3.4.1). But when a function template with - // explicit template arguments is used, the call does not have the - // correct syntactic form unless there is a function template with - // that name visible at the point of the call. If no such name is - // visible, the call is not syntactically well-formed and - // argument-dependent lookup does not apply. If some such name is - // visible, argument dependent lookup applies and additional function - // templates may be found in other namespaces. - // - // The summary of this paragraph is that, if we get to this point and the - // template-id was not a qualified name, then argument-dependent lookup - // is still possible. - if (TemplateIdRef->getQualifier()) - ADL = false; - break; - } else { - // Any kind of name that does not refer to a declaration (or - // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). - ADL = false; - break; - } - } + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + DeconstructCallFunction(Fn, NDecl, UnqualifiedName, Qualifier, QualifierRange, + ADL,HasExplicitTemplateArgs, ExplicitTemplateArgs, + NumExplicitTemplateArgs); OverloadedFunctionDecl *Ovl = 0; FunctionTemplateDecl *FunctionTemplate = 0; @@ -2903,16 +2941,15 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Update Fn to refer to the actual function selected. Expr *NewFn = 0; - if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) + if (Qualifier) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), - QDRExpr->getLocation(), + Fn->getLocStart(), false, false, - QDRExpr->getQualifierRange(), - QDRExpr->getQualifier()); + QualifierRange, + Qualifier); else NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(), - Fn->getSourceRange().getBegin()); + Fn->getLocStart()); Fn->Destroy(Context); Fn = NewFn; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2ff0c0544a..063b387fba 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2122,12 +2122,17 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { /// If @p ForceRValue, treat all arguments as rvalues. This is a slightly /// hacky way to implement the overloading rules for elidable copy /// initialization in C++0x (C++0x 12.8p15). +/// +/// \para PartialOverloading true if we are performing "partial" overloading +/// based on an incomplete set of function arguments. This feature is used by +/// code completion. void Sema::AddOverloadCandidate(FunctionDecl *Function, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, - bool ForceRValue) { + bool ForceRValue, + bool PartialOverloading) { const FunctionProtoType* Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -2177,7 +2182,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // parameter list is truncated on the right, so that there are // exactly m parameters. unsigned MinRequiredArgs = Function->getMinRequiredArguments(); - if (NumArgs < MinRequiredArgs) { + if (NumArgs < MinRequiredArgs && !PartialOverloading) { // Not enough arguments. Candidate.Viable = false; return; @@ -3615,9 +3620,15 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, - OverloadCandidateSet& CandidateSet) { + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + OverloadCandidateSet& CandidateSet, + bool PartialOverloading) { FunctionSet Functions; + // FIXME: Should we be trafficking in canonical function decls throughout? + // Record all of the function candidates that we've already // added to the overload set, so that we don't add those same // candidates a second time. @@ -3630,6 +3641,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, Functions.insert(FunTmpl); } + // FIXME: Pass in the explicit template arguments? ArgumentDependentLookup(Name, Args, NumArgs, Functions); // Erase all of the candidates we already knew about. @@ -3648,11 +3660,17 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); Func != FuncEnd; ++Func) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) - AddOverloadCandidate(FD, Args, NumArgs, CandidateSet); - else + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) { + if (HasExplicitTemplateArgs) + continue; + + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + false, false, PartialOverloading); + } else AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), - /*FIXME: explicit args */false, 0, 0, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, Args, NumArgs, CandidateSet); } } @@ -4100,25 +4118,48 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; } -/// ResolveOverloadedCallFn - Given the call expression that calls Fn -/// (which eventually refers to the declaration Func) and the call -/// arguments Args/NumArgs, attempt to resolve the function call down -/// to a specific function. If overload resolution succeeds, returns -/// the function declaration produced by overload -/// resolution. Otherwise, emits diagnostics, deletes all of the -/// arguments and Fn, and returns NULL. -FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, - DeclarationName UnqualifiedName, - bool HasExplicitTemplateArgs, +/// \brief Add a single candidate to the overload set. +static void AddOverloadedCallCandidate(Sema &S, + AnyFunctionDecl Callee, + bool &ArgumentDependentLookup, + bool HasExplicitTemplateArgs, const TemplateArgument *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc, - bool &ArgumentDependentLookup) { - OverloadCandidateSet CandidateSet; - + unsigned NumExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading) { + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) { + assert(!HasExplicitTemplateArgs && "Explicit template arguments?"); + S.AddOverloadCandidate(Func, Args, NumArgs, CandidateSet, false, false, + PartialOverloading); + + if (Func->getDeclContext()->isRecord() || + Func->getDeclContext()->isFunctionOrMethod()) + ArgumentDependentLookup = false; + return; + } + + FunctionTemplateDecl *FuncTemplate = cast<FunctionTemplateDecl>(Callee); + S.AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + Args, NumArgs, CandidateSet); + + if (FuncTemplate->getDeclContext()->isRecord()) + ArgumentDependentLookup = false; +} + +/// \brief Add the overload candidates named by callee and/or found by argument +/// dependent lookup to the given overload set. +void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, + DeclarationName &UnqualifiedName, + bool &ArgumentDependentLookup, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading) { // Add the functions denoted by Callee to the set of candidate // functions. While we're doing so, track whether argument-dependent // lookup still applies, per: @@ -4131,63 +4172,72 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, // -- a declaration of a class member, or // // -- a block-scope function declaration that is not a - // using-declaration, or + // using-declaration (FIXME: check for using declaration), or // // -- a declaration that is neither a function or a function // template // // then Y is empty. - if (OverloadedFunctionDecl *Ovl - = dyn_cast_or_null<OverloadedFunctionDecl>(Callee)) { + if (!Callee) { + // Nothing to do. + } else if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(Callee)) { for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), FuncEnd = Ovl->function_end(); - Func != FuncEnd; ++Func) { - DeclContext *Ctx = 0; - if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) { - if (HasExplicitTemplateArgs) - continue; - - AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet); - Ctx = FunDecl->getDeclContext(); - } else { - FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func); - AddTemplateOverloadCandidate(FunTmpl, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - Args, NumArgs, CandidateSet); - Ctx = FunTmpl->getDeclContext(); - } - - - if (Ctx->isRecord() || Ctx->isFunctionOrMethod()) - ArgumentDependentLookup = false; - } - } else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) { - assert(!HasExplicitTemplateArgs && "Explicit template arguments?"); - AddOverloadCandidate(Func, Args, NumArgs, CandidateSet); - - if (Func->getDeclContext()->isRecord() || - Func->getDeclContext()->isFunctionOrMethod()) - ArgumentDependentLookup = false; - } else if (FunctionTemplateDecl *FuncTemplate - = dyn_cast_or_null<FunctionTemplateDecl>(Callee)) { - AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, - Args, NumArgs, CandidateSet); - - if (FuncTemplate->getDeclContext()->isRecord()) - ArgumentDependentLookup = false; - } - + Func != FuncEnd; ++Func) + AddOverloadedCallCandidate(*this, *Func, ArgumentDependentLookup, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs, + Args, NumArgs, CandidateSet, + PartialOverloading); + } else if (isa<FunctionDecl>(Callee) || isa<FunctionTemplateDecl>(Callee)) + AddOverloadedCallCandidate(*this, + AnyFunctionDecl::getFromNamedDecl(Callee), + ArgumentDependentLookup, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs, + Args, NumArgs, CandidateSet, + PartialOverloading); + // FIXME: assert isa<FunctionDecl> || isa<FunctionTemplateDecl> rather than + // checking dynamically. + if (Callee) UnqualifiedName = Callee->getDeclName(); - - // FIXME: Pass explicit template arguments through for ADL + if (ArgumentDependentLookup) AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, - CandidateSet); + HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + CandidateSet, + PartialOverloading); +} + +/// ResolveOverloadedCallFn - Given the call expression that calls Fn +/// (which eventually refers to the declaration Func) and the call +/// arguments Args/NumArgs, attempt to resolve the function call down +/// to a specific function. If overload resolution succeeds, returns +/// the function declaration produced by overload +/// resolution. Otherwise, emits diagnostics, deletes all of the +/// arguments and Fn, and returns NULL. +FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, + DeclarationName UnqualifiedName, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc, + bool &ArgumentDependentLookup) { + OverloadCandidateSet CandidateSet; + // Add the functions denoted by Callee to the set of candidate + // functions. + AddOverloadedCallCandidates(Callee, UnqualifiedName, ArgumentDependentLookup, + HasExplicitTemplateArgs, ExplicitTemplateArgs, + NumExplicitTemplateArgs, Args, NumArgs, + CandidateSet); OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { case OR_Success: @@ -4877,7 +4927,6 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // for a class object x of type T if T::operator->() exists and if // the operator is selected as the best match function by the // overload resolution mechanism (13.3). - // FIXME: look in base classes. DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow); OverloadCandidateSet CandidateSet; const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); diff --git a/test/CodeCompletion/call.cpp b/test/CodeCompletion/call.cpp new file mode 100644 index 0000000000..4faff15c05 --- /dev/null +++ b/test/CodeCompletion/call.cpp @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s && +// RUN: true +void f(float x, float y); +void f(int i, int j, int k); +struct X { }; +void f(X); +namespace N { + struct Y { + Y(int = 0); + + operator int() const; + }; + void f(Y y); +} +typedef N::Y Y; +void f(); + +void test() { + // CHECK-CC1: f : 0 : f(<#struct N::Y y#>) + // CHECK-NEXT-CC1: f : 0 : f(<#int i#>, <#int j#>, <#int k#>) + // CHECK-NEXT-CC1: f : 0 : f(<#float x#>, <#float y#>) + f(Y(), |