From: Sebastian Redl Date: Sat, 17 Oct 2009 19:37:06 +0000 (+0000) Subject: In some dependent contexts, incomplete array types persist into FinalizeDeclaratorGro... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d75191f0d100b596281f99ea8f2f0a0d0560d969;p=clang In some dependent contexts, incomplete array types persist into FinalizeDeclaratorGroup. Don't require them to have a complete type. This allows us to compile Hello World with the Apache stdcxx library. If you don't use endl, it even links and runs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84347 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0ec247958c..2893abbad2 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3527,10 +3527,37 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, // Block scope. C99 6.7p7: If an identifier for an object is declared with // no linkage (C99 6.2.2p6), the type for the object shall be complete... if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) { - if (!IDecl->isInvalidDecl() && - RequireCompleteType(IDecl->getLocation(), T, - diag::err_typecheck_decl_incomplete_type)) - IDecl->setInvalidDecl(); + if (T->isDependentType()) { + // If T is dependent, we should not require a complete type. + // (RequireCompleteType shouldn't be called with dependent types.) + // But we still can at least check if we've got an array of unspecified + // size without an initializer. + if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() && + !IDecl->getInit()) { + Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type) + << T; + IDecl->setInvalidDecl(); + } + } else if (!IDecl->isInvalidDecl()) { + // If T is an incomplete array type with an initializer list that is + // dependent on something, its size has not been fixed. We could attempt + // to fix the size for such arrays, but we would still have to check + // here for initializers containing a C++0x vararg expansion, e.g. + // template void f(Args... args) { + // int vals[] = { args }; + // } + const IncompleteArrayType *IAT = T->getAs(); + Expr *Init = IDecl->getInit(); + if (IAT && Init && + (Init->isTypeDependent() || Init->isValueDependent())) { + // Check that the member type of the array is complete, at least. + if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(), + diag::err_typecheck_decl_incomplete_type)) + IDecl->setInvalidDecl(); + } else if (RequireCompleteType(IDecl->getLocation(), T, + diag::err_typecheck_decl_incomplete_type)) + IDecl->setInvalidDecl(); + } } // File scope. C99 6.9.2p2: A declaration of an identifier for an // object that has file scope without an initializer, and without a diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp new file mode 100644 index 0000000000..4d0319e58d --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 -pedantic -Werror %s +int a1[] = { 1, 3, 5 }; +void f() { + int a2[] = { 1, 3, 5 }; +} +template +void tf() { + T t; + // Element type may be dependent + T a3[] = { 1, 3, 5 }; + // As might be the initializer list, value + int a5[] = { sizeof(T) }; + // or even type. + int a6[] = { t.get() }; +} + +// Allowed by GNU extension +int a4[] = {}; // expected-warning {{zero size arrays}}