[clang] 62f769a - [Headers] Add missing __need_ macros to stdarg.h

Ian Anderson via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 23 23:55:35 PDT 2023


Author: Ian Anderson
Date: 2023-08-23T23:55:30-07:00
New Revision: 62f769aa82f668a076fed2633e425631a4598a47

URL: https://github.com/llvm/llvm-project/commit/62f769aa82f668a076fed2633e425631a4598a47
DIFF: https://github.com/llvm/llvm-project/commit/62f769aa82f668a076fed2633e425631a4598a47.diff

LOG: [Headers] Add missing __need_ macros to stdarg.h

Apple needs a `__need_` macro for va_list. Add one, and also ones for va_start/va_arg/va_end, __va_copy, va_copy.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D157793

Added: 
    clang/test/Headers/stdarg.c
    clang/test/Headers/stdargneeds.c

Modified: 
    clang/lib/Headers/stdarg.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/Headers/stdarg.h b/clang/lib/Headers/stdarg.h
index 13742eea61f631..521c4733d55589 100644
--- a/clang/lib/Headers/stdarg.h
+++ b/clang/lib/Headers/stdarg.h
@@ -7,22 +7,45 @@
  *===-----------------------------------------------------------------------===
  */
 
-#ifndef __STDARG_H
+#if !defined(__STDARG_H) || defined(__need___va_list) ||                       \
+    defined(__need_va_list) || defined(__need_va_arg) ||                       \
+    defined(__need___va_copy) || defined(__need_va_copy)
 
+#if !defined(__need___va_list) && !defined(__need_va_list) &&                  \
+    !defined(__need_va_arg) && !defined(__need___va_copy) &&                   \
+    !defined(__need_va_copy)
+#define __STDARG_H
+#define __need___va_list
+#define __need_va_list
+#define __need_va_arg
+#define __need___va_copy
+/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
+ * or -ansi is not specified, since it was not part of C90.
+ */
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) ||              \
+    (defined(__cplusplus) && __cplusplus >= 201103L) ||                        \
+    !defined(__STRICT_ANSI__)
+#define __need_va_copy
+#endif
+#endif
+
+#ifdef __need___va_list
 #ifndef __GNUC_VA_LIST
 #define __GNUC_VA_LIST
 typedef __builtin_va_list __gnuc_va_list;
 #endif
-
-#ifdef __need___va_list
 #undef __need___va_list
-#else
-#define __STDARG_H
+#endif /* defined(__need___va_list) */
+
+#ifdef __need_va_list
 #ifndef _VA_LIST
 typedef __builtin_va_list va_list;
 #define _VA_LIST
 #endif
+#undef __need_va_list
+#endif /* defined(__need_va_list) */
 
+#ifdef __need_va_arg
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
 /* C23 does not require the second parameter for va_start. */
 #define va_start(ap, ...) __builtin_va_start(ap, 0)
@@ -32,18 +55,17 @@ typedef __builtin_va_list va_list;
 #endif
 #define va_end(ap)          __builtin_va_end(ap)
 #define va_arg(ap, type)    __builtin_va_arg(ap, type)
+#undef __need_va_arg
+#endif /* defined(__need_va_arg) */
 
-/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
- * or -ansi is not specified, since it was not part of C90.
- */
+#ifdef __need___va_copy
 #define __va_copy(d,s) __builtin_va_copy(d,s)
+#undef __need___va_copy
+#endif /* defined(__need___va_copy) */
 
-#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) ||              \
-    (defined(__cplusplus) && __cplusplus >= 201103L) ||                        \
-    !defined(__STRICT_ANSI__)
+#ifdef __need_va_copy
 #define va_copy(dest, src)  __builtin_va_copy(dest, src)
-#endif
-
-#endif /* __STDARG_H */
+#undef __need_va_copy
+#endif /* defined(__need_va_copy) */
 
-#endif /* not __STDARG_H */
+#endif

