From: Nate Begeman Date: Thu, 31 Jan 2008 05:38:29 +0000 (+0000) Subject: Remainder of the __builtin_overload feedback X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=796ef3d4a32ce8d9e76df0d5bcab07db97883064;p=clang Remainder of the __builtin_overload feedback git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46601 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CodeGen/CGExprAgg.cpp b/CodeGen/CGExprAgg.cpp index d52e8b1a0e..377e90df70 100644 --- a/CodeGen/CGExprAgg.cpp +++ b/CodeGen/CGExprAgg.cpp @@ -76,6 +76,7 @@ public: void VisitStmtExpr(const StmtExpr *E); void VisitBinaryOperator(const BinaryOperator *BO); void VisitBinAssign(const BinaryOperator *E); + void VisitOverloadExpr(const OverloadExpr *E); void VisitConditionalOperator(const ConditionalOperator *CO); @@ -160,6 +161,20 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType()); } +void AggExprEmitter::VisitOverloadExpr(const OverloadExpr *E) +{ + RValue RV = CGF.EmitCallExpr(E->getFn(), E->arg_begin(), + E->getNumArgs(CGF.getContext())); + assert(RV.isAggregate() && "Return value must be aggregate value!"); + + // If the result is ignored, don't copy from the value. + if (DestPtr == 0) + // FIXME: If the source is volatile, we must read from it. + return; + + EmitAggregateCopy(DestPtr, RV.getAggregateAddr(), E->getType()); +} + void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest); } diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp index 00b2899a03..09f588aeec 100644 --- a/Parse/ParseExpr.cpp +++ b/Parse/ParseExpr.cpp @@ -938,12 +938,6 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren); return ExprResult(true); } - - // __builtin_overload requires at least 2 arguments - if (ArgExprs.size() < 2) { - Diag(Tok, diag::err_typecheck_call_too_few_args); - return ExprResult(true); - } Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(), &CommaLocs[0], StartLoc, ConsumeParen()); break; diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 86d6d772dd..6228b3cf76 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -2103,11 +2103,14 @@ Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { - assert((NumArgs > 1) && "Too few arguments for OverloadExpr!"); + // __builtin_overload requires at least 2 arguments + if (NumArgs < 2) + return Diag(RParenLoc, diag::err_typecheck_call_too_few_args, + SourceRange(BuiltinLoc, RParenLoc)); - Expr **Args = reinterpret_cast(args); // The first argument is required to be a constant expression. It tells us // the number of arguments to pass to each of the functions to be overloaded. + Expr **Args = reinterpret_cast(args); Expr *NParamsExpr = Args[0]; llvm::APSInt constEval(32); SourceLocation ExpLoc; @@ -2127,6 +2130,7 @@ Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs, // Figure out the return type, by matching the args to one of the functions // listed after the parameters. + OverloadExpr *OE = 0; for (unsigned i = NumParams + 1; i < NumArgs; ++i) { // UsualUnaryConversions will convert the function DeclRefExpr into a // pointer to function. @@ -2147,10 +2151,20 @@ Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs, // Scan the parameter list for the FunctionType, checking the QualType of // each parameter against the QualTypes of the arguments to the builtin. // If they match, return a new OverloadExpr. - if (ExprsMatchFnType(Args+1, FnType)) - return new OverloadExpr(Args, NumArgs, i, FnType->getResultType(), - BuiltinLoc, RParenLoc); + if (ExprsMatchFnType(Args+1, FnType)) { + if (OE) + return Diag(Fn->getExprLoc(), diag::err_overload_multiple_match, + OE->getFn()->getSourceRange()); + // Remember our match, and continue processing the remaining arguments + // to catch any errors. + OE = new OverloadExpr(Args, NumArgs, i, FnType->getResultType(), + BuiltinLoc, RParenLoc); + } } + // Return the newly created OverloadExpr node, if we succeded in matching + // exactly one of the candidate functions. + if (OE) + return OE; // If we didn't find a matching function Expr in the __builtin_overload list // the return an error. diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6e8c7c6e91..370e18d05f 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1158,20 +1158,18 @@ class OverloadExpr : public Expr { // NumExprs - the size of the SubExprs array unsigned NumExprs; - // NumArgs - the number of arguments - // The index of the matching candidate function unsigned FnIndex; SourceLocation BuiltinLoc; SourceLocation RParenLoc; public: - OverloadExpr(Expr **args, unsigned narg, unsigned idx, QualType t, + OverloadExpr(Expr **args, unsigned nexprs, unsigned idx, QualType t, SourceLocation bloc, SourceLocation rploc) - : Expr(OverloadExprClass, t), NumExprs(narg), FnIndex(idx), + : Expr(OverloadExprClass, t), NumExprs(nexprs), FnIndex(idx), BuiltinLoc(bloc), RParenLoc(rploc) { - SubExprs = new Expr*[narg]; - for (unsigned i = 0; i != narg; ++i) + SubExprs = new Expr*[nexprs]; + for (unsigned i = 0; i != nexprs; ++i) SubExprs[i] = args[i]; } ~OverloadExpr() { @@ -1192,16 +1190,18 @@ public: return constEval.getZExtValue(); } - /// getNumSubExprs - Return the size of the SubExprs array + /// getNumSubExprs - Return the size of the SubExprs array. This includes the + /// constant expression, the actual arguments passed in, and the function + /// pointers. unsigned getNumSubExprs() const { return NumExprs; } - /// getArg - Return the specified argument. - Expr *getExpr(unsigned Expr) { - assert((Expr < NumExprs) && "Arg access out of range!"); - return SubExprs[Expr]; + /// getExpr - Return the Expr at the specified index. + Expr *getExpr(unsigned Index) { + assert((Index < NumExprs) && "Arg access out of range!"); + return SubExprs[Index]; } - /// getFn - Return the matching candidate function for this OverloadExpr + /// getFn - Return the matching candidate function for this OverloadExpr. Expr *getFn() const { return SubExprs[FnIndex]; } virtual SourceRange getSourceRange() const { diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 023b7c439d..78f6c61c51 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -848,6 +848,8 @@ DIAG(err_overload_incorrect_fntype, ERROR, "argument is not a function, or has wrong number of parameters") DIAG(err_overload_no_match, ERROR, "no matching overload found for arguments of type '%0'") +DIAG(err_overload_multiple_match, ERROR, + "more than one matching function found in __builtin_overload") // CHECK: printf format string errors DIAG(warn_printf_not_string_constant, WARNING,