From: Douglas Gregor
Date: Sun, 23 May 2010 19:57:01 +0000 (+0000)
Subject: It turns out that people love using VLAs in templates, too. Weaken our
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a481ec4150ad203440852a2bfee0883dd26f7530;p=clang
It turns out that people love using VLAs in templates, too. Weaken our
VLA restrictions so that one can use VLAs in templates (even
accidentally), but not as part of a non-type template parameter (which
would be very bad).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104471 91177308-0d34-0410-b5e6-96231b3b80d8
---
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 5b7b0c566c..da7601d0ec 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -41,9 +41,8 @@ def ext_vla : Extension<
"variable length arrays are a C99 feature, accepted as an extension">,
InGroup;
def err_vla_non_pod : Error<"variable length array of non-POD element type %0">;
-def err_vla_in_template : Error<
- "variable length array cannot be used in a template %select{definition|"
- "instantiation}0">;
+def err_vla_in_sfinae : Error<
+ "variable length array cannot be formed during template argument deduction">;
def err_array_star_in_function_definition : Error<
"variable length array must be bound in function definition">;
def err_vla_decl_in_file_scope : Error<
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index a7527e7ccf..1aab65ebec 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -277,6 +277,9 @@ QualType Type::getPointeeType() const {
/// array types and types that contain variable array types in their
/// declarator
bool Type::isVariablyModifiedType() const {
+ // FIXME: We should really keep a "variably modified" bit in Type, rather
+ // than walking the type hierarchy to recompute it.
+
// A VLA is a variably modified type.
if (isVariableArrayType())
return true;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ecac7a212a..307be9d786 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -534,6 +534,14 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam,
/// otherwise, produces a diagnostic and returns a NULL type.
QualType
Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
+ // We don't allow variably-modified types as the type of non-type template
+ // parameters.
+ if (T->isVariablyModifiedType()) {
+ Diag(Loc, diag::err_variably_modified_nontype_template_param)
+ << T;
+ return QualType();
+ }
+
// C++ [temp.param]p4:
//
// A non-type template-parameter shall have one of the following
@@ -553,13 +561,6 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) {
// assume that it is well-formed.
T->isDependentType())
return T;
- // We don't allow variably-modified types as the type of non-type template
- // parameters.
- else if (T->isVariablyModifiedType()) {
- Diag(Loc, diag::err_variably_modified_nontype_template_param)
- << T;
- return QualType();
- }
// C++ [temp.param]p8:
//
// A non-type template-parameter of type "array of T" or
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index b25d076359..ea2b2e6812 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -716,15 +716,11 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
<< Context.getBaseElementType(T);
return QualType();
}
- // Prohibit the use of VLAs in template instantiations, since we don't
- // want them to accidentally be used. This means that we handle VLAs in
- // C-like contexts, but still ban them from C++-specific contexts.
- // And, since we check template definitions early, prohibit them there,
- // too.
- else if (CurContext->isDependentContext() ||
- ActiveTemplateInstantiations.size())
- Diag(Loc, diag::err_vla_in_template)
- << !CurContext->isDependentContext();
+ // Prohibit the use of VLAs during template argument deduction.
+ else if (isSFINAEContext()) {
+ Diag(Loc, diag::err_vla_in_sfinae);
+ return QualType();
+ }
// Just extwarn about VLAs.
else
Diag(Loc, diag::ext_vla);
diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp
index 8a2e35b012..8a9bcb38cb 100644
--- a/test/SemaCXX/c99-variable-length-array.cpp
+++ b/test/SemaCXX/c99-variable-length-array.cpp
@@ -20,10 +20,10 @@ void vla(int N) {
NonPOD2 array4[N][3]; // expected-error{{variable length array of non-POD element type 'NonPOD2'}}
}
-// We disallow VLAs in templates
+/// Warn about VLAs in templates.
template
void vla_in_template(int N, T t) {
- int array1[N]; // expected-error{{variable length array cannot be used in a template definition}}
+ int array1[N]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
}
struct HasConstantValue {
@@ -36,7 +36,7 @@ struct HasNonConstantValue {
template
void vla_in_template(T t) {
- int array2[T::value]; // expected-error{{variable length array cannot be used in a template instantiation}}
+ int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
}
template void vla_in_template(HasConstantValue);
@@ -53,7 +53,8 @@ void inst_with_vla(int N) {
template
struct X1 {
- template // expected-error{{variable length array cannot be used in a template instantiation}}
+ template // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}} \
+ // expected-warning{{variable length arrays are a C99 feature, accepted as an extension}}
struct Inner {
};
diff --git a/www/cxx_compatibility.html b/www/cxx_compatibility.html
index cfe3c0a60c..fe032403d7 100644
--- a/www/cxx_compatibility.html
+++ b/www/cxx_compatibility.html
@@ -53,11 +53,8 @@ compatibility with GNU C and C99 programs:
user-declared constructors or destructors, base classes, or any
members if non-POD type. All C types are POD types.
- Variable length arrays cannot be used in conjunction with
- templates. For example, one cannot use a variable length array
- inside a template or use a variable length array type in a template
- argument.
-
+ Variable length arrays cannot be used as the type of a non-type
+template parameter.
If your code uses variable length arrays in a manner that Clang doesn't support, there are several ways to fix your code: