[cfe-dev] clang printf correspondence between conversion specifier and arguments
Cristian Draghici
cristian.draghici at gmail.com
Thu Jan 21 02:17:10 PST 2010
Hi
I am attaching a patch for "%i" and "%d".
I've not carried on with the rest of the conversion specifiers because they
should probably be handled by a single block of code (vs having one common
block per type of argument - i.e. one for int, unsigned int, etc).
i.e.
builtinTypeKind conversionSpecifierType;
case 'i':
case 'd':
conversionSpecifierType = BuiltinType::Int;
case 'o':
case 'u':
case 'X':
case 'x':
conversionSpecifierType = BuiltinType::UInt;
[..]
case 'p':
/* do diagnostics here based on the conversionSpecifierType and the
current argument */
Thanks,
Cristi
PS Is there a way to get the string representation of the built-in type?
(i.e. 'int' out of 'BuiltinType::Int')
On Thu, Jan 21, 2010 at 8:24 AM, Ted Kremenek <kremenek at apple.com> wrote:
> Hi Cristi,
>
> This is definitely on the right track.
>
> To add a warning, you only need to modify the TableGen files (.td), as the
> .inc files are generated from the .td files during the build. Specifically,
> you only need to modify DiagnosticSemaKinds.td and add one warning to the
> Format group. Your warning declaration would look something like:
>
> def my_warning : Warning<
> "conversion specifies type '%0' but the argument has type '%1'">,
> InGroup<Format>;
>
> You would then use it similarly to the
> warn_printf_asterisk_precision_wrong_type warning (in SemaChecking.cpp),
> except you specify two QualType arguments instead of one.
>
> Please also include a couple test cases that show when the warning is both
> reported and *not* reported. The test cases should also include the use of
> typedefs (which I believe your logic already handles).
>
> - Ted
>
> On Jan 19, 2010, at 11:26 PM, Cristian Draghici wrote:
>
> > Hi
> >
> > I've started looking at printf correspondence between conversion
> specifier and arguments.
> >
> > 1/ Am I on the right track with the patch below?
> >
> > 2/ Assuming an affirmative answer on (1), I'm not sure how to define a
> new warning (I used warn_printf_asterisk_width_wrong_type which is wrong in
> this case).
> > I'm guessing defs are in include/clang/Basic/DiagnosticSemaKinds.inc and
> .td and referred in DiagnosticGroups.inc and .td
> > A new diagnostic would be needed, along the lines of "conversion
> specifies type 'X', but argument has type 'Y'"
> >
> >
> > Thanks for your time,
> > Cristi
> >
> >
> > cristi:clang diciu$ svn diff ./lib/Sema/SemaChecking.cpp
> > Index: lib/Sema/SemaChecking.cpp
> > ===================================================================
> > --- lib/Sema/SemaChecking.cpp (revision 93981)
> > +++ lib/Sema/SemaChecking.cpp (working copy)
> > @@ -1147,7 +1147,17 @@
> > //
> > // FIXME: additional checks will go into the following cases.
> > case 'i':
> > - case 'd':
> > + case 'd': {
> > + if(numDataArgs >= format_idx+numConversions+1) {
> > + const Expr *E2 = TheCall->getArg(format_idx+numConversions+1);
> > + const BuiltinType *BT = E2->getType()->getAs<BuiltinType>();
> > + if(BT == NULL || BT->getKind() != BuiltinType::Int) {
> > + SourceLocation Loc = getLocationOfStringLiteralByte(FExpr,
> StrIdx);
> > + Diag(Loc, diag::warn_printf_asterisk_width_wrong_type)
> > + << E2->getType() << E2->getSourceRange();
> > + }
> > + }
> > + }
> > case 'o':
> > case 'u':
> > case 'x':
> >
> >
> >
> > _______________________________________________
> > cfe-dev mailing list
> > cfe-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20100121/c9bc068b/attachment.html>
-------------- next part --------------
Index: test/Sema/format-strings.c
===================================================================
--- test/Sema/format-strings.c (revision 94069)
+++ test/Sema/format-strings.c (working copy)
@@ -103,6 +103,16 @@
printf("%.*d","foo",x); // expected-warning {{field precision should have type 'int', but argument has type 'char *'}}
}
+void check_conversion_specifier_vs_argument(int x) {
+ printf("%i", x); // no warning
+ printf("%i", "foo"); // expected-warning {{conversion specifies type 'int' but the argument has type 'char *'}}
+ printf("%i %i", x, "foo"); // expected-warning {{conversion specifies type 'int' but the argument has type 'char *'}}
+
+ typedef int myint;
+ myint i1=12;
+ printf("%i", i1); // no warning
+}
+
void __attribute__((format(printf,1,3))) myprintf(const char*, int blah, ...);
void test_myprintf() {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 94069)
+++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
@@ -2435,6 +2435,9 @@
def warn_printf_asterisk_precision_wrong_type : Warning<
"field precision should have type 'int', but argument has type %0">,
InGroup<Format>;
+def warn_printf_conversion_argument_type_mismatch : Warning<
+ "conversion specifies type '%0' but the argument has type %1">,
+ InGroup<Format>;
// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr : Warning<
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp (revision 94069)
+++ lib/Sema/SemaChecking.cpp (working copy)
@@ -1155,7 +1155,17 @@
//
// FIXME: additional checks will go into the following cases.
case 'i':
- case 'd':
+ case 'd': {
+ if(!HasVAListArg && numDataArgs + format_idx > numConversions) {
+ const Expr *E2 = TheCall->getArg(numConversions+format_idx+1);
+ const BuiltinType *BT = E2->getType()->getAs<BuiltinType>();
+ if(BT == NULL || BT->getKind() != BuiltinType::Int) {
+ SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx);
+ Diag(Loc, diag::warn_printf_conversion_argument_type_mismatch)
+ << "int" << E2->getType() << E2->getSourceRange();
+ }
+ }
+ }
case 'o':
case 'u':
case 'x':
More information about the cfe-dev
mailing list