[cfe-commits] r46339 - in /cfe/trunk: Sema/Sema.h Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/array-init.c

Steve Naroff snaroff at apple.com
Thu Jan 24 16:51:06 PST 2008


Author: snaroff
Date: Thu Jan 24 18:51:06 2008
New Revision: 46339

URL: http://llvm.org/viewvc/llvm-project?rev=46339&view=rev
Log:

Replace Sema::CheckVariableInitList, CheckConstantInitList, and CheckForCharArrayInitializer with CheckInitializerListTypes. The new routine now supports struct/union initializers.

This is a modified version of a patch by Eli Friedman. This version passes all of the clang tests and supports vectors:-)

Note that Eli and I are still unsatisfied the implementation of CheckInitializerListTypes(). We'd like to find a more elegant implementation. Nevertheless, this is a complex part of the standard (and may be hard to simplify). Since the complexity is localized to this routine, we can iterate without too much disruption:-)


Modified:
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/test/Sema/array-init.c

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=46339&r1=46338&r2=46339&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Thu Jan 24 18:51:06 2008
@@ -740,16 +740,8 @@
   bool CheckSingleInitializer(Expr *&simpleInit, QualType declType);
   bool CheckInitExpr(Expr *expr, InitListExpr *IList, unsigned slot,
                      QualType ElementType);
-                     
-  void CheckVariableInitList(QualType DeclType, InitListExpr *IList, 
-                             QualType ElementType,
-                             int &nInitializers, bool &hadError);
-  void CheckConstantInitList(QualType DeclType, InitListExpr *IList, 
-                             QualType ElementType,
-                             int &nInitializers, bool &hadError);
-  bool CheckForCharArrayInitializer(InitListExpr *IList, QualType ElementType,
-                                    int &nInitializers, bool isConstant,
-                                    bool &hadError);
+  bool CheckInitializerListTypes(InitListExpr*& IList, QualType &DeclType,
+								 bool topLevel, unsigned& startIndex);
   bool CheckForConstantInitializer(Expr *e, QualType t);
   
   StringLiteral *IsStringLiteralInit(Expr *Init, QualType DeclType);

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=46339&r1=46338&r2=46339&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Thu Jan 24 18:51:06 2008
@@ -376,140 +376,6 @@
   return false;
 }
 
