From: Douglas Gregor Date: Wed, 2 Nov 2011 23:04:16 +0000 (+0000) Subject: Don't build member initializers for zero-length or incomplete arrays, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ddb21473ef1ff20b3abf7ba3cd6cb29acbd5cf06;p=clang Don't build member initializers for zero-length or incomplete arrays, and don't try to destroy them, either. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143584 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 61385f9348..7a423a73f0 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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(); diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp index ec7f06c868..9e2da31f04 100644 --- a/test/CodeGenCXX/constructors.cpp +++ b/test/CodeGenCXX/constructors.cpp @@ -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 index 0000000000..05ded4ad9b --- /dev/null +++ b/test/SemaCXX/zero-length-arrays.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// +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; +}