[cfe-dev] type specifiers in scanf/sscanf and NSInteger
Александр Шапошников via cfe-dev
cfe-dev at lists.llvm.org
Thu Jun 8 19:05:38 PDT 2017
Hi,
recently, i was looking into Clang's fixits generated for the format string
used in
"printf" / "scanf" for some common ObjC types.
There is some relevant public documentation here:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
.
It turns out that in the case of "scanf" there are some extra complications
and
I would like to ask for your advice.
So let's take a look at the following two examples:
(Example 1)
void printNSInteger() {
NSInteger x = 123;
printf("%d", x);
}
A. If the triple is 32-bit this code compiles cleanly with -Wformat -fixit
B. If the triple is 64-bit Clang will generate a warning and the
corresponding fixit
replaces printf("%d", x) with printf("%ld", (long)x).
The new code has an important property that it's correct for 32-bit targets
as well.
(Example 2)
void readNSInteger() {
NSInteger x;
scanf("%d", &x);
}
A. If the triple is 32-bit this code compiles cleanly with -Wformat -fixit
B. If the triple is 64-bit Clang will generate a warning and the
corresponding fixit
which replaces scanf("%d", &x); with scanf("%ld", &x);
Unfortunately, the new code is broken for 32-bits targets:
Simple test:
#include <stdio.h>
typedef struct {
int x;
int y;
} Point;
int main() {
Point p = { 1, 1 };
scanf("%ld", &p.x);
printf("%d %d\n", p.x, p.y);
return 0;
}
./main <<< '2'
will print 2 0 (so p.y was overwritten by scanf).
This becomes an issue for some shared code which is compiled for 32-bit and
64 bit targets.
A natural question comes up what the proper "fixit" for readNSInteger()
should look like
and how it would coexist with the current warnings/fixits. I will list a
few options (mostly to start a discussion) which come on my mind first, but
i am interested in your opinion, plus
i assume i might be missing something.
Option 1:
Make "fixit" produce the following code modification
(if the code is compiled for 64 bits target):
replace (that's just a sketch, because there are some complications with
function-style macros and macro parameters)
scanf("%d", &x);
with
#if defined (_LP64_)
scanf("%ld", &x);
#else
scanf("%d", &x);
#endif
Option 2:
"Hacky" (inspired by
https://twitter.com/gparker/status/377910611453046784?lang=en )
Make "fixit" produce the following code modification
(if the code is compiled for 64 bits target):
replace
scanf("%d", &x);
with
scanf("%zd", &x); // aka size_t
-------------------
Kind regards,
Alexander Shaposhnikov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170608/f13d3f8d/attachment.html>
More information about the cfe-dev
mailing list