Index: include/clang/Basic/LangOptions.h =================================================================== --- include/clang/Basic/LangOptions.h +++ include/clang/Basic/LangOptions.h @@ -170,6 +170,11 @@ /// \brief Is this a libc/libm function that is no longer recognized as a /// builtin because a -fno-builtin-* option has been specified? bool isNoBuiltinFunc(StringRef Name) const; + + /// \brief True if any ObjC types may have non-trivial lifetime qualifiers. + bool allowsNonTrivialObjCLifetimeQualifiers() const { + return ObjCAutoRefCount || ObjCWeak; + } }; /// \brief Floating point control options Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -9334,14 +9334,14 @@ enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; /// \brief Checks for invalid conversions and casts between - /// retainable pointers and other pointer kinds. - ARCConversionResult CheckObjCARCConversion(SourceRange castRange, - QualType castType, Expr *&op, - CheckedConversionKind CCK, - bool Diagnose = true, - bool DiagnoseCFAudited = false, - BinaryOperatorKind Opc = BO_PtrMemD - ); + /// retainable pointers and other pointer kinds for ARC and Weak. + ARCConversionResult CheckObjCConversion(SourceRange castRange, + QualType castType, Expr *&op, + CheckedConversionKind CCK, + bool Diagnose = true, + bool DiagnoseCFAudited = false, + BinaryOperatorKind Opc = BO_PtrMemD + ); Expr *stripARCUnbridgedCast(Expr *e); void diagnoseARCUnbridgedCast(Expr *e); Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -120,12 +120,12 @@ Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); } - void checkObjCARCConversion(Sema::CheckedConversionKind CCK) { - assert(Self.getLangOpts().ObjCAutoRefCount); + void checkObjCConversion(Sema::CheckedConversionKind CCK) { + assert(Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()); Expr *src = SrcExpr.get(); - if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) == - Sema::ACR_unbridged) + if (Self.CheckObjCConversion(OpRange, DestType, src, CCK) == + Sema::ACR_unbridged) IsARCUnbridgedCast = true; SrcExpr = src; } @@ -872,7 +872,7 @@ SrcExpr = ExprError(); } else if (tcr == TC_Success) { if (Self.getLangOpts().ObjCAutoRefCount) - checkObjCARCConversion(Sema::CCK_OtherCast); + checkObjCConversion(Sema::CCK_OtherCast); DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); } } @@ -936,7 +936,7 @@ if (Kind == CK_BitCast) checkCastAlign(); if (Self.getLangOpts().ObjCAutoRefCount) - checkObjCARCConversion(Sema::CCK_OtherCast); + checkObjCConversion(Sema::CCK_OtherCast); } else if (Kind == CK_BitCast) { checkCastAlign(); } @@ -2272,8 +2272,9 @@ } } - if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success) - checkObjCARCConversion(CCK); + if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + tcr == TC_Success) + checkObjCConversion(CCK); if (tcr != TC_Success && msg != 0) { if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { @@ -2539,12 +2540,13 @@ } // ARC imposes extra restrictions on casts. - if (Self.getLangOpts().ObjCAutoRefCount) { - checkObjCARCConversion(Sema::CCK_CStyleCast); + if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) { + checkObjCConversion(Sema::CCK_CStyleCast); if (SrcExpr.isInvalid()) return; - - if (const PointerType *CastPtr = DestType->getAs()) { + + const PointerType *CastPtr = DestType->getAs(); + if (Self.getLangOpts().ObjCAutoRefCount && CastPtr) { if (const PointerType *ExprPtr = SrcType->getAs()) { Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers(); Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers(); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -7700,7 +7700,7 @@ Kind = CK_BitCast; Sema::AssignConvertType result = checkObjCPointerTypesForAssignment(*this, LHSType, RHSType); - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && result == Compatible && !CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType)) result = IncompatibleObjCWeakRef; @@ -7907,7 +7907,7 @@ if (RHS.isInvalid()) return Incompatible; Sema::AssignConvertType result = Compatible; - if (getLangOpts().ObjCAutoRefCount && + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && !CheckObjCARCUnavailableWeakConversion(LHSType, RHSType)) result = IncompatibleObjCWeakRef; return result; @@ -7984,9 +7984,9 @@ // Check for various Objective-C errors. If we are not reporting // diagnostics and just checking for errors, e.g., during overload // resolution, return Incompatible to indicate the failure. - if (getLangOpts().ObjCAutoRefCount && - CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, - Diagnose, DiagnoseCFAudited) != ACR_okay) { + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + CheckObjCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, + Diagnose, DiagnoseCFAudited) != ACR_okay) { if (!Diagnose) return Incompatible; } @@ -9612,16 +9612,17 @@ if (LHSIsNull && !RHSIsNull) { Expr *E = LHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), RHSType, E, CCK_ImplicitConversion); + CheckObjCConversion(SourceRange(), RHSType, E, + CCK_ImplicitConversion); LHS = ImpCastExprToType(E, RHSType, RPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } else { Expr *E = RHS.get(); if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), LHSType, E, - CCK_ImplicitConversion, /*Diagnose=*/true, - /*DiagnoseCFAudited=*/false, Opc); + CheckObjCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion, + /*Diagnose=*/true, + /*DiagnoseCFAudited=*/false, Opc); RHS = ImpCastExprToType(E, LHSType, LPT ? CK_BitCast :CK_CPointerToObjCPointerCast); } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -3744,10 +3744,9 @@ if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) EmitRelatedResultTypeNote(From); - } - else if (getLangOpts().ObjCAutoRefCount && - !CheckObjCARCUnavailableWeakConversion(ToType, - From->getType())) { + } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && + !CheckObjCARCUnavailableWeakConversion(ToType, + From->getType())) { if (Action == AA_Initializing) Diag(From->getLocStart(), diag::err_arc_weak_unavailable_assign); @@ -3770,8 +3769,8 @@ (void) PrepareCastToObjCObjectPointer(E); From = E.get(); } - if (getLangOpts().ObjCAutoRefCount) - CheckObjCARCConversion(SourceRange(), ToType, From, CCK); + if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) + CheckObjCConversion(SourceRange(), ToType, From, CCK); From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK) .get(); break; Index: lib/Sema/SemaExprObjC.cpp =================================================================== --- lib/Sema/SemaExprObjC.cpp +++ lib/Sema/SemaExprObjC.cpp @@ -4108,11 +4108,10 @@ } Sema::ARCConversionResult -Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, - Expr *&castExpr, CheckedConversionKind CCK, - bool Diagnose, - bool DiagnoseCFAudited, - BinaryOperatorKind Opc) { +Sema::CheckObjCConversion(SourceRange castRange, QualType castType, + Expr *&castExpr, CheckedConversionKind CCK, + bool Diagnose, bool DiagnoseCFAudited, + BinaryOperatorKind Opc) { QualType castExprType = castExpr->getType(); // For the purposes of the classification, we assume reference types @@ -4152,7 +4151,12 @@ } return ACR_okay; } - + + // The life-time qualifier cast check above is all we need for ObjCWeak. + // ObjCAutoRefCount has more restrictions on what is legal. + if (!getLangOpts().ObjCAutoRefCount) + return ACR_okay; + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; // Allow all of these types to be cast to integer types (but not Index: lib/Sema/SemaPseudoObject.cpp =================================================================== --- lib/Sema/SemaPseudoObject.cpp +++ lib/Sema/SemaPseudoObject.cpp @@ -1127,8 +1127,8 @@ if (!Getter) return; QualType T = Getter->parameters()[0]->getType(); - S.CheckObjCARCConversion(Key->getSourceRange(), - T, Key, Sema::CCK_ImplicitConversion); + S.CheckObjCConversion(Key->getSourceRange(), T, Key, + Sema::CCK_ImplicitConversion); } bool ObjCSubscriptOpBuilder::findAtIndexGetter() { Index: test/SemaObjC/arc-unavailable-for-weakref.m =================================================================== --- test/SemaObjC/arc-unavailable-for-weakref.m +++ test/SemaObjC/arc-unavailable-for-weakref.m @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify -Wno-objc-root-class %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable)) Index: test/SemaObjCXX/arc-unavailable-for-weakref.mm =================================================================== --- test/SemaObjCXX/arc-unavailable-for-weakref.mm +++ test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -fobjc-weak -verify %s // rdar://9693477 __attribute__((objc_arc_weak_reference_unavailable))