Implement support for the format_arg attribute. Fixes PR4442.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74369 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index a2ceafa..f6d6623 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -717,6 +717,8 @@
   if (E->isTypeDependent() || E->isValueDependent())
     return false;
 
+  E = E->IgnoreParenCasts();
+  
   switch (E->getStmtClass()) {
   case Stmt::ConditionalOperatorClass: {
     const ConditionalOperator *C = cast<ConditionalOperator>(E);
@@ -766,6 +768,25 @@
     return false;
   }
 
+  case Stmt::CallExprClass: {
+    const CallExpr *CE = cast<CallExpr>(E);
+    if (const ImplicitCastExpr *ICE 
+          = dyn_cast<ImplicitCastExpr>(CE->getCallee())) {
+      if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
+        if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+          if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>(Context)) {
+            unsigned ArgIndex = FA->getFormatIdx();
+            const Expr *Arg = CE->getArg(ArgIndex - 1);
+            
+            return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg, 
+                                          format_idx, firstDataArg);
+          }
+        }
+      }
+    }
+    
+    return false;
+  }
   case Stmt::ObjCStringLiteralClass:
   case Stmt::StringLiteralClass: {
     const StringLiteral *StrE = NULL;
diff --git a/test/Sema/attr-format_arg.c b/test/Sema/attr-format_arg.c
new file mode 100644
index 0000000..6f95315
--- /dev/null
+++ b/test/Sema/attr-format_arg.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+const char* f(const char *s) __attribute__((format_arg(1)));
+
+void g(const char *s) {
+  printf("%d", 123);
+  printf("%d %d", 123); // expected-warning{{more '%' conversions than data arguments}}
+
+  printf(f("%d"), 123);
+  printf(f("%d %d"), 123); // expected-warning{{more '%' conversions than data arguments}}
+}