]> granicus.if.org Git - clang/commitdiff
In some dependent contexts, incomplete array types persist into FinalizeDeclaratorGro...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Sat, 17 Oct 2009 19:37:06 +0000 (19:37 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Sat, 17 Oct 2009 19:37:06 +0000 (19:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84347 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp [new file with mode: 0644]

index 0ec247958c367b72c4196137f32d58101c654ac5..2893abbad205e20d84eb4a088aae69343a52ab13 100644 (file)
@@ -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 <typename... Args> void f(Args... args) {
+        //   int vals[] = { args };
+        // }
+        const IncompleteArrayType *IAT = T->getAs<IncompleteArrayType>();
+        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 (file)
index 0000000..4d0319e
--- /dev/null
@@ -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 <typename T>
+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}}