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 | 6eedcc1b86a10b2690803fe5e0d134aa7e3df5a8 (patch) | |
| tree | 44b15d47a770830190389749a7bd766daa1a5099 /clang/lib | |
| parent | 8ce3321eb68bfc43564e863d4e030524ec7ecc68 (diff) | |
| download | bcm5719-llvm-6eedcc1b86a10b2690803fe5e0d134aa7e3df5a8.tar.gz bcm5719-llvm-6eedcc1b86a10b2690803fe5e0d134aa7e3df5a8.zip | |
Adjust format attribute index for implicit object arguments. Fixes PR5521.
llvm-svn: 89113
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 20 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 9 |
2 files changed, 27 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 92f1ba5d6ad..9060fe6ab74 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/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) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 803be138c26..e7ea43be021 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1351,7 +1351,14 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { // 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); |

