From 762f928a7a64133a1c5dab73d469440bb2e21b26 Mon Sep 17 00:00:00 2001 From: Brian Kelley Date: Wed, 29 Mar 2017 18:16:38 +0000 Subject: [PATCH] [Objective-C] Miscellaneous -fobjc-weak Fixes Summary: After examining the remaining uses of LangOptions.ObjCAutoRefCount, found a some additional places to also check for ObjCWeak not covered by previous test cases. Added a test file to verify all the code paths that were changed. Reviewers: rsmith, doug.gregor, rjmccall Reviewed By: rjmccall Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D31007 llvm-svn: 299015 --- clang/lib/Sema/SemaCast.cpp | 4 ++-- clang/lib/Sema/SemaDecl.cpp | 12 ++++++------ clang/lib/Sema/SemaDeclCXX.cpp | 3 +-- clang/lib/Sema/SemaInit.cpp | 12 ++++-------- clang/test/SemaObjCXX/objc-weak.mm | 28 ++++++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 clang/test/SemaObjCXX/objc-weak.mm diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index ce21d15..7e91709 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -871,7 +871,7 @@ void CastOperation::CheckReinterpretCast() { } SrcExpr = ExprError(); } else if (tcr == TC_Success) { - if (Self.getLangOpts().ObjCAutoRefCount) + if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) checkObjCConversion(Sema::CCK_OtherCast); DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); } @@ -935,7 +935,7 @@ void CastOperation::CheckStaticCast() { } else if (tcr == TC_Success) { if (Kind == CK_BitCast) checkCastAlign(); - if (Self.getLangOpts().ObjCAutoRefCount) + if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) checkObjCConversion(Sema::CCK_OtherCast); } else if (Kind == CK_BitCast) { checkCastAlign(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f964d05..b07ca7d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -14468,7 +14468,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Verify that all the fields are okay. SmallVector RecFields; - bool ARCErrReported = false; + bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -14603,16 +14603,16 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); - } else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && + } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + Record && !ObjCFieldLifetimeErrReported && (!getLangOpts().CPlusPlus || Record->isUnion())) { - // It's an error in ARC if a field has lifetime. + // 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(); - Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + if (T.hasNonTrivialObjCLifetime()) { SourceLocation loc = FD->getLocation(); if (getSourceManager().isInSystemHeader(loc)) { if (!FD->hasAttr()) { @@ -14623,7 +14623,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) << T->isBlockPointerType() << Record->getTagKind(); } - ARCErrReported = true; + ObjCFieldLifetimeErrReported = true; } } else if (getLangOpts().ObjC1 && getLangOpts().getGC() != LangOptions::NonGC && diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c369d62..2a90b46 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7145,8 +7145,7 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, // [...] nontrivally ownership-qualified types are [...] not trivially // default constructible, copy constructible, move constructible, copy // assignable, move assignable, or destructible [...] - if (S.getLangOpts().ObjCAutoRefCount && - FieldType.hasNonTrivialObjCLifetime()) { + if (FieldType.hasNonTrivialObjCLifetime()) { if (Diagnose) S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) << RD << FieldType.getObjCLifetime(); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index e229168..08631a1 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6687,14 +6687,10 @@ InitializationSequence::Perform(Sema &S, /*IsInitializerList=*/false, ExtendingEntity->getDecl()); - // If we're binding to an Objective-C object that has lifetime, we - // need cleanups. Likewise if we're extending this temporary to automatic - // storage duration -- we need to register its cleanup during the - // full-expression's cleanups. - if ((S.getLangOpts().ObjCAutoRefCount && - MTE->getType()->isObjCLifetimeType()) || - (MTE->getStorageDuration() == SD_Automatic && - MTE->getType().isDestructedType())) + // If we're extending this temporary to automatic storage duration -- we + // need to register its cleanup during the full-expression's cleanups. + if (MTE->getStorageDuration() == SD_Automatic && + MTE->getType().isDestructedType()) S.Cleanup.setExprNeedsCleanups(true); CurInit = MTE; diff --git a/clang/test/SemaObjCXX/objc-weak.mm b/clang/test/SemaObjCXX/objc-weak.mm new file mode 100644 index 0000000..93c6af1 --- /dev/null +++ b/clang/test/SemaObjCXX/objc-weak.mm @@ -0,0 +1,28 @@ +// 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 + +@interface AnObject +@property(weak) id value; +@end + +__attribute__((objc_arc_weak_reference_unavailable)) +@interface NOWEAK : AnObject // expected-note 2 {{class is declared here}} +@end + +struct S { + __weak id a; // expected-note {{because type 'S' has a member with __weak ownership}} +}; + +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}} +}; + +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}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} + + __weak id b = static_cast<__weak NOWEAK *>(o); // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{explicit ownership qualifier on cast result has no effect}} \ + // expected-error {{assignment of a weak-unavailable object to a __weak object}} +} -- 2.7.4