From: Nico Weber Date: Wed, 30 Apr 2014 04:35:09 +0000 (+0000) Subject: Let stddef.h respect __need_{wchar_t, size_t, NULL, ptrdiff_t, wint_t}. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7933ecef1047af471f6116acb9ec052cec9e9335;p=clang Let stddef.h respect __need_{wchar_t, size_t, NULL, ptrdiff_t, wint_t}. glibc expects that stddef.h only defines a single thing if either of these defines is set. For example, before this change, a C file containing #include int ptrdiff_t = 0; would compile with gcc but not with clang. Now it compiles with clang too. This also fixes PR12997, where older versions of the Linux headers would define NULL incorrectly, and glibc would define __need_NULL and expect stddef.h to redefine NULL with the correct definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207606 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Headers/stddef.h b/lib/Headers/stddef.h index 97126ed152..2dfe0a29b2 100644 --- a/lib/Headers/stddef.h +++ b/lib/Headers/stddef.h @@ -23,9 +23,22 @@ *===-----------------------------------------------------------------------=== */ -#ifndef __STDDEF_H +#if !defined(__STDDEF_H) || defined(__need_ptrdiff_t) || \ + defined(__need_size_t) || defined(__need_wchar_t) || \ + defined(__need_NULL) || defined(__need_wint_t) + +#if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \ + !defined(__need_wchar_t) && !defined(__need_NULL) && \ + !defined(__need_wint_t) #define __STDDEF_H +#define __need_ptrdiff_t +#define __need_size_t +#define __need_wchar_t +#define __need_NULL +/* __need_wint_t is intentionally not defined here. */ +#endif +#if defined(__need_ptrdiff_t) #if !defined(_PTRDIFF_T) || __has_feature(modules) /* Always define ptrdiff_t when modules are available. */ #if !__has_feature(modules) @@ -33,7 +46,10 @@ #endif typedef __PTRDIFF_TYPE__ ptrdiff_t; #endif +#undef __need_ptrdiff_t +#endif /* defined(__need_ptrdiff_t) */ +#if defined(__need_size_t) #if !defined(_SIZE_T) || __has_feature(modules) /* Always define size_t when modules are available. */ #if !__has_feature(modules) @@ -41,7 +57,10 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; #endif typedef __SIZE_TYPE__ size_t; #endif +#undef __need_size_t +#endif /*defined(__need_size_t) */ +#if defined(__STDDEF_H) /* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is * enabled. */ #if (defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 && \ @@ -52,7 +71,9 @@ typedef __SIZE_TYPE__ size_t; #endif typedef __SIZE_TYPE__ rsize_t; #endif +#endif /* defined(__STDDEF_H) */ +#if defined(__need_wchar_t) #ifndef __cplusplus /* Always define wchar_t when modules are available. */ #if !defined(_WCHAR_T) || __has_feature(modules) @@ -65,7 +86,10 @@ typedef __SIZE_TYPE__ rsize_t; typedef __WCHAR_TYPE__ wchar_t; #endif #endif +#undef __need_wchar_t +#endif /* defined(__need_wchar_t) */ +#if defined(__need_NULL) #undef NULL #ifdef __cplusplus # if !defined(__MINGW32__) && !defined(_MSC_VER) @@ -76,15 +100,19 @@ typedef __WCHAR_TYPE__ wchar_t; #else # define NULL ((void*)0) #endif - #ifdef __cplusplus #if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED) namespace std { typedef decltype(nullptr) nullptr_t; } using ::std::nullptr_t; #endif #endif +#undef __need_NULL +#endif /* defined(__need_NULL) */ + +#if defined(__STDDEF_H) #if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L +#if !defined(__CLANG_MAX_ALIGN_T_DEFINED) || __has_feature(modules) #ifndef _MSC_VER typedef struct { long long __clang_max_align_nonce1 @@ -97,10 +125,10 @@ typedef double max_align_t; #endif #define __CLANG_MAX_ALIGN_T_DEFINED #endif +#endif #define offsetof(t, d) __builtin_offsetof(t, d) - -#endif /* __STDDEF_H */ +#endif /* __STDDEF_H */ /* Some C libraries expect to see a wint_t here. Others (notably MinGW) will use __WINT_TYPE__ directly; accommodate both by requiring __need_wint_t */ @@ -114,3 +142,5 @@ typedef __WINT_TYPE__ wint_t; #endif #undef __need_wint_t #endif /* __need_wint_t */ + +#endif diff --git a/test/Headers/stddefneeds.cpp b/test/Headers/stddefneeds.cpp new file mode 100644 index 0000000000..304a224acc --- /dev/null +++ b/test/Headers/stddefneeds.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wsentinel -std=c++11 %s + +ptrdiff_t p0; // expected-error{{unknown}} +size_t s0; // expected-error{{unknown}} +void* v0 = NULL; // expected-error{{undeclared}} +wint_t w0; // expected-error{{unknown}} +max_align_t m0; // expected-error{{unknown}} + +#define __need_ptrdiff_t +#include + +ptrdiff_t p1; +size_t s1; // expected-error{{unknown}} +void* v1 = NULL; // expected-error{{undeclared}} +wint_t w1; // expected-error{{unknown}} +max_align_t m1; // expected-error{{unknown}} + +#define __need_size_t +#include + +ptrdiff_t p2; +size_t s2; +void* v2 = NULL; // expected-error{{undeclared}} +wint_t w2; // expected-error{{unknown}} +max_align_t m2; // expected-error{{unknown}} + +#define __need_NULL +#include + +ptrdiff_t p3; +size_t s3; +void* v3 = NULL; +wint_t w3; // expected-error{{unknown}} +max_align_t m3; // expected-error{{unknown}} + +// Shouldn't bring in wint_t by default: +#include + +ptrdiff_t p4; +size_t s4; +void* v4 = NULL; +wint_t w4; // expected-error{{unknown}} +max_align_t m4; + +#define __need_wint_t +#include + +ptrdiff_t p5; +size_t s5; +void* v5 = NULL; +wint_t w5; +max_align_t m5; + + +// linux/stddef.h does something like this for cpp files: +#undef NULL +#define NULL 0 + +// glibc (and other) headers then define __need_NULL and rely on stddef.h +// to redefine NULL to the correct value again. +#define __need_NULL +#include + +// gtk headers then use __attribute__((sentinel)), which doesn't work if NULL +// is 0. +void f(const char* c, ...) __attribute__((sentinel)); +void g() { + f("", NULL); // Shouldn't warn. +} diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index ad7b37c3e1..e31644a987 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -1,8 +1,9 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs %s // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -isystem %S/Inputs -fno-signed-char %s -#define __need_wint_t #include +#include +#define __need_wint_t #include // For wint_t and wchar_t typedef struct _FILE FILE;