]> granicus.if.org Git - clang/commitdiff
When we're calling a function that we know based on its K&R-style
authorDouglas Gregor <dgregor@apple.com>
Mon, 25 Oct 2010 20:39:23 +0000 (20:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 25 Oct 2010 20:39:23 +0000 (20:39 +0000)
function definition, we should still use a prototype to type-check and
convert the function arguments, if such a prototype exists. Fixes
PR8314.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117305 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/Sema/knr-def-call.c

index ced383310ffb3210d7c90cfff5fe1559dea507c5..793dc42759b05c88d4251cfd564c0a007d7f7d86 100644 (file)
@@ -3836,24 +3836,51 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
       // on our knowledge of the function definition.
       const FunctionDecl *Def = 0;
       if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) {
-        const FunctionProtoType *Proto =
-            Def->getType()->getAs<FunctionProtoType>();
-        if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) {
+        const FunctionProtoType *Proto 
+          = Def->getType()->getAs<FunctionProtoType>();
+        if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size()))
           Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
             << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange();
-        }
       }
+      
+      // If the function we're calling isn't a function prototype, but we have
+      // a function prototype from a prior declaratiom, use that prototype.
+      if (!FDecl->hasPrototype())
+        Proto = FDecl->getType()->getAs<FunctionProtoType>();
     }
 
     // Promote the arguments (C99 6.5.2.2p6).
     for (unsigned i = 0; i != NumArgs; i++) {
       Expr *Arg = Args[i];
-      DefaultArgumentPromotion(Arg);
-      if (RequireCompleteType(Arg->getSourceRange().getBegin(),
-                              Arg->getType(),
-                              PDiag(diag::err_call_incomplete_argument)
-                                << Arg->getSourceRange()))
-        return ExprError();
+
+      if (Proto && i < Proto->getNumArgs()) {
+        if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+                                Arg->getType(),
+                                PDiag(diag::err_call_incomplete_argument)
+                                  << Arg->getSourceRange()))
+          return ExprError();
+
+        InitializedEntity Entity
+          = InitializedEntity::InitializeParameter(Context, 
+                                                   Proto->getArgType(i));
+        ExprResult ArgE = PerformCopyInitialization(Entity,
+                                                    SourceLocation(),
+                                                    Owned(Arg));
+        if (ArgE.isInvalid())
+          return true;
+        
+        Arg = ArgE.takeAs<Expr>();
+
+      } else {
+        DefaultArgumentPromotion(Arg);
+
+        if (RequireCompleteType(Arg->getSourceRange().getBegin(),
+                                Arg->getType(),
+                                PDiag(diag::err_call_incomplete_argument)
+                                  << Arg->getSourceRange()))
+          return ExprError();
+      }
+      
       TheCall->setArg(i, Arg);
     }
   }
index fd06cbf6457444a4bf6304a7b025f8bf389299dc..fc6cfbbd5623f4aebea777a0942cdd56e099e003 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -Wconversion -fsyntax-only -verify %s
 
 // C DR #316, PR 3626.
 void f0(a, b, c, d) int a,b,c,d; {}
@@ -27,3 +27,14 @@ char *rindex(s, c)
 {
   return 0;
 }
+
+// PR8314
+void proto(int);
+void proto(x) 
+     int x;
+{
+}
+
+void use_proto() {
+  proto(42.0); // expected-warning{{implicit conversion turns floating-point number into integer: 'double' to 'int'}}
+}