зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
bd144b7ac7
Коммит
67295d05c5
|
@ -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'")
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче