Christian Franke wrote:
Kai Tietz wrote:
The point about C++ is, that we lack a default prototype.
Yes, but if some "int printf(const char *, ...)" prototype is
specified, "__attribute__((format(printf(1,2)))" from builtin info is
always added silently by g++. Even an
"__attribute__(format(gnu_printf(1,2)))" in the prototype does not
prevent this.
Root of the problem is that the C++ compiler does not properly shadow a
"hidden" builtin if reimplemented as a static with C linkage. It merges
the builtin attributes instead. Probably a subtle bug around
gcc-4.5.3/gcc/cp/decl.c:dublicate_decls().
The following testcase shows that format errors common to ms_printf and
gnu_printf are reported twice in C++. This likely proves that both
attributes are set internally:
$ cat testfmt3.c
#ifdef __cplusplus
extern "C" {
#endif
static __attribute__((format(gnu_printf,1,2)))
int printf(const char *fmt, ...) { return 0; };
#ifdef __cplusplus
}
#endif
int main()
{
printf("%ld", 42); // C++: 2 warnings
printf("%lld", 42LL); // C++: bogus warning
printf("%I64d", 42LL);
}
$ i686-w64-mingw32-gcc -Wshadow -Wformat -c testfmt3.c
testfmt3.c:7:5: warning: declaration of 'printf' shadows a built-in function
testfmt3.c: In function 'main':
testfmt3.c:15:3: warning: format '%ld' expects type 'long int', but
argument 2 has type 'int'
testfmt3.c:17:3: warning: format '%I64d' expects type 'int', but
argument 2 has type 'long long int'
$ i686-w64-mingw32-g++ -Wshadow -Wformat -c testfmt3.c
testfmt3.c: In function 'int main()':
testfmt3.c:15:19: warning: format '%ld' expects type 'long int', but
argument 2 has type 'int'
testfmt3.c:15:19: warning: format '%ld' expects type 'long int', but
argument 2 has type 'int'
testfmt3.c:16:22: warning: unknown conversion type character 'l' in format
testfmt3.c:16:22: warning: too many arguments for format
testfmt3.c:17:23: warning: format '%I64d' expects type 'int', but
argument 2 has type 'long long int'
Meantime I found an easy workaround: Use C++ linkage for printf wrapper
functions, see attached patch. Smoke tested with smartmontools build.
As a positive side effect this produces less code than in C: e.g. one
__Z6printfPKcz per program instead of one _printf per module :-)
Christian
--- stdio.h.orig 2012-01-07 06:42:43.001000000 +0100
+++ stdio.h 2012-01-17 14:09:59.939569000 +0100
@@ -201,6 +201,10 @@
* User has expressed a preference for C99 conformance...
*/
+#ifdef __cplusplus
+extern "C++" {
+#endif
+
__mingw_ovr
__attribute__((__format__ (gnu_scanf, 2, 3))) __MINGW_ATTRIB_NONNULL(2)
int sscanf(const char *__source, const char *__format, ...)
@@ -355,6 +359,10 @@
/* #endif */ /* __NO_ISOCEXT */
+#ifdef __cplusplus
+}
+#endif
+
#else /* !__USE_MINGW_ANSI_STDIO */
#undef __builtin_vsnprintf
------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public