Adjust format attribute index for implicit object arguments. Fixes PR5521.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89113 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 92f1ba5..9060fe6 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -91,6 +91,12 @@
   if (Format->getType() == "printf0") {
     // printf0 allows null "format" string; if so don't check format/args
     unsigned format_idx = Format->getFormatIdx() - 1;
+    // Does the index refer to the implicit object argument?
+    if (isa<CXXMemberCallExpr>(TheCall)) {
+      if (format_idx == 0)
+        return false;
+      --format_idx;
+    }
     if (format_idx < TheCall->getNumArgs()) {
       Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts();
       if (!Format->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
@@ -204,7 +210,7 @@
       if (!HasVAListArg) {
         if (const FunctionProtoType *Proto
             = FDecl->getType()->getAs<FunctionProtoType>())
-        HasVAListArg = !Proto->isVariadic();
+          HasVAListArg = !Proto->isVariadic();
       }
       CheckPrintfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1,
                            HasVAListArg ? 0 : Format->getFirstArg() - 1);
@@ -970,6 +976,18 @@
                            unsigned format_idx, unsigned firstDataArg) {
   const Expr *Fn = TheCall->getCallee();
 
+  // The way the format attribute works in GCC, the implicit this argument
+  // of member functions is counted. However, it doesn't appear in our own
+  // lists, so decrement format_idx in that case.
+  if (isa<CXXMemberCallExpr>(TheCall)) {
+    // Catch a format attribute mistakenly referring to the object argument.
+    if (format_idx == 0)
+      return;
+    --format_idx;
+    if(firstDataArg != 0)
+      --firstDataArg;
+  }
+
   // CHECK: printf-like function is called with no format string.
   if (format_idx >= TheCall->getNumArgs()) {
     Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 803be13..e7ea43b 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1351,7 +1351,14 @@
   // FIXME: Do we need to bounds check?
   unsigned ArgIdx = Idx.getZExtValue() - 1;
 
-  if (HasImplicitThisParam) ArgIdx--;
+  if (HasImplicitThisParam) {
+    if (ArgIdx == 0) {
+      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
+        << "a string type" << IdxExpr->getSourceRange();
+      return;
+    }
+    ArgIdx--;
+  }
 
   // make sure the format string is really a string
   QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);