зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
865d447ac6
Коммит
73460a32bc
|
@ -640,11 +640,16 @@ OverloadedOperatorKind BinaryOperator::getOverloadedOperator(Opcode Opc) {
|
||||||
InitListExpr::InitListExpr(SourceLocation lbraceloc,
|
InitListExpr::InitListExpr(SourceLocation lbraceloc,
|
||||||
Expr **initExprs, unsigned numInits,
|
Expr **initExprs, unsigned numInits,
|
||||||
SourceLocation rbraceloc)
|
SourceLocation rbraceloc)
|
||||||
: Expr(InitListExprClass, QualType(),
|
: Expr(InitListExprClass, QualType(), false, false),
|
||||||
hasAnyTypeDependentArguments(initExprs, numInits),
|
|
||||||
hasAnyValueDependentArguments(initExprs, numInits)),
|
|
||||||
LBraceLoc(lbraceloc), RBraceLoc(rbraceloc), SyntacticForm(0),
|
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);
|
InitExprs.insert(InitExprs.end(), initExprs, initExprs+numInits);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,12 +143,34 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
|
||||||
|
|
||||||
// If the declaration is a non-dependent, incomplete array type
|
// If the declaration is a non-dependent, incomplete array type
|
||||||
// that has an initializer, then its type will be completed once
|
// that has an initializer, then its type will be completed once
|
||||||
// the initializer is instantiated, meaning that the type is
|
// the initializer is instantiated.
|
||||||
// dependent. Morph the declaration's type into a
|
|
||||||
// dependently-sized array type.
|
|
||||||
if (!DeclType->isDependentType()) {
|
if (!DeclType->isDependentType()) {
|
||||||
if (const IncompleteArrayType *ArrayT
|
if (const IncompleteArrayType *ArrayT
|
||||||
= Context.getAsIncompleteArrayType(DeclType)) {
|
= 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(),
|
DeclType = Context.getDependentSizedArrayType(ArrayT->getElementType(),
|
||||||
/*NumElts=*/0,
|
/*NumElts=*/0,
|
||||||
ArrayT->getSizeModifier(),
|
ArrayT->getSizeModifier(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: clang-cc -fsyntax-only -verify %s
|
// RUN: clang-cc -fsyntax-only -pedantic -verify %s
|
||||||
|
|
||||||
template<int N>
|
template<int N>
|
||||||
void f() {
|
void f() {
|
||||||
|
@ -8,3 +8,10 @@ void f() {
|
||||||
|
|
||||||
template void f<17>();
|
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}}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче