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
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index bb4cb51..86d6d77 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -2086,12 +2086,15 @@
   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 @@
                 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 @@
   // 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));