]> granicus.if.org Git - clang/commitdiff
Don't build member initializers for zero-length or incomplete arrays,
authorDouglas Gregor <dgregor@apple.com>
Wed, 2 Nov 2011 23:04:16 +0000 (23:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 2 Nov 2011 23:04:16 +0000 (23:04 +0000)
and don't try to destroy them, either. Fixes
<rdar://problem/10228639>.

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

lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/constructors.cpp
test/SemaCXX/zero-length-arrays.cpp [new file with mode: 0644]

index 61385f9348185c7ed72dd87952ec5570e25effa7..7a423a73f05c66da661690f8e9b0b4cdea3ac1ec 100644 (file)
@@ -2413,7 +2413,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
     // Suppress copying zero-width bitfields.
     if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
       return false;
-    
+        
     Expr *MemberExprBase = 
       DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, 
                           Loc, ParamType, VK_LValue, 0);
@@ -2649,6 +2649,22 @@ static bool isWithinAnonymousUnion(IndirectFieldDecl *F) {
   return false;
 }
 
+/// \brief Determine whether the given type is an incomplete or zero-lenfgth
+/// array type.
+static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
+  if (T->isIncompleteArrayType())
+    return true;
+  
+  while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
+    if (!ArrayT->getSize())
+      return true;
+    
+    T = ArrayT->getElementType();
+  }
+  
+  return false;
+}
+
 static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
                                     FieldDecl *Field, 
                                     IndirectFieldDecl *Indirect = 0) {
@@ -2684,6 +2700,10 @@ static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
       (Indirect && isWithinAnonymousUnion(Indirect)))
     return false;
 
+  // Don't initialize incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
+    return false;
+
   // Don't try to build an implicit initializer if there were semantic
   // errors in any of the initializers (and therefore we might be
   // missing some that the user actually wrote).
@@ -2822,13 +2842,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
       //   initialized.
       if (F->isUnnamedBitfield())
         continue;
-      
-      if (F->getType()->isIncompleteArrayType()) {
-        assert(ClassDecl->hasFlexibleArrayMember() &&
-               "Incomplete array type is not valid");
-        continue;
-      }
-      
+            
       // If we're not generating the implicit copy/move constructor, then we'll
       // handle anonymous struct/union fields based on their individual
       // indirect fields.
@@ -3169,6 +3183,11 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
     FieldDecl *Field = *I;
     if (Field->isInvalidDecl())
       continue;
+    
+    // Don't destroy incomplete or zero-length arrays.
+    if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+      continue;
+
     QualType FieldType = Context.getBaseElementType(Field->getType());
     
     const RecordType* RT = FieldType->getAs<RecordType>();
index ec7f06c868a9896a9c4cbddd11a4b744abb456cc..9e2da31f046aff0b90d560a225556bcfc092e4f7 100644 (file)
@@ -111,7 +111,5 @@ namespace test1 {
   B::B() {}
   // CHECK:    define void @_ZN5test11BC2Ev(
   // CHECK:      [[THIS:%.*]] = load [[B:%.*]]**
-  // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[B:%.*]]* [[THIS]], i32 0, i32 1
-  // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [0 x {{%.*}}]* [[A]], i32 0, i32 0
   // CHECK-NEXT: ret void
 }
diff --git a/test/SemaCXX/zero-length-arrays.cpp b/test/SemaCXX/zero-length-arrays.cpp
new file mode 100644 (file)
index 0000000..05ded4a
--- /dev/null
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/10228639>
+class Foo {
+  ~Foo();
+  Foo(const Foo&);
+public:
+  Foo(int);
+};
+
+class Bar {
+  int foo_count;
+  Foo foos[0];
+  Foo foos2[0][2];
+  Foo foos3[2][0];
+
+public:
+  Bar(): foo_count(0) { }    
+  ~Bar() { }
+};
+
+void testBar() {
+  Bar b;
+  Bar b2(b);
+  b = b2;
+}