diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -425,6 +425,16 @@ ``#pragma clang __debug sloc_usage`` can also be used to request this report. - Clang no longer permits the keyword 'bool' in a concept declaration as a concepts-ts compatibility extension. +- Added ``-Wvla-stack-allocation`` to only give warnings about VLA that need + stack allocation. + + .. code-block:: C + + void f(int n) { + int a[n]; // VLA that needs stack allocation + } + + void g(int n, int a[n]) {} // VLA that don't need stack allocation Non-comprehensive list of changes in this release ------------------------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -827,7 +827,9 @@ def VectorConversion : DiagGroup<"vector-conversion">; // clang specific def VexingParse : DiagGroup<"vexing-parse">; def VLAExtension : DiagGroup<"vla-extension">; -def VLA : DiagGroup<"vla", [VLAExtension]>; +def VLAPortability : DiagGroup<"vla-portability">; +def VLAStackAlloc : DiagGroup<"vla-stack-alloc">; +def VLA : DiagGroup<"vla", [VLAExtension, VLAPortability, VLAStackAlloc]>; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def Visibility : DiagGroup<"visibility">; def ZeroLengthArray : DiagGroup<"zero-length-array">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -131,8 +131,10 @@ // C99 variable-length arrays def ext_vla : Extension<"variable length arrays are a C99 feature">, InGroup; -def warn_vla_used : Warning<"variable length array used">, - InGroup, DefaultIgnore; +def warn_vla_portability : Warning<"variable length array used">, + InGroup, DefaultIgnore; +def warn_vla_stack_alloc : Warning<"variable length array that may require stack allocation used">, + InGroup, DefaultIgnore; def err_vla_in_sfinae : Error< "variable length array cannot be formed during template argument deduction">; def err_array_star_in_function_definition : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7477,6 +7477,9 @@ } } + if (R->isVariableArrayType()) + Diag(D.getIdentifierLoc(), diag::warn_vla_stack_alloc); + // If this variable has a VLA type and an initializer, try to // fold to a constant-sized type. This is otherwise invalid. if (D.hasInitializer() && R->isVariableArrayType()) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2538,7 +2538,7 @@ VLADiag = diag::err_opencl_vla; VLAIsError = true; } else if (getLangOpts().C99) { - VLADiag = diag::warn_vla_used; + VLADiag = diag::warn_vla_portability; VLAIsError = false; } else if (isSFINAEContext()) { VLADiag = diag::err_vla_in_sfinae; diff --git a/clang/test/C/drs/dr3xx.c b/clang/test/C/drs/dr3xx.c --- a/clang/test/C/drs/dr3xx.c +++ b/clang/test/C/drs/dr3xx.c @@ -86,7 +86,9 @@ /* Ensure that a constant array of variable-length arrays are still * considered a variable-length array. */ - vla y[3]; /* expected-warning {{variable length array}} */ + vla y[3]; /* expected-warning {{variable length array}} + expected-warning {{variable length array that may require stack allocation used}} + */ } /* WG14 DR313: yes @@ -153,10 +155,14 @@ typedef int type[dr320_v]; /* c89only-warning {{variable length arrays are a C99 feature}} c99andup-warning {{variable length array used}} */ - extern type bad; /* expected-error {{variable length array declaration cannot have 'extern' linkage}} */ + extern type bad; /* expected-error {{variable length array declaration cannot have 'extern' linkage}} + expected-warning {{variable length array that may require stack allocation used}} + */ /* C99 6.7.5.2p2, second sentence. */ - static type fine; /* expected-error {{variable length array declaration cannot have 'static' storage duration}} */ + static type fine; /* expected-error {{variable length array declaration cannot have 'static' storage duration}} + expected-warning {{variable length array that may require stack allocation used}} + */ } /* WG14 DR321: yes diff --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c --- a/clang/test/Sema/cast.c +++ b/clang/test/Sema/cast.c @@ -2,7 +2,8 @@ int array[(long)(char *)0]; // expected-warning {{variable length array used}} \ // expected-warning {{variable length array folded to constant array as an extension}} \ - // expected-note {{this conversion is not allowed in a constant expression}} + // expected-note {{this conversion is not allowed in a constant expression}} \ + // expected-warning {{variable length array that may require stack allocation used}} typedef struct { unsigned long bits[(((1) + (64) - 1) / (64))]; } cpumask_t; cpumask_t x; diff --git a/clang/test/Sema/warn-vla.c b/clang/test/Sema/warn-vla.c --- a/clang/test/Sema/warn-vla.c +++ b/clang/test/Sema/warn-vla.c @@ -1,12 +1,59 @@ -// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify -Wvla %s -// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify -Wvla %s +// RUN: %clang_cc1 -std=c89 -fsyntax-only -verify=expected,c89 -Wvla %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify=expected,c99 -Wvla %s +// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify=expected,only-stack-allocation -Wvla-stack-alloc -Wno-vla-portability %s void test1(int n) { - int v[n]; // expected-warning {{variable length array}} + int v[n]; /* + c89-warning {{variable length arrays are a C99 feature}} + c89-warning {{variable length array that may require stack allocation used}} + c99-warning {{variable length array used}} + c99-warning {{variable length array that may require stack allocation used}} + only-stack-allocation-warning {{variable length array that may require stack allocation used}} + */ } -void test2(int n, int v[n]) { // expected-warning {{variable length array}} +void test2(int n, int v[n]) { /* + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} +*/ } -void test3(int n, int v[n]); // expected-warning {{variable length array}} +void test3(int n, int v[n]); /* + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} +*/ +int test4_num; +typedef int Test4[test4_num]; /* + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} + expected-error {{variable length array declaration not allowed at file scope}} +*/ + +void func() { + typedef int test5[test4_num]; /* + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} + */ + + int test6[test4_num]; /* + c89-warning {{variable length arrays are a C99 feature}} + c89-warning {{variable length array that may require stack allocation used}} + c99-warning {{variable length array used}} + c99-warning {{variable length array that may require stack allocation used}} + only-stack-allocation-warning {{variable length array that may require stack allocation used}} + */ + + // FIXME: warn twice + (void)sizeof(int[test4_num]); /* + c89-warning {{variable length arrays are a C99 feature}} + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} + c99-warning {{variable length array used}} + */ + + int (*test7)[test4_num]; /* + c89-warning {{variable length arrays are a C99 feature}} + c99-warning {{variable length array used}} + */ +} diff --git a/clang/test/SemaCXX/warn-vla.cpp b/clang/test/SemaCXX/warn-vla.cpp --- a/clang/test/SemaCXX/warn-vla.cpp +++ b/clang/test/SemaCXX/warn-vla.cpp @@ -1,7 +1,10 @@ // RUN: %clang_cc1 -fsyntax-only -verify -Wvla %s void test1(int n) { // expected-note {{here}} - int v[n]; // expected-warning {{variable length array}} expected-note {{parameter 'n'}} + int v[n]; /* expected-warning {{variable length array}} + expected-note {{parameter 'n'}} + expected-warning {{variable length array that may require stack allocation used}} + */ } void test2(int n, int v[n]) { // expected-warning {{variable length array}} expected-note {{parameter 'n'}} expected-note {{here}} @@ -11,7 +14,10 @@ template void test4(int n) { // expected-note {{here}} - int v[n]; // expected-warning {{variable length array}} expected-note {{parameter 'n'}} + int v[n]; /* expected-warning {{variable length array}} + expected-note {{parameter 'n'}} + expected-warning {{variable length array that may require stack allocation used}} + */ } template