Implement first round of feedback on __builtin_overload

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46572 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2008-01-30 20:50:20 +00:00
Родитель bd144b7ac7
Коммит 67295d05c5
7 изменённых файлов: 82 добавлений и 29 удалений

Просмотреть файл

@ -1291,7 +1291,7 @@ Stmt::child_iterator OverloadExpr::child_begin() {
return reinterpret_cast<Stmt**>(&SubExprs[0]);
}
Stmt::child_iterator OverloadExpr::child_end() {
return reinterpret_cast<Stmt**>(&SubExprs[NumArgs]);
return reinterpret_cast<Stmt**>(&SubExprs[NumExprs]);
}
// VAArgExpr

Просмотреть файл

@ -743,9 +743,9 @@ void StmtPrinter::VisitChooseExpr(ChooseExpr *Node) {
void StmtPrinter::VisitOverloadExpr(OverloadExpr *Node) {
OS << "__builtin_overload(";
for (unsigned i = 0, e = Node->getNumArgs(); i != e; ++i) {
for (unsigned i = 0, e = Node->getNumSubExprs(); i != e; ++i) {
if (i) OS << ", ";
PrintExpr(Node->getArg(i));
PrintExpr(Node->getExpr(i));
}
OS << ")";
}

Просмотреть файл

@ -93,6 +93,7 @@ public:
}
ComplexPairTy VisitCallExpr(const CallExpr *E);
ComplexPairTy VisitStmtExpr(const StmtExpr *E);
ComplexPairTy VisitOverloadExpr(const OverloadExpr *OE);
// Operators.
ComplexPairTy VisitPrePostIncDec(const UnaryOperator *E,
@ -250,6 +251,11 @@ ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) {
return CGF.EmitCallExpr(E).getComplexVal();
}
ComplexPairTy ComplexExprEmitter::VisitOverloadExpr(const OverloadExpr *E) {
return CGF.EmitCallExpr(E->getFn(), E->arg_begin(),
E->getNumArgs(CGF.getContext())).getComplexVal();
}
ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) {
return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal();
}

Просмотреть файл

@ -1012,7 +1012,8 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) {
}
Value *ScalarExprEmitter::VisitOverloadExpr(OverloadExpr *E) {
return CGF.EmitCallExpr(E->getFn(), E->arg_begin(), E->getNumArgs()).getScalarVal();
return CGF.EmitCallExpr(E->getFn(), E->arg_begin(),
E->getNumArgs(CGF.getContext())).getScalarVal();
}
Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {

Просмотреть файл

@ -2086,12 +2086,15 @@ Sema::ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
}
/// ExprsCompatibleWithFnType - return true if the Exprs in array Args have
/// ExprsMatchFnType - return true if the Exprs in array Args have
/// QualTypes that match the QualTypes of the arguments of the FnType.
static bool ExprsCompatibleWithFnType(Expr **Args, FunctionTypeProto *FnType) {
/// The number of arguments has already been validated to match the number of
/// arguments in FnType.
static bool ExprsMatchFnType(Expr **Args, const FunctionTypeProto *FnType) {
unsigned NumParams = FnType->getNumArgs();
for (unsigned i = 0; i != NumParams; ++i)
if (Args[i]->getType() != FnType->getArgType(i))
if (Args[i]->getType().getCanonicalType() !=
FnType->getArgType(i).getCanonicalType())
return false;
return true;
}
@ -2123,25 +2126,28 @@ Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs,
SourceRange(BuiltinLoc, RParenLoc));
// Figure out the return type, by matching the args to one of the functions
// listed after the paramters.
// listed after the parameters.
for (unsigned i = NumParams + 1; i < NumArgs; ++i) {
// UsualUnaryConversions will convert the function DeclRefExpr into a
// pointer to function.
Expr *Fn = UsualUnaryConversions(Args[i]);
FunctionTypeProto *FnType = 0;
if (const PointerType *PT = Fn->getType()->getAsPointerType())
FnType = dyn_cast<FunctionTypeProto>(PT->getPointeeType());
if (const PointerType *PT = Fn->getType()->getAsPointerType()) {
QualType PointeeType = PT->getPointeeType().getCanonicalType();
FnType = dyn_cast<FunctionTypeProto>(PointeeType);
}
// The Expr type must be FunctionTypeProto, since FunctionTypeProto has no
// parameters, and the number of parameters must match the value passed to
// the builtin.
if (!FnType || (FnType->getNumArgs() != NumParams))
continue;
return Diag(Fn->getExprLoc(), diag::err_overload_incorrect_fntype,
Fn->getSourceRange());
// Scan the parameter list for the FunctionType, checking the QualType of
// each paramter against the QualTypes of the arguments to the builtin.
// each parameter against the QualTypes of the arguments to the builtin.
// If they match, return a new OverloadExpr.
if (ExprsCompatibleWithFnType(Args+1, FnType))
if (ExprsMatchFnType(Args+1, FnType))
return new OverloadExpr(Args, NumArgs, i, FnType->getResultType(),
BuiltinLoc, RParenLoc);
}
@ -2149,8 +2155,10 @@ Sema::ExprResult Sema::ActOnOverloadExpr(ExprTy **args, unsigned NumArgs,
// If we didn't find a matching function Expr in the __builtin_overload list
// the return an error.
std::string typeNames;
for (unsigned i = 0; i != NumParams; ++i)
typeNames += Args[i+1]->getType().getAsString() + " ";
for (unsigned i = 0; i != NumParams; ++i) {
if (i != 0) typeNames += ", ";
typeNames += Args[i+1]->getType().getAsString();
}
return Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
SourceRange(BuiltinLoc, RParenLoc));

