Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5179,6 +5179,8 @@ "%select{struct|interface|union|class|enum}1">; def err_flexible_array_has_nontrivial_dtor : Error< "flexible array member %0 of type %1 with non-trivial destruction">; +def err_flexible_array_in_objc_class : Error< + "%0 may not be used in interface due to flexible array member">; def ext_flexible_array_in_struct : Extension< "%0 may not be nested in a struct due to flexible array member">, InGroup; Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -14990,6 +14990,12 @@ // Ivars can not have abstract class types FD->setInvalidDecl(); } + if (isa(EnclosingDecl) && FDTTy->getDecl()->hasFlexibleArrayMember()) { + Diag(FD->getLocation(), diag::err_flexible_array_in_objc_class) + << FD->getDeclName(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + } if (Record && FDTTy->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); if (Record && FDTTy->getDecl()->hasVolatileMember()) Index: clang/test/SemaObjC/ivar-sem-check-3.m =================================================================== --- /dev/null +++ clang/test/SemaObjC/ivar-sem-check-3.m @@ -0,0 +1,184 @@ +// RUN: %clang_cc1 -emit-llvm-only -fobjc-arc -verify -Wno-objc-root-class %s + +// # Flexible array member, not structs with flexible array members. +// ## Ivars only in interface. +@interface LastIVar +{ + char flexible[]; +} +@end +@implementation LastIVar +@end + +@interface NotLastIVar +{ + char flexible[]; // expected error + int last; +} +@end +@implementation NotLastIVar +@end + +// ## IVars in implementation. +@interface LastIVarInImpl +@end +@implementation LastIVarInImpl +{ + char flexible[]; // expected warning like "Field 'flexible' with variable sized type 'char[]' is not visible to subclasses and can conflict with their fields" +} +@end + +@interface OtherIVarInImpl +{ + char flexible[]; // expected error +} +@end +@implementation OtherIVarInImpl +{ + int last; +} +@end + +@interface NotLastIVarInImpl +@end +@implementation NotLastIVarInImpl +{ + char flexible[]; // expected error + int last; +} +@end + +// ## Synthesized ivars. +@interface ExplicitlyNamedValid +{ + int _elementsCount; + char flexible[]; +} +@property int count; +@end +@implementation ExplicitlyNamedValid +@synthesize count = _elementsCount; +@end + +@interface ImplicitlyNamedValid +{ + int _count; + char flexible[]; +} +@property int count; +@end +@implementation ExplicitlyNamedValid +@synthesize count; +@end + +@interface ExplicitlyNamedInvalid +{ + char flexible[]; // expected error +} +@property int count; +@end +@implementation ExplicitlyNamedInvalid +@synthesize count = _elementsCount; +@end + +@interface ImplicitlyNamedInvalid +{ + char flexible[]; // expected error +} +@property int count; +@end +@implementation ExplicitlyNamedInvalid +@synthesize count; +@end + + +// # Variable sized types. +struct Packet +{ + unsigned int size; + char data[]; +}; + +// ## Ivars only in interface. +@interface StructLastIVar +{ + struct Packet flexible; +} +@end +@implementation StructLastIVar +@end + +@interface StructNotLastIVar +{ + struct Packet flexible; // expected error + int last; +} +@end +@implementation StructNotLastIVar +@end + +// ## IVars in implementation. +@interface StructLastIVarInImpl +@end +@implementation StructLastIVarInImpl +{ + struct Packet flexible; // expected warning like "Field 'flexible' with variable sized type 'struct Packet' is not visible to subclasses and can conflict with their fields" +} +@end + +@interface StructOtherIVarInImpl +{ + struct Packet flexible; // expected error +} +@end +@implementation StructOtherIVarInImpl +{ + int last; +} +@end + +@interface StructNotLastIVarInImpl +@end +@implementation StructNotLastIVarInImpl +{ + struct Packet flexible; // expected error + int last; +} +@end + +// # Subclassing. +@interface FlexibleArrayMemberBase +{ + char flexible[]; +} +@end +@implementation FlexibleArrayMemberBase +@end + +@interface NoAdditions : FlexibleArrayMemberBase +@end +@implementation NoAdditions +@end + +@interface AddedInInterface : FlexibleArrayMemberBase +{ + int last; // expected warning +} +@end +@implementation AddedInInterface +@end + +@interface AddedInImplementation : FlexibleArrayMemberBase +@end +@implementation AddedInImplementation +{ + int last; // expected warning +} +@end + +@interface SynthesizeIVar : FlexibleArrayMemberBase +@property int count; +@end +@implementation AddedInImplementation +@synthesize count; // expected warning +@end