-void Sema::CheckVariableInitList(QualType DeclType, InitListExpr *IList, 
-                                 QualType ElementType,
-                                 int &nInitializers, bool &hadError) {
-  unsigned numInits = IList->getNumInits();
-
-  if (numInits) {
-    if (CheckForCharArrayInitializer(IList, ElementType, nInitializers,
-                                     false, hadError))
-      return;
-        
-    for (unsigned i = 0; i < numInits; i++) {
-      Expr *expr = IList->getInit(i);
-    
-      if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
-        if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
-          int maxElements = CAT->getMaximumElements();
-          CheckConstantInitList(DeclType, InitList, ElementType,
-                                maxElements, hadError);
-        }
-      } else {
-        hadError = CheckInitExpr(expr, IList, i, ElementType);
-      }
-      nInitializers++;
-    }
-  } else {
-    Diag(IList->getLocStart(),
-         diag::err_at_least_one_initializer_needed_to_size_array);
-    hadError = true;
-  }
-}
-
-bool Sema::CheckForCharArrayInitializer(InitListExpr *IList, 
-                                        QualType ElementType,
-                                        int &nInitializers, bool isConstant,
-                                        bool &hadError)
-{
-  if (ElementType->isPointerType())
-    return false;
-  
-  if (StringLiteral *literal = dyn_cast<StringLiteral>(IList->getInit(0))) {
-    // FIXME: Handle wide strings
-    if (ElementType->isCharType()) {
-      if (isConstant) {
-        if (literal->getByteLength() > (unsigned)nInitializers) {
-          Diag(literal->getSourceRange().getBegin(),
-               diag::warn_initializer_string_for_char_array_too_long,
-               literal->getSourceRange());
-        }
-      } else {
-        nInitializers = literal->getByteLength() + 1;
-      }
-    } else {
-      // FIXME: It might be better if we could point to the declaration
-      // here, instead of the string literal.
-      Diag(literal->getSourceRange().getBegin(), 
-           diag::array_of_wrong_type_initialized_from_string,
-           ElementType.getAsString());
-      hadError = true;
-    }
-    
-    // Check for excess initializers
-    for (unsigned i = 1; i < IList->getNumInits(); i++) {
-      Expr *expr = IList->getInit(i);
-      Diag(expr->getLocStart(), 
-           diag::err_excess_initializers_in_char_array_initializer, 
-           expr->getSourceRange());
-    }
-    
-    return true;
-  }
-
-  return false;
-}
-
-// FIXME: Doesn't deal with arrays of structures yet.
-void Sema::CheckConstantInitList(QualType DeclType, InitListExpr *IList, 
-                                 QualType ElementType,
-                                 int &totalInits, bool &hadError) {
-  int maxElementsAtThisLevel = 0;
-  int nInitsAtLevel = 0;
-
-  if (ElementType->isRecordType()) // FIXME: until we support structures...
-    return;
-    
-  if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
-    // We have a constant array type, compute maxElements *at this level*.
-    maxElementsAtThisLevel = CAT->getMaximumElements();
-    // Set DeclType, used below to recurse (for multi-dimensional arrays).
-    DeclType = CAT->getElementType();
-  } else if (DeclType->isScalarType()) {
-    if (const VectorType *VT = DeclType->getAsVectorType())
-      maxElementsAtThisLevel = VT->getNumElements();
-    else {
-      Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init, 
-           IList->getSourceRange());
-      maxElementsAtThisLevel = 1;
-    }
-  } 
-  // The empty init list "{ }" is treated specially below.
-  unsigned numInits = IList->getNumInits();
-  if (numInits) {
-    if (CheckForCharArrayInitializer(IList, ElementType, 
-                                     maxElementsAtThisLevel,
-                                     true, hadError))
-      return;
-    
-    for (unsigned i = 0; i < numInits; i++) {
-      Expr *expr = IList->getInit(i);
-      
-      if (InitListExpr *InitList = dyn_cast<InitListExpr>(expr)) {
-        CheckConstantInitList(DeclType, InitList, ElementType, 
-                              totalInits, hadError);
-      } else {
-        hadError = CheckInitExpr(expr, IList, i, ElementType);
-        nInitsAtLevel++; // increment the number of initializers at this level.
-        totalInits--;    // decrement the total number of initializers.
-        
-        // Check if we have space for another initializer.
-        if (((nInitsAtLevel > maxElementsAtThisLevel) || (totalInits < 0)))
-          Diag(expr->getLocStart(), diag::warn_excess_initializers, 
-               expr->getSourceRange());
-      }
-    }
-    if (nInitsAtLevel < maxElementsAtThisLevel) // fill the remaining elements.
-      totalInits -= (maxElementsAtThisLevel - nInitsAtLevel);
-  } else { 
-    // we have an initializer list with no elements.
-    totalInits -= maxElementsAtThisLevel;
-    if (totalInits < 0)
-      Diag(IList->getLocStart(), diag::warn_excess_initializers, 
-           IList->getSourceRange());
-  }
-}
-
 bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
   if (const VariableArrayType *VAT = DeclT->getAsIncompleteArrayType()) {
     // C99 6.7.8p14. We have an array of character type with unknown size 
@@ -535,16 +401,199 @@
 }
 
 StringLiteral *Sema::IsStringLiteralInit(Expr *Init, QualType DeclType) {
-  StringLiteral *strLiteral = dyn_cast<StringLiteral>(Init);
   const ArrayType *AT = DeclType->getAsArrayType();
-  if (strLiteral && (AT && AT->getElementType()->isCharType()))
-    return strLiteral;
+  if (AT && AT->getElementType()->isCharType()) {
+    return dyn_cast<StringLiteral>(Init);
+  }
   return 0;
 }
 
-bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
+// CheckInitializerListTypes - Checks the types of elements of an initializer
+// list. This function is recursive: it calls itself to initialize subelements
+// of aggregate types.  Note that the topLevel parameter essentially refers to
+// whether this expression "owns" the initializer list passed in, or if this
+// initialization is taking elements out of a parent initializer.  Each
+// call to this function adds zero or more to startIndex, reports any errors,
+// and returns true if it found any inconsistent types.
+bool Sema::CheckInitializerListTypes(InitListExpr*& IList, QualType &DeclType,
+                                     bool topLevel, unsigned& startIndex) {
   bool hadError = false;
-  
+
+  if (DeclType->isScalarType()) {
+    // The simplest case: initializing a single scalar
+    if (topLevel) {
+      Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init, 
+           IList->getSourceRange());
+    }
+    if (startIndex < IList->getNumInits()) {
+      Expr* expr = IList->getInit(startIndex);
+      if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+        // FIXME: Should an error be reported here instead?
+        unsigned newIndex = 0;
+        CheckInitializerListTypes(SubInitList, DeclType, true, newIndex);
+      } else {
+        hadError |= CheckInitExpr(expr, IList, startIndex, DeclType);
+      }
+      ++startIndex;
+    }
+    // FIXME: Should an error be reported for empty initializer list + scalar?
+  } else if (DeclType->isVectorType()) {
+    if (startIndex < IList->getNumInits()) {
+      const VectorType *VT = DeclType->getAsVectorType();
+      int maxElements = VT->getNumElements();
+      QualType elementType = VT->getElementType();
+      
+      for (int i = 0; i < maxElements; ++i) {
+        // Don't attempt to go past the end of the init list
+        if (startIndex >= IList->getNumInits())
+          break;
+        Expr* expr = IList->getInit(startIndex);
+        if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+          unsigned newIndex = 0;
+          hadError |= CheckInitializerListTypes(SubInitList, elementType, 
+                                                true, newIndex);
+          ++startIndex;
+        } else {
+          hadError |= CheckInitializerListTypes(IList, elementType, 
+                                                false, startIndex);
+        }
+      }
+    }
+  } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
+    if (DeclType->isStructureType() || DeclType->isUnionType()) {
+      if (startIndex < IList->getNumInits() &&
+          Context.typesAreCompatible(IList->getInit(startIndex)->getType(), DeclType)) {
+        // We found a compatible struct; per the standard, this initializes the
+        // struct.  (The C standard technically says that this only applies for
+        // initializers for declarations with automatic scope; however, this
+        // construct is unambiguous anyway because a struct cannot contain
+        // a type compatible with itself. We'll output an error when we check
+        // if the initializer is constant.)
+        // FIXME: Is a call to CheckSingleInitializer required here?
+        ++startIndex;
+      } else {
+        RecordDecl* structDecl = DeclType->getAsRecordType()->getDecl();
+        // If structDecl is a forward declaration, this loop won't do anything;
+        // That's okay, because an error should get printed out elsewhere. It
+        // might be worthwhile to skip over the rest of the initializer, though.
+        int numMembers = structDecl->getNumMembers() -
+                         structDecl->hasFlexibleArrayMember();
+        for (int i = 0; i < numMembers; i++) {
+          // Don't attempt to go past the end of the init list
+          if (startIndex >= IList->getNumInits())
+            break;
+          FieldDecl * curField = structDecl->getMember(i);
+          if (!curField->getIdentifier()) {
+            // Don't initialize unnamed fields, e.g. "int : 20;"
+            continue;
+          }
+          QualType fieldType = curField->getType();
+          Expr* expr = IList->getInit(startIndex);
+          if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+            unsigned newStart = 0;
+            hadError |= CheckInitializerListTypes(SubInitList, fieldType, 
+                                                  true, newStart);
+            ++startIndex;
+          } else {
+            hadError |= CheckInitializerListTypes(IList, fieldType, 
+                                                  false, startIndex);
+          }
+          if (DeclType->isUnionType())
+            break;
+        }
+        // FIXME: Implement flexible array initialization GCC extension (it's a 
+        // really messy extension to implement, unfortunately...the necessary
+        // information isn't actually even here!)
+      }
+    } else if (DeclType->isArrayType()) {
+      // Check for the special-case of initializing an array with a string.
+      if (startIndex < IList->getNumInits()) {
+        if (StringLiteral *lit = IsStringLiteralInit(IList->getInit(startIndex), 
+                                                     DeclType)) {
+          CheckStringLiteralInit(lit, DeclType);
+          ++startIndex;
+          if (topLevel && startIndex < IList->getNumInits()) {
+            // We have leftover initializers; warn
+            Diag(IList->getInit(startIndex)->getLocStart(), 
+                 diag::err_excess_initializers_in_char_array_initializer, 
+                 IList->getInit(startIndex)->getSourceRange());
+          }
+          return false;
+        }
+      }
+      int maxElements;
+      if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
+        // FIXME: use a proper constant
+        maxElements = 0x7FFFFFFF;
+        // Check for VLAs; in standard C it would be possible to check this
+        // earlier, but I don't know where clang accepts VLAs (gcc accepts
+        // them in all sorts of strange places).
+        if (const Expr *expr = VAT->getSizeExpr()) {
+          Diag(expr->getLocStart(), diag::err_variable_object_no_init,
+               expr->getSourceRange());
+          hadError = true;
+        }
+      } else {
+        const ConstantArrayType *CAT = DeclType->getAsConstantArrayType();
+        maxElements = static_cast<int>(CAT->getSize().getZExtValue());
+      }
+      QualType elementType = DeclType->getAsArrayType()->getElementType();
+      int numElements = 0;
+      for (int i = 0; i < maxElements; ++i, ++numElements) {
+        // Don't attempt to go past the end of the init list
+        if (startIndex >= IList->getNumInits())
+          break;
+        Expr* expr = IList->getInit(startIndex);
+        if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) {
+          unsigned newIndex = 0;
+          hadError |= CheckInitializerListTypes(SubInitList, elementType, 
+                                                true, newIndex);
+          ++startIndex;
+        } else {
+          hadError |= CheckInitializerListTypes(IList, elementType, 
+                                                false, startIndex);
+        }
+      }
+      if (DeclType->getAsVariableArrayType()) {
+        // If this is an incomplete array type, the actual type needs to
+        // be calculated here
+        if (numElements == 0) {
+          // Sizing an array implicitly to zero is not allowed
+          // (It could in theory be allowed, but it doesn't really matter.)
+          Diag(IList->getLocStart(),
+               diag::err_at_least_one_initializer_needed_to_size_array);
+          hadError = true;
+        } else {
+          llvm::APSInt ConstVal(32);
+          ConstVal = numElements;
+          DeclType = Context.getConstantArrayType(elementType, ConstVal, 
+                                                  ArrayType::Normal, 0);
+        }
+      }
+    } else {
+      assert(0 && "Aggregate that isn't a function or array?!");
+    }
+  } else {
+    // In C, all types are either scalars or aggregates, but
+    // additional handling is needed here for C++ (and possibly others?). 
+    assert(0 && "Unsupported initializer type");
+  }
+
+  // If this init list is a base list, we set the type; an initializer doesn't
+  // fundamentally have a type, but this makes the ASTs a bit easier to read
+  if (topLevel)
+    IList->setType(DeclType);
+
+  if (topLevel && startIndex < IList->getNumInits()) {
+    // We have leftover initializers; warn
+    Diag(IList->getInit(startIndex)->getLocStart(), 
+         diag::warn_excess_initializers, 
+         IList->getInit(startIndex)->getSourceRange());
+  }
+  return hadError;
+}
+
+bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {  
   // 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->getAsVariablyModifiedType())
@@ -559,53 +608,8 @@
       return CheckStringLiteralInit(strLiteral, DeclType);
     return CheckSingleInitializer(Init, DeclType);
   }
