Skip to content

[cherry-pick stable/20230725] [Headers] Add missing __need_ macros to stdarg.h #7612

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 37 additions & 15 deletions clang/lib/Headers/stdarg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
/* FIXME: This is using the placeholder dates Clang produces for these macros
in C2x mode; switch to the correct values once they've been published. */
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L
Expand All @@ -34,18 +57,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
37 changes: 37 additions & 0 deletions clang/test/Headers/stdarg.c
Original file line number Diff line number Diff line change
@@ -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}}
}
91 changes: 91 additions & 0 deletions clang/test/Headers/stdargneeds.c
Original file line number Diff line number Diff line change
@@ -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);
}