diff  --git a/clang/test/Headers/stdarg.c b/clang/test/Headers/stdarg.c
new file mode 100644
index 00000000000000..49df42caa3300a
--- /dev/null
+++ b/clang/test/Headers/stdarg.c
@@ -0,0 +1,37 @@
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c
+// RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c
+
+// Split the file so that the "implicitly declaring library function" errors get repeated.
+
+//--- stdarg0.c
+static void f(int p, ...) {
+    __gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}}
+    va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}}
+    va_start(v, p); // c89-error{{implicitly declaring library function 'va_start'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_start'}} c89-error{{undeclared identifier 'v'}} \
+                       c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
+    int i = va_arg(v, int); // c89-error{{implicit declaration of function 'va_arg'}} c89-error{{expected expression}} c89-error{{use of undeclared identifier 'v'}} \
+                               c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}}
+    va_end(v); // c89-error{{implicitly declaring library function 'va_end'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_end'}} c89-error{{undeclared identifier 'v'}} \
+                  c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
+    __va_copy(g, v); // c89-error{{implicit declaration of function '__va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \
+                        c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
+    va_copy(g, v); // c89-error{{implicitly declaring library function 'va_copy'}} c89-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_copy'}} c89-error{{use of undeclared identifier 'g'}} c89-error{{use of undeclared identifier 'v'}} \
+                      c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
+}
+
+//--- stdarg1.c
+// c99-no-diagnostics
+
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g;
+    va_list v;
+    va_start(v, p);
+    int i = va_arg(v, int);
+    va_end(v);
+    __va_copy(g, v);
+    va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}}
+}

diff  --git a/clang/test/Headers/stdargneeds.c b/clang/test/Headers/stdargneeds.c
new file mode 100644
index 00000000000000..7505ff55731f14
--- /dev/null
+++ b/clang/test/Headers/stdargneeds.c
@@ -0,0 +1,91 @@
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c
+// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c
+
+// Split the file so that the "implicitly declaring library function" errors get repeated.
+// Use C89 to verify that __need_ can be used to get types that wouldn't normally be available.
+
+//--- stdargneeds0.c
+static void f(int p, ...) {
+    __gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}}
+    va_list v; // expected-error{{undeclared identifier 'va_list'}}
+    va_start(v, p); // expected-error{{implicitly declaring library function 'va_start'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_start'}} expected-error{{undeclared identifier 'v'}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function 'va_arg'}} expected-error{{expected expression}} expected-error{{use of undeclared identifier 'v'}}
+    va_end(v); // expected-error{{implicitly declaring library function 'va_end'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_end'}} expected-error{{undeclared identifier 'v'}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function '__va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function 'va_copy'}} expected-note{{include the header <stdarg.h> or explicitly provide a declaration for 'va_copy'}} expected-error{{use of undeclared identifier 'g'}} expected-error{{use of undeclared identifier 'v'}}
+}
+
+//--- stdargneeds1.c
+#define __need___va_list
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g;
+    va_list v; // expected-error{{undeclared identifier}}
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+}
+
+//--- stdargneeds2.c
+#define __need_va_list
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g; // expected-error{{undeclared identifier}}
+    va_list v;
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+}
+
+//--- stdargneeds3.c
+#define __need_va_list
+#define __need_va_arg
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g; // expected-error{{undeclared identifier}}
+    va_list v;
+    va_start(v, p);
+    int i = va_arg(v, int);
+    va_end(v);
+    __va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
+}
+
+//--- stdargneeds4.c
+#define __need___va_list
+#define __need_va_list
+#define __need___va_copy
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g;
+    va_list v;
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    __va_copy(g, v);
+    va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+}
+
+//--- stdargneeds5.c
+#define __need___va_list
+#define __need_va_list
+#define __need_va_copy
+#include <stdarg.h>
+static void f(int p, ...) {
+    __gnuc_va_list g;
+    va_list v;
+    va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
+    va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
+    __va_copy(g, v); // expected-error{{implicit declaration of function}}
+    va_copy(g, v);
+}


        


More information about the cfe-commits mailing list