-  // We have an InitListExpr, make sure we set the type.
-  Init->setType(DeclType);
-
-  // 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->getAsIncompleteArrayType()) { 
-
-    // We have a VariableArrayType with unknown size. Note that only the first
-    // array can have unknown size. For example, "int [][]" is illegal.
-    int numInits = 0;
-    CheckVariableInitList(VAT->getElementType(), InitList, VAT->getBaseType(), 
-                          numInits, hadError);
-    llvm::APSInt ConstVal(32);
-    
-    if (!hadError)
-      ConstVal = numInits;
-    
-    // Return a new array type from the number of initializers (C99 6.7.8p22).
-
-    // Note that if there was an error, we will still set the decl type,
-    // to an array type with 0 elements. 
-    // This is to avoid "incomplete type foo[]" errors when we've already
-    // reported the real cause of the error.
-    DeclType = Context.getConstantArrayType(VAT->getElementType(), ConstVal, 
-                                            ArrayType::Normal, 0);      
-    return hadError;
-  }
-  if (const ConstantArrayType *CAT = DeclType->getAsConstantArrayType()) {
-    int maxElements = CAT->getMaximumElements();
-    CheckConstantInitList(DeclType, InitList, CAT->getBaseType(), 
-                          maxElements, hadError);
-    return hadError;
-  }
-  if (const VectorType *VT = DeclType->getAsVectorType()) {
-    int maxElements = VT->getNumElements();
-    CheckConstantInitList(DeclType, InitList, VT->getElementType(),
-                          maxElements, hadError);
-    return hadError;
-  }
-  if (DeclType->isScalarType()) { // C99 6.7.8p11: Allow "int x = { 1, 2 };"
-    int maxElements = 1;
-    CheckConstantInitList(DeclType, InitList, DeclType, maxElements, hadError);
-    return hadError;
-  }
-  // FIXME: Handle struct/union types, including those appearing in a 
-  // CompoundLiteralExpr...
-  return hadError;
+  unsigned newIndex = 0;
+  return CheckInitializerListTypes(InitList, DeclType, true, newIndex);
 }
 
 Sema::DeclTy *
