]> granicus.if.org Git - clang/commitdiff
Finish getting "array-init.c" to work properly.
authorSteve Naroff <snaroff@apple.com>
Mon, 3 Sep 2007 01:24:23 +0000 (01:24 +0000)
committerSteve Naroff <snaroff@apple.com>
Mon, 3 Sep 2007 01:24:23 +0000 (01:24 +0000)
Array scalar initialization is now is reasonable shape.

Next step, structure and array of structure initializers.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41681 91177308-0d34-0410-b5e6-96231b3b80d8

Sema/Sema.h
Sema/SemaDecl.cpp
Sema/SemaExpr.cpp
include/clang/Basic/DiagnosticKinds.def
test/Sema/array-init.c

index a741657bf6f024d8da2330eda60e8f5d4cb475c1..0979c607a0daf5bad2639aae674150fb30601154 100644 (file)
@@ -442,10 +442,11 @@ private:
                                    IdentifierInfo &Comp, SourceLocation CmpLoc);
   
   /// type checking declaration initializers (C99 6.7.8)
-  QualType CheckInitializer(Expr *simpleInit_or_initList, QualType declType,
-                            bool isStatic);
+  bool CheckInitializer(Expr *simpleInit_or_initList, QualType &declType,
+                        bool isStatic);
   bool CheckSingleInitializer(Expr *simpleInit, QualType declType);
-  bool CheckInitList(InitListExpr *IList, QualType DType, bool isStatic);
+  void CheckInitList(InitListExpr *IList, QualType DType, bool isStatic,
+                     int &nInitializers, int maxElements, bool &hadError);
   
   /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
   /// the specified width and sign.  If an overflow occurs, detect it and emit
index c2f03a373c5686f8c89aeb194ca242bb17f2372a..15fe7c1033e424f5027c00b4b7133f265d95008d 100644 (file)
@@ -289,15 +289,17 @@ bool Sema::CheckSingleInitializer(Expr *Init, QualType DeclType) {
   return false;
 }
 
-bool Sema::CheckInitList(InitListExpr *IList, QualType DType, bool isStatic) {
-  bool hadError = false;
+void Sema::CheckInitList(InitListExpr *IList, QualType DType, 
+                         bool isStatic, int &nInitializers, int maxElements,
+                         bool &hadError) {
   for (unsigned i = 0; i < IList->getNumInits(); i++) {
     Expr *expr = IList->getInit(i);
     
     if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr))
-      CheckInitList(InitList, DType, isStatic);
+      CheckInitList(InitList, DType, isStatic, nInitializers, maxElements,
+                    hadError);
     else {
-      SourceLocation loc;
+      SourceLocation loc = expr->getLocStart();
 
       if (isStatic && !expr->isConstantExpr(Context, &loc)) { // C99 6.7.8p4.
         Diag(loc, diag::err_init_element_not_constant, expr->getSourceRange());
@@ -305,41 +307,71 @@ bool Sema::CheckInitList(InitListExpr *IList, QualType DType, bool isStatic) {
       } else if (CheckSingleInitializer(expr, DType)) {
         hadError = true; // types didn't match.
       }
+      // Does the element fit?
+      nInitializers++;
+      if ((maxElements >= 0) && (nInitializers > maxElements))
+        Diag(loc, diag::warn_excess_initializers, expr->getSourceRange());
     }
   }
-  return hadError;
+  return;
 }
 
