r207606 - Let stddef.h respect __need_{wchar_t, size_t, NULL, ptrdiff_t, wint_t}.

Nico Weber nicolasweber at gmx.de
Tue Apr 29 21:35:09 PDT 2014


Author: nico
Date: Tue Apr 29 23:35:09 2014
New Revision: 207606

URL: http://llvm.org/viewvc/llvm-project?rev=207606&view=rev
Log:
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 <stdlib.h>
  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.

Added:
    cfe/trunk/test/Headers/stddefneeds.cpp
Modified:
    cfe/trunk/lib/Headers/stddef.h
    cfe/trunk/test/Sema/format-strings.c

Modified: cfe/trunk/lib/Headers/stddef.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/stddef.h?rev=207606&r1=207605&r2=207606&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/stddef.h (original)
+++ cfe/trunk/lib/Headers/stddef.h Tue Apr 29 23:35:09 2014
@@ -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

Added: cfe/trunk/test/Headers/stddefneeds.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Headers/stddefneeds.cpp?rev=207606&view=auto
==============================================================================
--- cfe/trunk/test/Headers/stddefneeds.cpp (added)
+++ cfe/trunk/test/Headers/stddefneeds.cpp Tue Apr 29 23:35:09 2014
@@ -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 <stddef.h>
+
+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 <stddef.h>
+
+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 <stddef.h>
+
+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 <stddef.h>
+
+ptrdiff_t p4;
+size_t s4;
+void* v4 = NULL;
+wint_t w4; // expected-error{{unknown}}
+max_align_t m4;
+
+#define __need_wint_t
+#include <stddef.h>
+
+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 <stddef.h>
+
+// 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.
+}

Modified: cfe/trunk/test/Sema/format-strings.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/format-strings.c?rev=207606&r1=207605&r2=207606&view=diff
==============================================================================
--- cfe/trunk/test/Sema/format-strings.c (original)
+++ cfe/trunk/test/Sema/format-strings.c Tue Apr 29 23:35:09 2014
@@ -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 <stdarg.h>
+#include <stddef.h>
+#define __need_wint_t
 #include <stddef.h> // For wint_t and wchar_t
 
 typedef struct _FILE FILE;





More information about the cfe-commits mailing list