diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-10-12 20:51:52 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-10-12 20:51:52 +0000 |
commit | 580b664e9c2acd3bffddfea79b1ce2863cfd9dd0 (patch) | |
tree | 787c494c41ab1c4186a0df6d69eecf70463b9c0e /Sema/SemaChecking.cpp | |
parent | 3457e8cbaa8a6fec5d69173450655fe0bc38634b (diff) |
Added notion of '*' specified format width/specifiers when checking
printf format strings. Added type checking to see if the matching
width/precision argument was of type 'int'.
Thanks to Anders Carlsson for reporting this missing feature.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42933 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Sema/SemaChecking.cpp')
-rw-r--r-- | Sema/SemaChecking.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/Sema/SemaChecking.cpp b/Sema/SemaChecking.cpp index f764d80df2..c2e3817171 100644 --- a/Sema/SemaChecking.cpp +++ b/Sema/SemaChecking.cpp @@ -313,10 +313,47 @@ Sema::CheckPrintfArguments(Expr *Fn, // Seen '%'. Now processing a format conversion. switch (Str[StrIdx]) { - // Handle dynamic precision specifier. - case '*': - if (Str[StrIdx-1] == '.') ++numConversions; + // Handle dynamic precision or width specifier. + case '*': { + ++numConversions; + + if (!HasVAListArg && numConversions > numDataArgs) { + + SourceLocation Loc = + PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(), + StrIdx+1); + + if (Str[StrIdx-1] == '.') + Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg, + Fn->getSourceRange()); + else + Diag(Loc, diag::warn_printf_asterisk_width_missing_arg, + Fn->getSourceRange()); + + // Don't do any more checking. We'll just emit spurious errors. + return; + } + + // Perform type checking on width/precision specifier. + Expr* E = Args[format_idx+numConversions]; + QualType T = E->getType().getCanonicalType(); + if (BuiltinType *BT = dyn_cast<BuiltinType>(T)) + if (BT->getKind() == BuiltinType::Int) + break; + + SourceLocation Loc = + PP.AdvanceToTokenCharacter(Args[format_idx]->getLocStart(), + StrIdx+1); + + if (Str[StrIdx-1] == '.') + Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type, + T.getAsString(), E->getSourceRange()); + else + Diag(Loc, diag::warn_printf_asterisk_width_wrong_type, + T.getAsString(), E->getSourceRange()); + break; + } // Characters which can terminate a format conversion // (e.g. "%d"). Characters that specify length modifiers or @@ -376,7 +413,7 @@ Sema::CheckPrintfArguments(Expr *Fn, LastConversionIdx+1); Diag(Loc, diag::warn_printf_invalid_conversion, - std::string(Str+LastConversionIdx, Str+StrIdx), + std::string(Str+LastConversionIdx, Str+StrIdx), Fn->getSourceRange()); // This conversion is broken. Advance to the next format |