[clang][Sema] Accept gnu format attributes by higuoxing · Pull Request #160255 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-clang

Author: Xing Guo (higuoxing)

Changes

This patch teaches clang accepts gnu_printf, gnu_scanf and gnu_strftime.
These attributes are aliases for printf, scanf and strftime.

Ref: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
Fixes: #16219


Full diff: https://github.com/llvm/llvm-project/pull/160255.diff

6 Files Affected:

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d017d1f829015..5edfc29d93781 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -503,7 +503,6 @@ enum class FormatStringType { FreeBSDKPrintf, OSTrace, OSLog,

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 740b472b0eb16..614a7ba36a623 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -6862,10 +6862,10 @@ StringRef Sema::GetFormatStringTypeName(FormatStringType FST) {

FormatStringType Sema::GetFormatStringType(StringRef Flavor) { return llvm::StringSwitch(Flavor)

@@ -6986,7 +6986,6 @@ bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, case FormatStringType::Kprintf: case FormatStringType::FreeBSDKPrintf: case FormatStringType::Printf:

@@ -9175,8 +9172,7 @@ bool Sema::ValidateFormatString(FormatStringType Type, if (Type != FormatStringType::Printf && Type != FormatStringType::NSString && Type != FormatStringType::Kprintf && Type != FormatStringType::FreeBSDKPrintf &&

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b876911384f6f..1f19931b74be6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3629,10 +3629,10 @@ static FormatAttrKind getFormatAttrKind(StringRef Format) { // Check for formats that get handled specially. .Case("NSString", NSStringFormat) .Case("CFString", CFStringFormat)

diff --git a/clang/test/Sema/attr-format.c b/clang/test/Sema/attr-format.c index 5b9e4d02bbaf9..de6a99b15780e 100644 --- a/clang/test/Sema/attr-format.c +++ b/clang/test/Sema/attr-format.c @@ -106,3 +106,11 @@ void b2(const char *a, ...) attribute((format(syslog, 1, 1))); // expecte void c2(const char *a, ...) attribute((format(syslog, 0, 2))); // expected-error {{'format' attribute parameter 2 is out of bounds}} void d2(const char *a, int c) attribute((format(syslog, 1, 2))); // expected-warning {{GCC requires a function with the 'format' attribute to be variadic}} void e2(char *str, int c, ...) attribute((format(syslog, 2, 3))); // expected-error {{format argument not a string type}} + +// gnu_printf +// same as format(pritf(...))... +void a2(const char *a, ...) attribute((format(gnu_printf, 1, 2))); // no-error +void b2(const char *a, ...) attribute((format(gnu_printf, 1, 1))); // expected-error {{'format' attribute parameter 3 is out of bounds}} +void c2(const char *a, ...) attribute((format(gnu_printf, 0, 2))); // expected-error {{'format' attribute parameter 2 is out of bounds}} +void d2(const char *a, int c) attribute((format(gnu_printf, 1, 2))); // expected-warning {{GCC requires a function with the 'format' attribute to be variadic}} +void e2(char *str, int c, ...) attribute((format(gnu_printf, 2, 3))); // expected-error {{format argument not a string type}} diff --git a/clang/test/Sema/format-strings-scanf.c b/clang/test/Sema/format-strings-scanf.c index d1f694f3595cf..22c1cce2f989b 100644 --- a/clang/test/Sema/format-strings-scanf.c +++ b/clang/test/Sema/format-strings-scanf.c @@ -30,6 +30,7 @@ int fscanf(FILE * restrict, const char * restrict, ...) ; int scanf(const char * restrict, ...) ; int sscanf(const char * restrict, const char * restrict, ...) ; int my_scanf(const char * restrict, ...) attribute((format(scanf, 1, 2))); +int my_gnu_scanf(const char * restrict, ...) attribute((format(gnu_scanf, 1, 2)));

int vscanf(const char * restrict, va_list); int vfscanf(FILE * restrict, const char * restrict, va_list); @@ -98,6 +99,7 @@ void test_variants(int *i, const char *s, ...) { fscanf(f, "%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}} sscanf(buf, "%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}} my_scanf("%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}

diff --git a/clang/test/Sema/format-strings.c b/clang/test/Sema/format-strings.c index 4bff30c313c8f..4a2ee8900bb5a 100644 --- a/clang/test/Sema/format-strings.c +++ b/clang/test/Sema/format-strings.c @@ -679,6 +679,7 @@ void pr18905(void) {

void attribute((format(strfmon,1,2))) monformat(const char *fmt, ...); void attribute((format(strftime,1,0))) dateformat(const char *fmt); +void attribute((format(gnu_strftime,1,0))) gnu_dateformat(const char *fmt);

// Other formats void test_other_formats(void) { @@ -687,6 +688,8 @@ void test_other_formats(void) { monformat(str); // expected-warning{{format string is not a string literal (potentially insecure)}} dateformat(""); // expected-warning{{format string is empty}} dateformat(str); // no-warning (using strftime non-literal is not unsafe)

// Do not warn about unused arguments coming from system headers.