@@ -784,7 +788,8 @@
       Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
       BVD->setInvalidDecl();
     } else if (!BVD->isInvalidDecl()) {
-      CheckInitializerTypes(Init, DclT);
+      if (CheckInitializerTypes(Init, DclT))
+        BVD->setInvalidDecl();
       if (SC == VarDecl::Static) // C99 6.7.8p4.
         CheckForConstantInitializer(Init, DclT);
     }
@@ -792,7 +797,8 @@
     if (FVD->getStorageClass() == VarDecl::Extern)
       Diag(VDecl->getLocation(), diag::warn_extern_init);
     if (!FVD->isInvalidDecl())
-      CheckInitializerTypes(Init, DclT);
+      if (CheckInitializerTypes(Init, DclT))
+        FVD->setInvalidDecl();
     
     // C99 6.7.8p4. All file scoped initializers need to be constant.
     CheckForConstantInitializer(Init, DclT);

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=46339&r1=46338&r2=46339&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Thu Jan 24 18:51:06 2008
@@ -628,8 +628,6 @@
      "zero size arrays are an extension")
 DIAG(err_at_least_one_initializer_needed_to_size_array, ERROR,
     "at least one initializer value required to size array")
-DIAG(array_of_wrong_type_initialized_from_string, ERROR,
-    "array of wrong type '%0' initialized from string constant")
 DIAG(err_array_size_non_int, ERROR,
      "size of array has non-integer type '%0'")
 DIAG(err_init_element_not_constant, ERROR,
@@ -640,7 +638,7 @@
      "'extern' variable has an initializer")
 DIAG(err_variable_object_no_init, ERROR,
      "variable-sized object may not be initialized")