-QualType Sema::CheckInitializer(Expr *Init, QualType DeclType, bool isStatic) {
+bool Sema::CheckInitializer(Expr *Init, QualType &DeclType, bool isStatic) {
   InitListExpr *InitList = dyn_cast<InitListExpr>(Init);
-  if (!InitList) {
-    return CheckSingleInitializer(Init, DeclType) ? QualType() : DeclType;
-  }
+  if (!InitList)
+    return CheckSingleInitializer(Init, DeclType);
+
   // We have an InitListExpr, make sure we set the type.
   Init->setType(DeclType);
+
+  bool hadError = false;
+  int nInits = 0;
   
   // C99 6.7.8p3: The type of the entity to be initialized shall be an array
   // of unknown size ("[]") or an object type that is not a variable array type.
   if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) { 
     Expr *expr = VAT->getSizeExpr();
-    if (expr) { 
-      Diag(expr->getLocStart(), diag::err_variable_object_no_init, 
-           expr->getSourceRange());
-      return QualType();
+    if (expr)
+      return Diag(expr->getLocStart(), diag::err_variable_object_no_init, 
+                  expr->getSourceRange());
+
+    // We have a VariableArrayType with unknown size.
+    QualType ElmtType = VAT->getElementType();
+    
+    // If we have a multi-dimensional array, navigate to the base type.
+    while ((VAT = ElmtType->getAsVariableArrayType())) {
+      ElmtType = VAT->getElementType();
+    }
+    CheckInitList(InitList, ElmtType, isStatic, nInits, -1, hadError);
+    
+    if (!hadError) {
+      // Return a new array type from the number of initializers (C99 6.7.8p22).
+      llvm::APSInt ConstVal(32);
+      ConstVal = nInits;
+      DeclType = Context.getConstantArrayType(ElmtType, ConstVal, 
+                                              ArrayType::Normal, 0);
     }
+    return hadError;
   }
-  if (const ArrayType *Ary = DeclType->getAsArrayType()) {
-    // We have a ConstantArrayType or VariableArrayType with unknown size.
-    QualType ElmtType = Ary->getElementType();
+  if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
+    QualType ElmtType = CAT->getElementType();
+    unsigned numElements = CAT->getSize().getZExtValue();
     
-    // If we have a multi-dimensional array, navigate to the base type.
-    while ((Ary = ElmtType->getAsArrayType()))
-      ElmtType = Ary->getElementType();
-
-    CheckInitList(InitList, ElmtType, isStatic);
+    // If we have a multi-dimensional array, navigate to the base type. Also
+    // compute the absolute size of the array, so we can detect excess elements.
+    while ((CAT = ElmtType->getAsConstantArrayType())) {
+      ElmtType = CAT->getElementType();
+      numElements *= CAT->getSize().getZExtValue();
+    }
+    CheckInitList(InitList, ElmtType, isStatic, nInits, numElements, hadError);
+    return hadError;
+  }
+  if (DeclType->isScalarType()) { // C99 6.7.8p11
+    CheckInitList(InitList, DeclType, isStatic, nInits, 1, hadError);
+    return hadError;
   }
   // FIXME: Handle struct/union types.
-  return DeclType;
+  return hadError;
 }
 
 Sema::DeclTy *
index 8788c2f9dce71b0c708ceeb05043e6010dc87f9c..55b6d600c4e2708e84d27e7512282519f4c8793a 100644 (file)
@@ -644,10 +644,8 @@ ParseInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
               SourceLocation RBraceLoc) {
   Expr **InitList = reinterpret_cast<Expr**>(initlist);
 
-  // FIXME: add semantic analysis (C99 6.7.8). This involves 
-  // knowledge of the object being intialized. As a result, the code for
-  // doing the semantic analysis will likely be located elsewhere (i.e. in 
-  // consumers of InitListExpr (e.g. ParseDeclarator, ParseCompoundLiteral).
+  // Semantic analysis for initializers is done by ParseDeclarator() and
+  // CheckInitializer() - it requires knowledge of the object being intialized. 
   
   InitListExpr *e = new InitListExpr(LBraceLoc, InitList, NumInit, RBraceLoc);
   e->setType(Context.VoidTy); // FIXME: just a place holder for now.
index e396d95b55cfd1c24bcfdcbbfc1a52d73a49c68e..85ed51bd7980e202bd56a8c17da30ec8aa8bf4fc 100644 (file)
@@ -550,6 +550,8 @@ DIAG(warn_extern_init, WARNING,
      "'extern' variable has an initializer")
 DIAG(err_variable_object_no_init, ERROR,
      "variable-sized object may not be initialized")
+DIAG(warn_excess_initializers, WARNING,
+     "excess elements in array initializer")
 
 DIAG(err_redefinition_of_label, ERROR,
      "redefinition of label '%0'")
index 209b73463adc863ace22331d4b0822f80a8caa8f..20daa458384494e81f44669480f3fcbb35bb60ec 100644 (file)
@@ -7,16 +7,16 @@ int ary2[] = { x, y, z }; // expected-error{{initializer element is not constant
 
 extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}}
 
-static int ary3[] = { 1, "abc", 3 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}}
+static int ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible types assigning 'char *' to 'int'}}
 
 void func() {
   int x = 1;
 
-  //int x2[] = { 1, 3, 5 };
+  int xComputeSize[] = { 1, 3, 5 };
 
   int x3[x] = { 1, 2 }; // expected-error{{variable-sized object may not be initialized}}
 
-  int x4 = { 1, 2 }; // gcc-warning {{excess elements in array initializer}}
+  int x4 = { 1, 2 }; // // expected-warning{{excess elements in array initializer}}
 
   int y[4][3] = { 
     { 1, 3, 5 },
@@ -28,6 +28,14 @@ void func() {
     1, 3, 5, 2, 4, 6, 3, 5, 7
   };
 
+  int y3[4][3] = {  
+    { 1, 3, 5 },
+    { 2, 4, 6 },
+    { 3, 5, 7 },
+    { 4, 6, 8 },
+    { 5 }, // expected-warning{{excess elements in array initializer}}
+  };
+
   struct threeElements {
     int a,b,c;
   } z = { 1 };