Просмотреть файл

@ -1128,21 +1128,45 @@ public:
};
/// OverloadExpr - Clang builtin-in function __builtin_overload.
/// This AST node provides a way to overload functions in C
/// i.e. float Z = __builtin_overload(2, X, Y, modf, mod, modl);
/// would pick whichever of the functions modf, mod, and modl that took two
/// arguments of the same type as X and Y.
/// This AST node provides a way to overload functions in C.
///
/// The first argument is required to be a constant expression, for the number
/// of arguments passed to each candidate function.
///
/// The next N arguments, where N is the value of the constant expression,
/// are the values to be passed as arguments.
///
/// The rest of the arguments are values of pointer to function type, which
/// are the candidate functions for overloading.
///
/// The result is a equivalent to a CallExpr taking N arguments to the
/// candidate function whose parameter types match the types of the N arguments.
///
/// example: float Z = __builtin_overload(2, X, Y, modf, mod, modl);
/// If X and Y are long doubles, Z will assigned the result of modl(X, Y);
/// If X and Y are floats, Z will be assigned the result of modf(X, Y);
class OverloadExpr : public Expr {
// SubExprs - the list of values passed to the __builtin_overload function.
// SubExpr[0] is a constant expression
// SubExpr[1-N] are the parameters to pass to the matching function call
// SubExpr[N-...] are the candidate functions, of type pointer to function.
Expr **SubExprs;
unsigned NumArgs;
// 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,
SourceLocation bloc, SourceLocation rploc)
: Expr(OverloadExprClass, t), NumArgs(narg), FnIndex(idx), BuiltinLoc(bloc),
RParenLoc(rploc) {
: Expr(OverloadExprClass, t), NumExprs(narg), FnIndex(idx),
BuiltinLoc(bloc), RParenLoc(rploc) {
SubExprs = new Expr*[narg];
for (unsigned i = 0; i != narg; ++i)
SubExprs[i] = args[i];
@ -1151,19 +1175,31 @@ public:
delete [] SubExprs;
}
/// arg_begin - Return a pointer to the list of arguments that will be passed
/// to the matching candidate function, skipping over the initial constant
/// expression.
typedef Expr * const *arg_const_iterator;
arg_const_iterator arg_begin() const { return SubExprs+1; }
/// getNumArgs - Return the number of actual arguments to this call.
///
unsigned getNumArgs() const { return NumArgs; }
/// getNumArgs - Return the number of arguments to pass to the candidate
/// functions.
unsigned getNumArgs(ASTContext &Ctx) const {
llvm::APSInt constEval(32);
(void) SubExprs[0]->isIntegerConstantExpr(constEval, Ctx);
return constEval.getZExtValue();
}
/// getNumSubExprs - Return the size of the SubExprs array
unsigned getNumSubExprs() const { return NumExprs; }
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return SubExprs[Arg];
Expr *getExpr(unsigned Expr) {
assert((Expr < NumExprs) && "Arg access out of range!");
return SubExprs[Expr];
}
Expr *getFn() { return SubExprs[FnIndex]; }
/// getFn - Return the matching candidate function for this OverloadExpr
Expr *getFn() const { return SubExprs[FnIndex]; }
virtual SourceRange getSourceRange() const {
return SourceRange(BuiltinLoc, RParenLoc);

Просмотреть файл

@ -844,6 +844,8 @@ DIAG(err_invalid_conversion_between_vector_and_scalar, ERROR,
"invalid conversion between vector type '%0' and scalar type '%1'")
DIAG(err_overload_expr_requires_non_zero_constant, ERROR,
"overload requires a non-zero constant expression as first argument")
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'")