-DIAG(warn_excess_initializers, EXTENSION,
+DIAG(warn_excess_initializers, WARNING,
      "excess elements in array initializer")
 DIAG(err_excess_initializers_in_char_array_initializer, ERROR,
     "excess elements in char array initializer")

Modified: cfe/trunk/test/Sema/array-init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-init.c?rev=46339&r1=46338&r2=46339&view=diff

==============================================================================
--- cfe/trunk/test/Sema/array-init.c (original)
+++ cfe/trunk/test/Sema/array-init.c Thu Jan 24 18:51:06 2008
@@ -66,7 +66,7 @@
     { 1, 3, 5, 2 }, // expected-warning{{excess elements in array initializer}}
     { 4, 6 },
     { 3, 5, 7 },
-    { 4, 6, 8 }, // expected-warning{{excess elements in array initializer}}
+    { 4, 6, 8 },
   };
 }
 
@@ -152,14 +152,14 @@
   char c[] = { "Hello" };
   int l[sizeof(c) == 6 ? 1 : -1];
   
-  int i[] = { "Hello "}; // expected-error{{array of wrong type 'int' initialized from string constant}}
+  int i[] = { "Hello "}; // expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
   char c2[] = { "Hello", "Good bye" }; //expected-error{{excess elements in char array initializer}}
 
-  int i2[1] = { "Hello" }; //expected-error{{array of wrong type 'int' initialized from string constant}}
+  int i2[1] = { "Hello" }; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'int'}}
   char c3[5] = { "Hello" };
   char c4[4] = { "Hello" }; //expected-warning{{initializer-string for char array is too long}}
 
-  int i3[] = {}; //expected-error{{at least one initializer value required to size array}} expected-warning{{use of GNU empty initializer extension}}
+  int i3[] = {}; //expected-error{{at least one initializer value required to size array}} expected-error{{variable has incomplete type 'int []'}} expected-warning{{use of GNU empty initializer extension}}
 }
 
 void variableArrayInit() {
@@ -167,3 +167,40 @@
   char strlit[a] = "foo"; //expected-error{{variable-sized object may not be initialized}}
   int b[a] = { 1, 2, 4 }; //expected-error{{variable-sized object may not be initialized}}
 }
+
+// Pure array tests
+float r1[10] = {{7}}; //expected-warning{{braces around scalar initializer}}
+float r2[] = {{8}}; //expected-warning{{braces around scalar initializer}}
+char r3[][5] = {1,2,3,4,5,6};
+char r3_2[sizeof r3 == 10 ? 1 : -1];
+float r4[1][2] = {1,{2},3,4}; //expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}}
+char r5[][5] = {"aa", "bbb", "ccccc"};
+char r6[sizeof r5 == 15 ? 1 : -1];
+const char r7[] = "zxcv";
+char r8[5] = "5char";
+char r9[5] = "6chars"; //expected-warning{{initializer-string for char array is too long}}
+
+int r11[0] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}}
+
+// Some struct tests
+void autoStructTest() {
+struct s1 {char a; char b;} t1;
+struct s2 {struct s1 c;} t2 = { t1 };
+// The following is a less than great diagnostic (though it's on par with EDG).
+struct s1 t3[] = {t1, t1, "abc", 0}; //expected-warning{{incompatible pointer to integer conversion initializing 'char *', expected 'char'}}
+int t4[sizeof t3 == 6 ? 1 : -1];
+}
+struct s3 {void (*a)(void);} t5 = {autoStructTest};
+// GCC extension; flexible array init. Once this is implemented, the warning should be removed.
+// Note that clang objc implementation depends on this extension.
+struct {int a; int b[];} t6 = {1, {1, 2, 3}}; //expected-warning{{excess elements in array initializer}}
+union {char a; int b;} t7[] = {1, 2, 3};
+int t8[sizeof t7 == (3*sizeof(int)) ? 1 : -1];
+
+struct bittest{int : 31, a, :21, :12, b;};
+struct bittest bittestvar = {1, 2, 3, 4}; //expected-warning{{excess elements in array initializer}}
+
+// Not completely sure what should happen here...
+int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-warning{{braces around scalar initializer}}
+int u2 = {{3}}; //expected-warning{{braces around scalar initializer}}
+





More information about the cfe-commits mailing list