[cfe-commits] r63253 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenTypes.cpp lib/Sema/Sema.h lib/Sema/SemaInit.cpp test/Sema/designated-initializers.c

Douglas Gregor dgregor at apple.com
Wed Jan 28 15:36:19 PST 2009


Author: dgregor
Date: Wed Jan 28 17:36:17 2009
New Revision: 63253

URL: http://llvm.org/viewvc/llvm-project?rev=63253&view=rev
Log:
Improvements to code-generation and semantic analysis of designated
initializers.

  - We now initialize unions properly when a member other than the
    first is named by a designated initializer.
  - We now provide proper semantic analysis and code generation for
    GNU array-range designators *except* that side effects will occur
    more than once. We warn about this.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Sema/designated-initializers.c

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Jan 28 17:36:17 2009
@@ -60,10 +60,8 @@
      "initializer overrides prior initialization of this subobject")
 DIAG(note_previous_initializer, NOTE,
      "previous initialization %select{|with side effects }0is here%select{| (side effects may not occur at run time)}0")
-DIAG(warn_gnu_array_range_designator_unsupported, WARNING,
-     "GNU array-range designator extension is unsupported")
-DIAG(warn_designator_into_union_broken_init, WARNING,
-     "designated initialization of union member is broken")
+DIAG(warn_gnu_array_range_designator_side_effects, WARNING,
+     "side effects due to the GNU array-range designator extension may occur multiple times")
 
 // Declarations.
 DIAG(ext_vla, EXTENSION,

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=63253&r1=63252&r2=63253&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Jan 28 17:36:17 2009
@@ -454,10 +454,17 @@
     if (Field->getType()->isIncompleteArrayType())
       break;
 
-    if (Field->getIdentifier() == 0) {
-      // Initializers can't initialize unnamed fields, e.g. "int : 20;"
+    if (Field->isUnnamedBitfield())
       continue;
-    }
+
+    // When we're coping with C99 designated initializers into a
+    // union, find the field that has the same type as the expression
+    // we're initializing the union with.
+    if (isUnion && CurInitVal < NumInitElements && 
+        (CGF.getContext().getCanonicalType(Field->getType()) != 
+           CGF.getContext().getCanonicalType(E->getInit(CurInitVal)->getType())))
+      continue;
+
     // FIXME: volatility
     LValue FieldLoc = CGF.EmitLValueForField(DestPtr, *Field, isUnion,0);
     if (CurInitVal < NumInitElements) {
@@ -471,8 +478,6 @@
     }
 
     // Unions only initialize one field.
-    // (FIXME: things can get weird with designators, but they aren't
-    // supported yet.)
     if (isUnion)
       break;
   }

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=63253&r1=63252&r2=63253&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Jan 28 17:36:17 2009
@@ -246,12 +246,22 @@
     // first field
     int FieldNo = 0; // Field no in RecordDecl
     FieldDecl* curField = 0;
+    bool sawAnyFields = false;
     for (RecordDecl::field_iterator Field = RD->field_begin(),
                                  FieldEnd = RD->field_end();
          Field != FieldEnd; ++Field) {
       curField = *Field;
       FieldNo++;
-      if (curField->getIdentifier())
+
+      if (curField->isUnnamedBitfield())
+        continue;
+
+      // If we have an initializer, find the field whose type is the
+      // same as that initializer. This 
+      sawAnyFields = true;
+      if (ILE->getNumInits() > 0 &&
+          CGM.getContext().getCanonicalType(curField->getType()) ==
+            CGM.getContext().getCanonicalType(ILE->getInit(0)->getType()))
         break;
     }
 

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=63253&r1=63252&r2=63253&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Wed Jan 28 17:36:17 2009
@@ -518,6 +518,7 @@
        Field != FieldEnd; ++Field) {
     // The offset should usually be zero, but bitfields could be strange
     uint64_t offset = RL.getFieldOffset(curField);
+    CGT.ConvertTypeRecursive(Field->getType());
 
     if (Field->isBitField()) {
       Expr *BitWidth = Field->getBitWidth();

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jan 28 17:36:17 2009
@@ -1879,7 +1879,8 @@
                                   llvm::APSInt *NextElementIndex,
                                   unsigned &Index,
                                   InitListExpr *StructuredList,
-                                  unsigned &StructuredIndex);
+                                  unsigned &StructuredIndex,
+                                  bool FinishSubobjectInit = true);
   InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index,
                                            QualType CurrentObjectType,
                                            InitListExpr *StructuredList,

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=63253&r1=63252&r2=63253&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jan 28 17:36:17 2009
@@ -500,7 +500,7 @@
 
     CheckSubElementType(IList, Field->getType(), IList->getInit(Index), Index,
                         StructuredList, StructuredIndex);
