From 73460a32bc5299a5927d23d2e464d72af796eabf Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 19 Nov 2009 23:25:22 +0000 Subject: [PATCH] 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! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89407 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Expr.cpp | 15 +++++++---- lib/Sema/SemaInit.cpp | 28 ++++++++++++++++++--- test/SemaTemplate/dependent-sized_array.cpp | 9 ++++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 91b89e7dde..12bfee7a91 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index fbc4680f8f..2eba704ff3 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(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(), diff --git a/test/SemaTemplate/dependent-sized_array.cpp b/test/SemaTemplate/dependent-sized_array.cpp index 77b2bdce30..d221a4d276 100644 --- a/test/SemaTemplate/dependent-sized_array.cpp +++ b/test/SemaTemplate/dependent-sized_array.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only -verify %s +// RUN: clang-cc -fsyntax-only -pedantic -verify %s template void f() { @@ -8,3 +8,10 @@ void f() { template void f<17>(); + +template +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}} +}