SourceLocation Loc = Brackets.getBegin();
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
- if (RequireCompleteType(Loc, T,
- diag::err_illegal_decl_array_incomplete_type))
- return QualType();
+ // Not in C++, though. There we only dislike void.
+ if (getLangOptions().CPlusPlus) {
+ if (T->isVoidType()) {
+ Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
+ return QualType();
+ }
+ } else {
+ if (RequireCompleteType(Loc, T,
+ diag::err_illegal_decl_array_incomplete_type))
+ return QualType();
+ }
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
} else if (ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
- (!T->isDependentType() && !T->isConstantSizeType())) {
+ (!T->isDependentType() && !T->isIncompleteType() &&
+ !T->isConstantSizeType())) {
// Per C99, a variable array is an array with either a non-constant
// size or an element type that has a non-constant-size
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
} else {
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
// have a value greater than zero.
- if (ConstVal.isSigned()) {
- if (ConstVal.isNegative()) {
- Diag(ArraySize->getLocStart(),
- diag::err_typecheck_negative_array_size)
- << ArraySize->getSourceRange();
- return QualType();
- } else if (ConstVal == 0) {
- // GCC accepts zero sized static arrays.
- Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
- << ArraySize->getSourceRange();
- }
+ if (ConstVal.isSigned() && ConstVal.isNegative()) {
+ Diag(ArraySize->getLocStart(),
+ diag::err_typecheck_negative_array_size)
+ << ArraySize->getSourceRange();
+ return QualType();
+ }
+ if (ConstVal == 0) {
+ // GCC accepts zero sized static arrays.
+ Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
+ << ArraySize->getSourceRange();
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
return false;
// If we have a class template specialization or a class member of a
- // class template specialization, try to instantiate it.
- if (const RecordType *Record = T->getAs<RecordType>()) {
+ // class template specialization, or an array with known size of such,
+ // try to instantiate it.
+ QualType MaybeTemplate = T;
+ if (const ConstantArrayType *Array = T->getAs<ConstantArrayType>())
+ MaybeTemplate = Array->getElementType();
+ if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
--- /dev/null
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+
+// Simple form
+int ar1[10];
+
+// Element type cannot be:
+// - (cv) void
+volatile void ar2[10]; // expected-error {{incomplete element type 'void volatile'}}
+// - a reference
+int& ar3[10]; // expected-error {{array of references}}
+// - a function type
+typedef void Fn();
+Fn ar4[10]; // expected-error {{array of functions}}
+// - an abstract class
+struct Abstract { virtual void fn() = 0; }; // expected-note {{pure virtual}}
+Abstract ar5[10]; // expected-error {{abstract class}}
+
+// If we have a size, it must be greater than zero.
+int ar6[-1]; // expected-error {{array size is negative}}
+int ar7[0u]; // expected-warning {{zero size arrays are an extension}}
+
+// An array with unknown bound is incomplete.
+int ar8[]; // FIXME: This needs to fail!
+// So is an array with an incomplete element type.
+struct Incomplete; // expected-note {{forward declaration}}
+Incomplete ar9[10]; // expected-error {{incomplete type}}
+// Neither of which should be a problem in situations where no complete type
+// is required. (PR5048)
+void fun(int p1[], Incomplete p2[10]);
+extern int ear1[];
+extern Incomplete ear2[10];
+
+// cv migrates to element type
+typedef const int cint;
+extern cint car1[10];
+typedef int intar[10];
+// thus this is a valid redeclaration
+extern const intar car1;
+
+// Check that instantiation works properly when the element type is a template.
+template <typename T> struct S {
+ typename T::type x; // expected-error {{has no members}}
+};
+S<int> ar10[10]; // expected-note {{requested here}}