Skip to content

Commit 723fee6

Browse files
Merge pull request swiftlang#7612 from ian-twilightcoder/stdarg_needs
[cherry-pick stable/20230725] [Headers] Add missing __need_ macros to stdarg.h
2 parents 17f8d66 + 307de33 commit 723fee6

File tree

3 files changed

+165
-15
lines changed

3 files changed

+165
-15
lines changed

clang/lib/Headers/stdarg.h

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,45 @@
77
*===-----------------------------------------------------------------------===
88
*/
99

10-
#ifndef __STDARG_H
10+
#if !defined(__STDARG_H) || defined(__need___va_list) || \
11+
defined(__need_va_list) || defined(__need_va_arg) || \
12+
defined(__need___va_copy) || defined(__need_va_copy)
1113

14+
#if !defined(__need___va_list) && !defined(__need_va_list) && \
15+
!defined(__need_va_arg) && !defined(__need___va_copy) && \
16+
!defined(__need_va_copy)
17+
#define __STDARG_H
18+
#define __need___va_list
19+
#define __need_va_list
20+
#define __need_va_arg
21+
#define __need___va_copy
22+
/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
23+
* or -ansi is not specified, since it was not part of C90.
24+
*/
25+
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
26+
(defined(__cplusplus) && __cplusplus >= 201103L) || \
27+
!defined(__STRICT_ANSI__)
28+
#define __need_va_copy
29+
#endif
30+
#endif
31+
32+
#ifdef __need___va_list
1233
#ifndef __GNUC_VA_LIST
1334
#define __GNUC_VA_LIST
1435
typedef __builtin_va_list __gnuc_va_list;
1536
#endif
16-
17-
#ifdef __need___va_list
1837
#undef __need___va_list
19-
#else
20-
#define __STDARG_H
38+
#endif /* defined(__need___va_list) */
39+
40+
#ifdef __need_va_list
2141
#ifndef _VA_LIST
2242
typedef __builtin_va_list va_list;
2343
#define _VA_LIST
2444
#endif
45+
#undef __need_va_list
46+
#endif /* defined(__need_va_list) */
2547

48+
#ifdef __need_va_arg
2649
/* FIXME: This is using the placeholder dates Clang produces for these macros
2750
in C2x mode; switch to the correct values once they've been published. */
2851
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L
@@ -34,18 +57,17 @@ typedef __builtin_va_list va_list;
3457
#endif
3558
#define va_end(ap) __builtin_va_end(ap)
3659
#define va_arg(ap, type) __builtin_va_arg(ap, type)
60+
#undef __need_va_arg
61+
#endif /* defined(__need_va_arg) */
3762

38-
/* GCC always defines __va_copy, but does not define va_copy unless in c99 mode
39-
* or -ansi is not specified, since it was not part of C90.
40-
*/
63+
#ifdef __need___va_copy
4164
#define __va_copy(d,s) __builtin_va_copy(d,s)
65+
#undef __need___va_copy
66+
#endif /* defined(__need___va_copy) */
4267

43-
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
44-
(defined(__cplusplus) && __cplusplus >= 201103L) || \
45-
!defined(__STRICT_ANSI__)
68+
#ifdef __need_va_copy
4669
#define va_copy(dest, src) __builtin_va_copy(dest, src)
47-
#endif
48-
49-
#endif /* __STDARG_H */
70+
#undef __need_va_copy
71+
#endif /* defined(__need_va_copy) */
5072

51-
#endif /* not __STDARG_H */
73+
#endif

