From: Douglas Gregor Date: Mon, 28 Jan 2013 19:08:09 +0000 (+0000) Subject: Forbid the use of objects in unions in Objective-C++ ARC. Fixes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4581d45405f07374770366be8644d52733985833;p=clang Forbid the use of objects in unions in Objective-C++ ARC. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173708 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 54b8c6f64c..4e48089e38 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3696,8 +3696,9 @@ def err_arc_mismatched_cast : Error< " to %3 is disallowed with ARC">; def err_arc_nolifetime_behavior : Error< "explicit ownership qualifier on cast result has no effect">; -def err_arc_objc_object_in_struct : Error< - "ARC forbids %select{Objective-C objects|blocks}0 in structs or unions">; +def err_arc_objc_object_in_tag : Error< + "ARC forbids %select{Objective-C objects|blocks}0 of type %1 in " + "%select{struct|interface|union|<>|enum}2">; 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">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a5f39a82f1..aa4a865344 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -10498,44 +10498,42 @@ void Sema::ActOnFields(Scope* S, << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); - } else if (!getLangOpts().CPlusPlus) { - if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) { - // It's an error in ARC 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(); - Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { - SourceLocation loc = FD->getLocation(); - if (getSourceManager().isInSystemHeader(loc)) { - if (!FD->hasAttr()) { - FD->addAttr(new (Context) UnavailableAttr(loc, Context, - "this system field has retaining ownership")); - } - } else { - Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct) - << T->isBlockPointerType(); + } else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && + (!getLangOpts().CPlusPlus || Record->isUnion())) { + // It's an error in ARC 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(); + Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); + if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + SourceLocation loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(loc)) { + if (!FD->hasAttr()) { + FD->addAttr(new (Context) UnavailableAttr(loc, Context, + "this system field has retaining ownership")); } - ARCErrReported = true; + } else { + Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) + << T->isBlockPointerType() << T << Record->getTagKind(); } + ARCErrReported = true; } - else if (getLangOpts().ObjC1 && + } else if (getLangOpts().ObjC1 && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { - if (FD->getType()->isObjCObjectPointerType() || - FD->getType().isObjCGCStrong()) + if (FD->getType()->isObjCObjectPointerType() || + FD->getType().isObjCGCStrong()) + Record->setHasObjectMember(true); + else if (Context.getAsArrayType(FD->getType())) { + QualType BaseType = Context.getBaseElementType(FD->getType()); + if (BaseType->isRecordType() && + BaseType->getAs()->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); - else if (Context.getAsArrayType(FD->getType())) { - QualType BaseType = Context.getBaseElementType(FD->getType()); - if (BaseType->isRecordType() && - BaseType->getAs()->getDecl()->hasObjectMember()) - Record->setHasObjectMember(true); - else if (BaseType->isObjCObjectPointerType() || - BaseType.isObjCGCStrong()) - Record->setHasObjectMember(true); - } + else if (BaseType->isObjCObjectPointerType() || + BaseType.isObjCGCStrong()) + Record->setHasObjectMember(true); } } if (Record && FD->getType().isVolatileQualified()) diff --git a/test/ARCMT/checking.m b/test/ARCMT/checking.m index 9fd50029d0..a5c364a058 100644 --- a/test/ARCMT/checking.m +++ b/test/ARCMT/checking.m @@ -117,7 +117,7 @@ void test1(A *a, BOOL b, struct UnsafeS *unsafeS) { } struct S { - A* a; // expected-error {{ARC forbids Objective-C objects in structs or unions}} + A* a; // expected-error {{ARC forbids Objective-C objects of type 'A *__strong' in struct}} }; @interface B diff --git a/test/SemaObjC/arc-decls.m b/test/SemaObjC/arc-decls.m index a53b52acd8..e9ce415188 100644 --- a/test/SemaObjC/arc-decls.m +++ b/test/SemaObjC/arc-decls.m @@ -3,17 +3,17 @@ // rdar://8843524 struct A { - id x; // expected-error {{ARC forbids Objective-C objects in structs or unions}} + id x; // expected-error {{ARC forbids Objective-C objects of type '__strong id' in struct}} }; union u { - id u; // expected-error {{ARC forbids Objective-C objects in structs or unions}} + id u; // expected-error {{ARC forbids Objective-C objects of type '__strong id' in union}} }; @interface I { struct A a; struct B { - id y[10][20]; // expected-error {{ARC forbids Objective-C objects in structs or unions}} + id y[10][20]; // expected-error {{ARC forbids Objective-C objects}} id z; } b; @@ -23,7 +23,7 @@ union u { // rdar://10260525 struct r10260525 { - id (^block) (); // expected-error {{ARC forbids blocks in structs or unions}} + id (^block) (); // expected-error {{ARC forbids blocks of type 'id (^__strong)()' in struct}} }; struct S {