Deduce a ConstantArrayType from a value-dependent initializer list

rather than punting to a DependentSizedArrayType, tightening up our
type checking for template definitions. Thanks, John!

llvm-svn: 89407
This commit is contained in:
Douglas Gregor 2009-11-19 23:25:22 +00:00
parent 36dd7d5f5c
commit deebf6efab
3 changed files with 43 additions and 9 deletions

View File

@ -640,12 +640,17 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
InitListExpr::InitListExpr(SourceLocation lbraceloc,
Expr **initExprs, unsigned numInits,
SourceLocation rbraceloc)
: Expr(InitListExprClass, QualType(),
hasAnyTypeDependentArguments(initExprs, numInits),
hasAnyValueDependentArguments(initExprs, numInits)),
: Expr(InitListExprClass, QualType(), false, false),
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
UnionFieldInit(0), HadArrayRangeDesignator(false) {
UnionFieldInit(0), HadArrayRangeDesignator(false)
{
for (unsigned I = 0; I != numInits; ++I) {
if (initExprs[I]->isTypeDependent())
TypeDependent = true;
if (initExprs[I]->isValueDependent())
ValueDependent = true;
}
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
}

View File

@ -143,12 +143,34 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
// If the declaration is a non-dependent, incomplete array type
// that has an initializer, then its type will be completed once
// the initializer is instantiated, meaning that the type is
// dependent. Morph the declaration's type into a
// dependently-sized array type.
// the initializer is instantiated.
if (!DeclType->isDependentType()) {
if (const IncompleteArrayType *ArrayT
= Context.getAsIncompleteArrayType(DeclType)) {
if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
if (!ILE->isTypeDependent()) {
// Compute the constant array type from the length of the
// initializer list.
// FIXME: This will be wrong if there are designated
// initializations. Good thing they don't exist in C++!
llvm::APInt NumElements(Context.getTypeSize(Context.getSizeType()),
ILE->getNumInits());
llvm::APInt Zero(Context.getTypeSize(Context.getSizeType()), 0);
if (NumElements == Zero) {
// Sizing an array implicitly to zero is not allowed by ISO C,
// but is supported by GNU.
Diag(ILE->getLocStart(), diag::ext_typecheck_zero_array_size);
}
DeclType = Context.getConstantArrayType(ArrayT->getElementType(),
NumElements,
ArrayT->getSizeModifier(),
ArrayT->getIndexTypeCVRQualifiers());
return false;
}
}
// Make the array type-dependent by making it dependently-sized.
DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(),
/*NumElts=*/0,
ArrayT->getSizeModifier(),

View File

@ -1,4 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s
// RUN: clang-cc -fsyntax-only -pedantic -verify %s
template<int N>
void f() {
@ -8,3 +8,10 @@ void f() {
template void f<17>();
template<int N>
void f1() {
int a0[] = {}; // expected-warning{{zero}}
int a1[] = { 1, 2, 3, N };
int a3[sizeof(a1)/sizeof(int) != 4? 1 : -1]; // expected-error{{negative}}
}