]> granicus.if.org Git - clang/commitdiff
Implement first round of feedback on __builtin_overload
authorNate Begeman <natebegeman@mac.com>
Wed, 30 Jan 2008 20:50:20 +0000 (20:50 +0000)
committerNate Begeman <natebegeman@mac.com>
Wed, 30 Jan 2008 20:50:20 +0000 (20:50 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46572 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Expr.cpp
AST/StmtPrinter.cpp
CodeGen/CGExprComplex.cpp
CodeGen/CGExprScalar.cpp
Sema/SemaExpr.cpp
include/clang/AST/Expr.h
include/clang/Basic/DiagnosticKinds.def

index 210d1a280b968edbf1e5da53d33c6a3d51042d65..e209db35ffb9a71c671ea40314736c5272260b9f 100644 (file)
@@ -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
index f04f9e5ba517896b36eaeb964cdcd22266cb04fd..668902708d3112da2f72a60ddf436e0c146d0760 100644 (file)
@@ -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 << ")";
 }
index d96fbc77fcadc35a7570e11cdceee5b3aab19384..b1de93570d94cfd40198fde8cca421cb1ef84e35 100644 (file)
@@ -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();
 }
index 32a1b5386f080ea6b531e420d6e56a82c654d0c9..e7f58bb4689a27400bd7697a9411c03bac49c709 100644 (file)
@@ -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) {
index bb4cb519f0be661bbd5f65dde371ffa02913bfbc..86d6d772ddb7d32f4fac498bf08fac3aef9d0ed4 100644 (file)
@@ -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));
index bdd5da3e40ddf66e0400f25ff627d539e62793f0..820289976d7ebe4afc0f47ef5adb45bd6c2ac2ff 100644 (file)
@@ -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);
index 83e9e84dce1bf52e08894ba5f9ecce69a8907389..023b7c439d8962b7c9850ff1d93a058959c58b2f 100644 (file)
@@ -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'")