]> granicus.if.org Git - clang/commitdiff
Deduce a ConstantArrayType from a value-dependent initializer list
authorDouglas Gregor <dgregor@apple.com>
Thu, 19 Nov 2009 23:25:22 +0000 (23:25 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 19 Nov 2009 23:25:22 +0000 (23:25 +0000)
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
lib/Sema/SemaInit.cpp
test/SemaTemplate/dependent-sized_array.cpp

index 91b89e7ddeaa33fae7543ef4fc392cf6e11afc18..12bfee7a91d0aba8b8dbdf324a0f5f1e4590c27b 100644 (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);
 }
 
index fbc4680f8f2f071ae7fa522d6f0e64bf985f1a1f..2eba704ff3a3c374285cfa997822230d1ba6fd9a 100644 (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(),
index 77b2bdce30f0d0003672ba3097f7fa11b6a9c7b6..d221a4d276d27ef8128da19927aaf23602cee5f9 100644 (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}}
+}