diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-11-17 18:02:24 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-11-17 18:02:24 +0000 |
commit | 4a2614e94672c47395abcde60518776fbebec589 (patch) | |
tree | 793db4f94de9dd0f2c7c7ee3be9d4ed09be41f37 /lib/Sema/SemaChecking.cpp | |
parent | 24a069f5ebf441d86eaec7524365101adf6b2aeb (diff) |
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
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 92f1ba5d6a..9060fe6ab7 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -91,6 +91,12 @@ bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { 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 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { 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 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, 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) |