-    if (DeclType->isUnionType()) // FIXME: designated initializers?
+    if (DeclType->isUnionType())
       break;
 
     ++Field;
@@ -554,7 +554,8 @@
                                       llvm::APSInt *NextElementIndex,
                                       unsigned &Index,
                                       InitListExpr *StructuredList,
-                                      unsigned &StructuredIndex) {
+                                      unsigned &StructuredIndex,
+                                      bool FinishSubobjectInit) {
   if (D == DIE->designators_end()) {
     // Check the actual initialization for the designated object type.
     bool prevHadError = hadError;
@@ -645,13 +646,8 @@
 
     // All of the fields of a union are located at the same place in
     // the initializer list.
-    // FIXME: Need to tell CodeGen which type to initialize to. ImplicitCastExpr?
-    if (RT->getDecl()->isUnion() && FieldIndex != 0) {
-      SemaRef->Diag(D->getStartLocation(), 
-                    diag::warn_designator_into_union_broken_init)
-        << SourceRange(D->getStartLocation(), DIE->getSourceRange().getEnd());
+    if (RT->getDecl()->isUnion())
       FieldIndex = 0;
-    }
 
     // Update the designator with the field declaration.
     D->setField(*Field);
@@ -682,6 +678,9 @@
       return false;
     }
 
+    if (!FinishSubobjectInit)
+      return false;
+
     // Check the remaining fields within this class/struct/union subobject.
     bool prevHadError = hadError;
     CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index,
@@ -713,63 +712,102 @@
   }
 
   Expr *IndexExpr = 0;
-  llvm::APSInt DesignatedIndex;
-  if (D->isArrayDesignator())
+  llvm::APSInt DesignatedStartIndex, DesignatedEndIndex;
+  if (D->isArrayDesignator()) {
     IndexExpr = DIE->getArrayIndex(*D);
-  else {
+    
+    bool ConstExpr 
+      = IndexExpr->isIntegerConstantExpr(DesignatedStartIndex, SemaRef->Context);
+    assert(ConstExpr && "Expression must be constant"); (void)ConstExpr;
+    
+    DesignatedEndIndex = DesignatedStartIndex;
+  } else {
     assert(D->isArrayRangeDesignator() && "Need array-range designator");
+    
+    bool StartConstExpr
+      = DIE->getArrayRangeStart(*D)->isIntegerConstantExpr(DesignatedStartIndex,
+                                                           SemaRef->Context);
+    assert(StartConstExpr && "Expression must be constant"); (void)StartConstExpr;
+
+    bool EndConstExpr
+      = DIE->getArrayRangeEnd(*D)->isIntegerConstantExpr(DesignatedEndIndex,
+                                                         SemaRef->Context);
+    assert(EndConstExpr && "Expression must be constant"); (void)EndConstExpr;
+    
     IndexExpr = DIE->getArrayRangeEnd(*D);
-    SemaRef->Diag(D->getEllipsisLoc(), 
-                  diag::warn_gnu_array_range_designator_unsupported)
-      << SourceRange(D->getLBracketLoc(), D->getRBracketLoc());
+
+    if (DesignatedStartIndex.getZExtValue() != DesignatedEndIndex.getZExtValue())
+      SemaRef->Diag(D->getEllipsisLoc(), 
+                    diag::warn_gnu_array_range_designator_side_effects)
+        << SourceRange(D->getLBracketLoc(), D->getRBracketLoc());
   }
 
-  bool ConstExpr 
-    = IndexExpr->isIntegerConstantExpr(DesignatedIndex, SemaRef->Context);
-  assert(ConstExpr && "Expression must be constant"); (void)ConstExpr;
-  
   if (isa<ConstantArrayType>(AT)) {
     llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false);
-    DesignatedIndex.extOrTrunc(MaxElements.getBitWidth());
-    DesignatedIndex.setIsUnsigned(MaxElements.isUnsigned());
-    if (DesignatedIndex >= MaxElements) {
+    DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned());
+    DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth());
+    DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned());
+    if (DesignatedEndIndex >= MaxElements) {
       SemaRef->Diag(IndexExpr->getSourceRange().getBegin(),
                     diag::err_array_designator_too_large)
-        << DesignatedIndex.toString(10) << MaxElements.toString(10)
+        << DesignatedEndIndex.toString(10) << MaxElements.toString(10)
         << IndexExpr->getSourceRange();
       ++Index;
       return true;
     }
+  } else {
+    // Make sure the bit-widths and signedness match.
+    if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth())
+      DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth());
+    else if (DesignatedStartIndex.getBitWidth() < DesignatedEndIndex.getBitWidth())
+      DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth());
+    DesignatedStartIndex.setIsUnsigned(true);
+    DesignatedEndIndex.setIsUnsigned(true);
   }
   
   // Make sure that our non-designated initializer list has space
   // for a subobject corresponding to this array element.
