Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -1137,6 +1137,11 @@ /// kind. PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const; + bool isTrivialOrTrivialVolatileToPrimitiveCopy() const { + PrimitiveCopyKind Kind = isNonTrivialToPrimitiveCopy(); + return Kind == PCK_Trivial || Kind == PCK_VolatileTrivial; + } + /// Check if this is a non-trivial type that would cause a C struct /// transitively containing this type to be non-trivial to destructively /// move and return the kind. Destructive move in this context is a C++-style @@ -1145,6 +1150,10 @@ /// source object is placed in an uninitialized state. PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const; + bool isTrivialOrTrivialVolatileToPrimitiveMove() const { + return isTrivialOrTrivialVolatileToPrimitiveCopy(); + } + enum DestructionKind { DK_none, DK_cxx_destructor, Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -5280,6 +5280,8 @@ def err_arc_objc_object_in_tag : Error< "ARC forbids %select{Objective-C objects|blocks}0 in " "%select{struct|interface|union|<>|enum}1">; +def err_arc_nontrivial_primitive_type_in_union : Error< + "ARC forbids non-trivial C types in union">; def err_arc_objc_property_default_assign_on_object : Error< "ARC forbids synthesizing a property of an Objective-C object " "with unspecified ownership or storage attribute">; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -15760,13 +15760,13 @@ // Verify that all the fields are okay. SmallVector RecFields; - bool ObjCFieldLifetimeErrReported = false; + bool NonTrivialPrimitiveFieldErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); // Get the type for the field. - const Type *FDTy = FD->getType().getTypePtr(); + QualType FDTy = FD->getType(); if (!FD->isAnonymousStructOrUnion()) { // Remember all fields written by the user. @@ -15868,6 +15868,40 @@ FD->setInvalidDecl(); EnclosingDecl->setInvalidDecl(); continue; + } else if (FDTy->isObjCObjectType()) { + /// A field cannot be an Objective-c object + Diag(FD->getLocation(), diag::err_statically_allocated_object) + << FixItHint::CreateInsertion(FD->getLocation(), "*"); + QualType T = Context.getObjCObjectPointerType(FD->getType()); + FD->setType(T); + } else if (Record && !NonTrivialPrimitiveFieldErrReported && + Record->isUnion() && + (FDTy.hasNonTrivialObjCLifetime() || + (!getLangOpts().CPlusPlus && + (FDTy.isNonTrivialToPrimitiveDefaultInitialize() || + !FDTy.isTrivialOrTrivialVolatileToPrimitiveCopy() || + !FDTy.isTrivialOrTrivialVolatileToPrimitiveMove() || + FDTy.isDestructedType())))) { + // It's an error to have a field that has a non-trivial ObjC lifetime or + // a non-trivial C type in a union. + // We don't want to report this in a system header, though, + // so we just make the field unavailable. + // FIXME: that's really not sufficient; we need to make the type + // itself invalid to, say, initialize or copy. + SourceLocation loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(loc)) { + if (!FD->hasAttr()) { + FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", + UnavailableAttr::IR_ARCFieldWithOwnership, loc)); + } + } else if (FDTy.hasNonTrivialObjCLifetime()) { + Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) + << FDTy->isBlockPointerType() << Record->getTagKind(); + } else { + Diag(FD->getLocation(), + diag::err_arc_nontrivial_primitive_type_in_union); + } + NonTrivialPrimitiveFieldErrReported = true; } else if (const RecordType *FDTTy = FDTy->getAs()) { if (Record && FDTTy->getDecl()->hasFlexibleArrayMember()) { // A type which contains a flexible array member is considered to be a @@ -15899,33 +15933,6 @@ Record->setHasObjectMember(true); if (Record && FDTTy->getDecl()->hasVolatileMember()) Record->setHasVolatileMember(true); - } else if (FDTy->isObjCObjectType()) { - /// A field cannot be an Objective-c object - Diag(FD->getLocation(), diag::err_statically_allocated_object) - << FixItHint::CreateInsertion(FD->getLocation(), "*"); - QualType T = Context.getObjCObjectPointerType(FD->getType()); - FD->setType(T); - } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) { - // It's an error in ARC or Weak if a field has lifetime. - // We don't want to report this in a system header, though, - // so we just make the field unavailable. - // FIXME: that's really not sufficient; we need to make the type - // itself invalid to, say, initialize or copy. - QualType T = FD->getType(); - if (T.hasNonTrivialObjCLifetime()) { - SourceLocation loc = FD->getLocation(); - if (getSourceManager().isInSystemHeader(loc)) { - if (!FD->hasAttr()) { - FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", - UnavailableAttr::IR_ARCFieldWithOwnership, loc)); - } - } else { - Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) - << T->isBlockPointerType() << Record->getTagKind(); - } - ObjCFieldLifetimeErrReported = true; - } } else if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { Index: test/SemaObjC/arc-decls.m =================================================================== --- test/SemaObjC/arc-decls.m +++ test/SemaObjC/arc-decls.m @@ -10,6 +10,10 @@ id u; // expected-error {{ARC forbids Objective-C objects in union}} }; +union u_nontrivial_c { + struct A a; // expected-error {{ARC forbids non-trivial C types in union}} +}; + @interface I { struct A a; struct B { Index: test/SemaObjCXX/objc-weak.mm =================================================================== --- test/SemaObjCXX/objc-weak.mm +++ test/SemaObjCXX/objc-weak.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++98 -Wno-c++0x-extensions -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Wno-c++0x-extensions -verify %s @interface AnObject @property(weak) id value; @@ -9,14 +10,19 @@ @end struct S { - __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} + __weak id a; }; union U { __weak id a; // expected-error {{ARC forbids Objective-C objects in union}} - S b; // expected-error {{union member 'b' has a non-trivial copy constructor}} + S b; }; +#if __cplusplus < 201103L +// expected-note@-9 {{because type 'S' has a member with __weak ownership}} +// expected-error@-5 {{union member 'b' has a non-trivial copy constructor}} +#endif + void testCast(AnObject *o) { __weak id a = reinterpret_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ // expected-error {{explicit ownership qualifier on cast result has no effect}} \