Skip to content

Commit ecadccf

Browse files
authored
merge main into amd-staging (llvm#1204)
2 parents e2c96a0 + f7b3ead commit ecadccf

File tree

100 files changed

+7095
-707
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+7095
-707
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4283,6 +4283,17 @@ the ellipsis. This function initializes the given ``__builtin_va_list`` object.
42834283
It is undefined behavior to call this function on an already initialized
42844284
``__builtin_va_list`` object.
42854285
4286+
* ``void __builtin_c23_va_start(__builtin_va_list list, ...)``
4287+
4288+
A builtin function for the target-specific ``va_start`` function-like macro,
4289+
available only in C23 and later. The builtin accepts zero or one argument for
4290+
the ellipsis (``...``). If such an argument is provided, it should be the name
4291+
of the parameter preceeding the ellipsis, which is used for compatibility with
4292+
C versions before C23. It is an error to provide two or more variadic arguments.
4293+
This function initializes the given ``__builtin_va_list`` object. It is
4294+
undefined behavior to call this function on an already initialized
4295+
``__builtin_va_list`` object.
4296+
42864297
* ``void __builtin_va_end(__builtin_va_list list)``
42874298
42884299
A builtin function for the target-specific ``va_end`` function-like macro. This

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ C2y Feature Support
123123

124124
C23 Feature Support
125125
^^^^^^^^^^^^^^^^^^^
126+
- Added ``__builtin_c23_va_start()`` for compatibility with GCC and to enable
127+
better diagnostic behavior for the ``va_start()`` macro in C23 and later.
128+
This also updates the definition of ``va_start()`` in ``<stdarg.h>`` to use
129+
the new builtin. Fixes #GH124031.
126130

127131
Non-comprehensive list of changes in this release
128132
-------------------------------------------------

clang/include/clang/Basic/Builtins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum LanguageID : uint16_t {
4444
OCL_DSE = 0x400, // builtin requires OpenCL device side enqueue.
4545
ALL_OCL_LANGUAGES = 0x800, // builtin for OCL languages.
4646
HLSL_LANG = 0x1000, // builtin requires HLSL.
47+
C23_LANG = 0x2000, // builtin requires C23 or later.
4748
ALL_LANGUAGES = C_LANG | CXX_LANG | OBJC_LANG, // builtin for all languages.
4849
ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode.
4950
ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode.

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,12 @@ def BuiltinVaStart : Builtin {
833833
let Prototype = "void(__builtin_va_list_ref, ...)";
834834
}
835835

836+
def BuiltinC23VaStart : LangBuiltin<"C23_LANG"> {
837+
let Spellings = ["__builtin_c23_va_start"];
838+
let Attributes = [NoThrow, CustomTypeChecking];
839+
let Prototype = "void(__builtin_va_list_ref, ...)";
840+
}
841+
836842
def BuiltinStdargStart : Builtin {
837843
let Spellings = ["__builtin_stdarg_start"];
838844
let Attributes = [NoThrow, CustomTypeChecking];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10622,6 +10622,9 @@ def warn_second_arg_of_va_start_not_last_non_variadic_param : Warning<
1062210622
def warn_c17_compat_ellipsis_only_parameter : Warning<
1062310623
"'...' as the only parameter of a function is incompatible with C standards "
1062410624
"before C23">, DefaultIgnore, InGroup<CPre23Compat>;
10625+
def warn_c17_compat_va_start_one_arg : Warning<
10626+
"passing only one argument to 'va_start' is incompatible with C standards "
10627+
"before C23">, DefaultIgnore, InGroup<CPre23Compat>;
1062510628
def warn_va_start_type_is_undefined : Warning<
1062610629
"passing %select{an object that undergoes default argument promotion|"
1062710630
"an object of reference type|a parameter declared with the 'register' "

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,9 +2499,9 @@ class Sema final : public SemaBase {
24992499

25002500
void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
25012501

2502-
/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
2503-
/// for validity. Emit an error and return true on failure; return false
2504-
/// on success.
2502+
/// Check the arguments to '__builtin_va_start', '__builtin_ms_va_start',
2503+
/// or '__builtin_c23_va_start' for validity. Emit an error and return true
2504+
/// on failure; return false on success.
25052505
bool BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
25062506
bool BuiltinVAStartARMMicrosoft(CallExpr *Call);
25072507

clang/lib/Basic/Builtins.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ static bool builtinIsSupported(const llvm::StringTable &Strings,
191191
/* consteval Unsupported */
192192
if (!LangOpts.CPlusPlus20 && strchr(AttributesStr.data(), 'G') != nullptr)
193193
return false;
194+
/* C23 unsupported */
195+
if (!LangOpts.C23 && BuiltinInfo.Langs == C23_LANG)
196+
return false;
194197
return true;
195198
}
196199

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3551,6 +3551,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
35513551
case Builtin::BI__builtin_stdarg_start:
35523552
case Builtin::BI__builtin_va_start:
35533553
case Builtin::BI__va_start:
3554+
case Builtin::BI__builtin_c23_va_start:
35543555
case Builtin::BI__builtin_va_end:
35553556
EmitVAStartEnd(BuiltinID == Builtin::BI__va_start
35563557
? EmitScalarExpr(E->getArg(0))

clang/lib/Headers/__stdarg_va_arg.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
#ifndef va_arg
1111

1212
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L
13-
/* C23 does not require the second parameter for va_start. */
14-
#define va_start(ap, ...) __builtin_va_start(ap, 0)
13+
/* C23 uses a special builtin. */
14+
#define va_start(...) __builtin_c23_va_start(__VA_ARGS__)
1515
#else
1616
/* Versions before C23 do require the second parameter. */
1717
#define va_start(ap, param) __builtin_va_start(ap, param)

clang/lib/Sema/SemaChecking.cpp

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
21612161
case Builtin::BI__builtin_ms_va_start:
21622162
case Builtin::BI__builtin_stdarg_start:
21632163
case Builtin::BI__builtin_va_start:
2164+
case Builtin::BI__builtin_c23_va_start:
21642165
if (BuiltinVAStart(BuiltinID, TheCall))
21652166
return ExprError();
21662167
break;
@@ -4844,15 +4845,27 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn,
48444845

48454846
bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
48464847
Expr *Fn = TheCall->getCallee();
4847-
48484848
if (checkVAStartABI(*this, BuiltinID, Fn))
48494849
return true;
48504850

4851-
// In C23 mode, va_start only needs one argument. However, the builtin still
4852-
// requires two arguments (which matches the behavior of the GCC builtin),
4853-
// <stdarg.h> passes `0` as the second argument in C23 mode.
4854-
if (checkArgCount(TheCall, 2))
4855-
return true;
4851+
if (BuiltinID == Builtin::BI__builtin_c23_va_start) {
4852+
// This builtin requires one argument (the va_list), allows two arguments,
4853+
// but diagnoses more than two arguments. e.g.,
4854+
// __builtin_c23_va_start(); // error
4855+
// __builtin_c23_va_start(list); // ok
4856+
// __builtin_c23_va_start(list, param); // ok
4857+
// __builtin_c23_va_start(list, anything, anything); // error
4858+
// This differs from the GCC behavior in that they accept the last case
4859+
// with a warning, but it doesn't seem like a useful behavior to allow.
4860+
if (checkArgCountRange(TheCall, 1, 2))
4861+
return true;
4862+
} else {
4863+
// In C23 mode, va_start only needs one argument. However, the builtin still
4864+
// requires two arguments (which matches the behavior of the GCC builtin),
4865+
// <stdarg.h> passes `0` as the second argument in C23 mode.
4866+
if (checkArgCount(TheCall, 2))
4867+
return true;
4868+
}
48564869

48574870
// Type-check the first argument normally.
48584871
if (checkBuiltinArgument(*this, TheCall, 0))
@@ -4863,23 +4876,34 @@ bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) {
48634876
if (checkVAStartIsInVariadicFunction(*this, Fn, &LastParam))
48644877
return true;
48654878

4866-
// Verify that the second argument to the builtin is the last argument of the
4867-
// current function or method. In C23 mode, if the second argument is an
4868-
// integer constant expression with value 0, then we don't bother with this
4869-
// check.
4870-
bool SecondArgIsLastNamedArgument = false;
4879+
// Verify that the second argument to the builtin is the last non-variadic
4880+
// argument of the current function or method. In C23 mode, if the call is
4881+
// not to __builtin_c23_va_start, and the second argument is an integer
4882+
// constant expression with value 0, then we don't bother with this check.
4883+
// For __builtin_c23_va_start, we only perform the check for the second
4884+
// argument being the last argument to the current function if there is a
4885+
// second argument present.
4886+
if (BuiltinID == Builtin::BI__builtin_c23_va_start &&
4887+
TheCall->getNumArgs() < 2) {
4888+
Diag(TheCall->getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
4889+
return false;
4890+
}
4891+
48714892
const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts();
48724893
if (std::optional<llvm::APSInt> Val =
48734894
TheCall->getArg(1)->getIntegerConstantExpr(Context);
4874-
Val && LangOpts.C23 && *Val == 0)
4895+
Val && LangOpts.C23 && *Val == 0 &&
4896+
BuiltinID != Builtin::BI__builtin_c23_va_start) {
4897+
Diag(TheCall->getExprLoc(), diag::warn_c17_compat_va_start_one_arg);
48754898
return false;
4899+
}
48764900

48774901
// These are valid if SecondArgIsLastNamedArgument is false after the next
48784902
// block.
48794903
QualType Type;
48804904
SourceLocation ParamLoc;
48814905
bool IsCRegister = false;
4882-
4906+
bool SecondArgIsLastNamedArgument = false;
48834907
if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) {
48844908
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) {
48854909
SecondArgIsLastNamedArgument = PV == LastParam;

0 commit comments

Comments
 (0)