-  unsigned ElementIndex = DesignatedIndex.getZExtValue();
-  if (ElementIndex >= StructuredList->getNumInits())
-    StructuredList->resizeInits(SemaRef->Context, ElementIndex + 1);
-
-  // Recurse to check later designated subobjects.
-  QualType ElementType = AT->getElementType();
-  if (CheckDesignatedInitializer(IList, DIE, ++D, ElementType, 0, 0, Index,
-                                 StructuredList, ElementIndex))
-    return true;
+  if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits())
+    StructuredList->resizeInits(SemaRef->Context, 
+                                DesignatedEndIndex.getZExtValue() + 1);
+
+  // Repeatedly perform subobject initializations in the range
+  // [DesignatedStartIndex, DesignatedEndIndex].
+
+  // Move to the next designator
+  unsigned ElementIndex = DesignatedStartIndex.getZExtValue();
+  unsigned OldIndex = Index;
+  ++D;
+  while (DesignatedStartIndex <= DesignatedEndIndex) {
+    // Recurse to check later designated subobjects.
+    QualType ElementType = AT->getElementType();
+    Index = OldIndex;
+    if (CheckDesignatedInitializer(IList, DIE, D, ElementType, 0, 0, Index,
+                                   StructuredList, ElementIndex,
+                                   (DesignatedStartIndex == DesignatedEndIndex)))
+      return true;
 
-  // Move to the next index in the array that we'll be initializing.
-  ++DesignatedIndex;
-  ElementIndex = DesignatedIndex.getZExtValue();
+    // Move to the next index in the array that we'll be initializing.
+    ++DesignatedStartIndex;
+    ElementIndex = DesignatedStartIndex.getZExtValue();
+  }
 
   // If this the first designator, our caller will continue checking
   // the rest of this array subobject.
   if (IsFirstDesignator) {
     if (NextElementIndex)
-      *NextElementIndex = DesignatedIndex;
+      *NextElementIndex = DesignatedStartIndex;
     StructuredIndex = ElementIndex;
     return false;
   }
-    
+  
+  if (!FinishSubobjectInit)
+    return false;
+
   // Check the remaining elements within this array subobject.
   bool prevHadError = hadError;
-  CheckArrayType(IList, CurrentObjectType, DesignatedIndex, true, Index,
+  CheckArrayType(IList, CurrentObjectType, DesignatedStartIndex, true, Index,
                  StructuredList, ElementIndex);
   return hadError && !prevHadError;  
 }

Modified: cfe/trunk/test/Sema/designated-initializers.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/designated-initializers.c?rev=63253&r1=63252&r2=63253&view=diff

==============================================================================
--- cfe/trunk/test/Sema/designated-initializers.c (original)
+++ cfe/trunk/test/Sema/designated-initializers.c Wed Jan 28 17:36:17 2009
@@ -19,7 +19,7 @@
 
 int iarray3[10] = {
   [5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}}\
-                // expected-warning{{GNU array-range designator extension is unsupported}}
+                // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
 };
 
 struct point {
@@ -45,8 +45,8 @@
 
 struct point array2[10] = {
   [10].x = 2.0, // expected-error{{array designator index (10) exceeds array bounds (10)}}
-  [4 ... 5].y = 2.0, // expected-warning{{GNU array-range designator extension is unsupported}}
-  [4 ... 6] = { .x = 3, .y = 4.0 } // expected-warning{{GNU array-range designator extension is unsupported}}
+  [4 ... 5].y = 2.0, // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
+  [4 ... 6] = { .x = 3, .y = 4.0 } // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
 };
 
 struct point array3[10] = {
@@ -117,7 +117,7 @@
 // PR clang/3378
 int bitwidth[] = { [(long long int)1] = 5, [(short int)2] = 2 };
 int a[]= { [sizeof(int)] = 0 };
-int a2[]= { [0 ... sizeof(int)] = 0 }; // expected-warning{{GNU array-range designator extension is unsupported}}
+int a2[]= { [0 ... sizeof(int)] = 0 }; // expected-warning{{side effects due to the GNU array-range designator extension may occur multiple times}}
 
 // Test warnings about initializers overriding previous initializers
 struct X {
@@ -138,4 +138,4 @@
 }
 
 // FIXME: we need to 
-union { char c; long l; } u1 = { .l = 0xFFFF }; // expected-warning{{designated initialization of union member is broken}}
+union { char c; long l; } u1 = { .l = 0xFFFF };





More information about the cfe-commits mailing list