clang/test/Headers/stdarg.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: split-file %s %t
2+
// RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg0.c
3+
// RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg0.c
4+
// RUN: %clang_cc1 -fsyntax-only -verify=c89 -Werror=implicit-function-declaration -std=c89 %t/stdarg1.c
5+
// RUN: %clang_cc1 -fsyntax-only -verify=c99 -Werror=implicit-function-declaration -std=c99 %t/stdarg1.c
6+
7+
// Split the file so that the "implicitly declaring library function" errors get repeated.
8+
9+
//--- stdarg0.c
10+
static void f(int p, ...) {
11+
__gnuc_va_list g; // c89-error{{undeclared identifier '__gnuc_va_list'}} c99-error{{undeclared identifier}}
12+
va_list v; // c89-error{{undeclared identifier 'va_list'}} c99-error{{undeclared identifier}}
13+
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'}} \
14+
c99-error{{call to undeclared library function 'va_start'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
15+
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'}} \
16+
c99-error{{call to undeclared function 'va_arg'}} c99-error{{expected expression}} c99-error{{undeclared identifier}}
17+
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'}} \
18+
c99-error{{call to undeclared library function 'va_end'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}}
19+
__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'}} \
20+
c99-error{{call to undeclared function '__va_copy'}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
21+
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'}} \
22+
c99-error{{call to undeclared library function 'va_copy'}} c99-note{{provide a declaration}} c99-error{{undeclared identifier}} c99-error{{undeclared identifier}}
23+
}
24+
25+
//--- stdarg1.c
26+
// c99-no-diagnostics
27+
28+
#include <stdarg.h>
29+
static void f(int p, ...) {
30+
__gnuc_va_list g;
31+
va_list v;
32+
va_start(v, p);
33+
int i = va_arg(v, int);
34+
va_end(v);
35+
__va_copy(g, v);
36+
va_copy(g, v); // c89-error{{implicitly declaring library function}} c89-note{{provide a declaration}}
37+
}

clang/test/Headers/stdargneeds.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// RUN: split-file %s %t
2+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds0.c
3+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds1.c
4+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds2.c
5+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds3.c
6+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds4.c
7+
// RUN: %clang_cc1 -fsyntax-only -verify -Werror=implicit-function-declaration -std=c89 %t/stdargneeds5.c
8+
9+
// Split the file so that the "implicitly declaring library function" errors get repeated.
10+
// Use C89 to verify that __need_ can be used to get types that wouldn't normally be available.
11+
12+
//--- stdargneeds0.c
13+
static void f(int p, ...) {
14+
__gnuc_va_list g; // expected-error{{undeclared identifier '__gnuc_va_list'}}
15+
va_list v; // expected-error{{undeclared identifier 'va_list'}}
16+
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'}}
17+
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'}}
18+
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'}}
19+
__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'}}
20+
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'}}
21+
}
22+
23+
//--- stdargneeds1.c
24+
#define __need___va_list
25+
#include <stdarg.h>
26+
static void f(int p, ...) {
27+
__gnuc_va_list g;
28+
va_list v; // expected-error{{undeclared identifier}}
29+
va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
30+
int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}} expected-error{{undeclared identifier}}
31+
va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
32+
__va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
33+
va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
34+
}
35+
36+
//--- stdargneeds2.c
37+
#define __need_va_list
38+
#include <stdarg.h>
39+
static void f(int p, ...) {
40+
__gnuc_va_list g; // expected-error{{undeclared identifier}}
41+
va_list v;
42+
va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
43+
int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
44+
va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
45+
__va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
46+
va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
47+
}
48+
49+
//--- stdargneeds3.c
50+
#define __need_va_list
51+
#define __need_va_arg
52+
#include <stdarg.h>
53+
static void f(int p, ...) {
54+
__gnuc_va_list g; // expected-error{{undeclared identifier}}
55+
va_list v;
56+
va_start(v, p);
57+
int i = va_arg(v, int);
58+
va_end(v);
59+
__va_copy(g, v); // expected-error{{implicit declaration of function}} expected-error{{undeclared identifier}}
60+
va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}} expected-error{{undeclared identifier}}
61+
}
62+
63+
//--- stdargneeds4.c
64+
#define __need___va_list
65+
#define __need_va_list
66+
#define __need___va_copy
67+
#include <stdarg.h>
68+
static void f(int p, ...) {
69+
__gnuc_va_list g;
70+
va_list v;
71+
va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
72+
int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
73+
va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
74+
__va_copy(g, v);
75+
va_copy(g, v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
76+
}
77+
78+
//--- stdargneeds5.c
79+
#define __need___va_list
80+
#define __need_va_list
81+
#define __need_va_copy
82+
#include <stdarg.h>
83+
static void f(int p, ...) {
84+
__gnuc_va_list g;
85+
va_list v;
86+
va_start(v, p); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
87+
int i = va_arg(v, int); // expected-error{{implicit declaration of function}} expected-error{{expected expression}}
88+
va_end(v); // expected-error{{implicitly declaring library function}} expected-note{{provide a declaration}}
89+
__va_copy(g, v); // expected-error{{implicit declaration of function}}
90+
va_copy(g, v);
91+
}

0 commit comments

Comments
 (0)