vsapsai created this revision. vsapsai added reviewers: arphaman, dexonsmith. Herald added subscribers: ributzka, jkorous. Herald added a project: clang.
Commit 73152a2ec20766ac45673a129bf1f5fc97ca9bbe fixed type checking for blocks with qualified id parameters. But there are existing APIs in Apple SDKs relying on the old type checking behavior. Specifically, these are APIs using NSItemProviderCompletionHandler in Foundation/NSItemProvider.h. To keep existing code working and to allow developers to use affected APIs introduce a compatibility mode that enables the previous type checking. This mode is enabled only on Darwin platforms. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D79511 Files: clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/CC1Options.td clang/lib/AST/ASTContext.cpp clang/lib/Driver/ToolChains/Darwin.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/test/Driver/darwin-objc-options.m clang/test/SemaObjC/block-type-safety.m
Index: clang/test/SemaObjC/block-type-safety.m =================================================================== --- clang/test/SemaObjC/block-type-safety.m +++ clang/test/SemaObjC/block-type-safety.m @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wno-objc-root-class \ +// RUN: -fcompatibility-qualified-id-block-type-checking -DCOMPATIBILITY_QUALIFIED_ID_TYPE_CHECKING=1 %s // test for block type safety. @interface Super @end @@ -132,6 +134,7 @@ @interface NSAllArray (FooConformance) <Foo> @end +#ifndef COMPATIBILITY_QUALIFIED_ID_TYPE_CHECKING int test5() { // Returned value is used outside of a block, so error on changing // a return type to a more general than expected. @@ -149,6 +152,25 @@ blockWithParam = genericBlockWithParam; return 0; } +#else +// In Apple SDK APIs using NSItemProviderCompletionHandler require to work with +// blocks that have parameters more specific than in method signatures. As +// explained in non-compatibility test above, it is not safe in general. But +// to keep existing code working we support a compatibility mode that uses +// previous type checking. +int test5() { + NSAllArray *(^block)(id); + id <Foo> (^genericBlock)(id); + genericBlock = block; + block = genericBlock; // expected-error {{incompatible block pointer types assigning to 'NSAllArray *(^)(id)' from 'id<Foo> (^)(id)'}} + + void (^blockWithParam)(NSAllArray *); + void (^genericBlockWithParam)(id<Foo>); + genericBlockWithParam = blockWithParam; + blockWithParam = genericBlockWithParam; // expected-error {{incompatible block pointer types assigning to 'void (^)(NSAllArray *)' from 'void (^)(id<Foo>)'}} + return 0; +} +#endif // rdar://10798770 typedef int NSInteger; Index: clang/test/Driver/darwin-objc-options.m =================================================================== --- clang/test/Driver/darwin-objc-options.m +++ clang/test/Driver/darwin-objc-options.m @@ -40,3 +40,9 @@ // Don't crash with an unexpected target triple. // RUN: %clang -target i386-apple-ios7 -S -### %s + +// Add -fcompatibility-qualified-id-block-type-checking only on Darwin. +// RUN: %clang -target x86_64-apple-darwin10 -### %s 2>&1 | FileCheck --check-prefix=DARWIN_COMPATIBILITY %s +// RUN: %clang -target x86_64-linux-gnu -### %s 2>&1 | FileCheck --check-prefix=OTHER_COMPATIBILITY %s +// DARWIN_COMPATIBILITY: -fcompatibility-qualified-id-block-type-checking +// OTHER_COMPATIBILITY-NOT: -fcompatibility-qualified-id-block-type-checking Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -3371,6 +3371,9 @@ } Opts.BranchTargetEnforcement = Args.hasArg(OPT_mbranch_target_enforce); + + Opts.CompatibilityQualifiedIdBlockParamTypeChecking = + Args.hasArg(OPT_fcompatibility_qualified_id_block_param_type_checking); } static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { Index: clang/lib/Driver/ToolChains/Darwin.cpp =================================================================== --- clang/lib/Driver/ToolChains/Darwin.cpp +++ clang/lib/Driver/ToolChains/Darwin.cpp @@ -2374,6 +2374,10 @@ OS << "-target-sdk-version=" << SDKInfo->getVersion(); CC1Args.push_back(DriverArgs.MakeArgString(OS.str())); } + + // Enable compatibility mode for NSItemProviderCompletionHandler in + // Foundation/NSItemProvider.h. + CC1Args.push_back("-fcompatibility-qualified-id-block-type-checking"); } DerivedArgList * Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -8499,10 +8499,14 @@ RHSOPT->isObjCQualifiedIdType()); } - if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType()) - return finish(ObjCQualifiedIdTypesAreCompatible( - (BlockReturnType ? LHSOPT : RHSOPT), - (BlockReturnType ? RHSOPT : LHSOPT), false)); + if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType()) { + if (getLangOpts().CompatibilityQualifiedIdBlockParamTypeChecking) + return finish(ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, false)); + else + return finish(ObjCQualifiedIdTypesAreCompatible( + (BlockReturnType ? LHSOPT : RHSOPT), + (BlockReturnType ? RHSOPT : LHSOPT), false)); + } const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); Index: clang/include/clang/Driver/CC1Options.td =================================================================== --- clang/include/clang/Driver/CC1Options.td +++ clang/include/clang/Driver/CC1Options.td @@ -815,6 +815,9 @@ HelpText<"Use a signed type for wchar_t">; def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">, HelpText<"Use an unsigned type for wchar_t">; +def fcompatibility_qualified_id_block_param_type_checking : Flag<["-"], "fcompatibility-qualified-id-block-type-checking">, + HelpText<"Allow using blocks with parameters of more specific type than " + "the type system guarantees when a parameter is qualified id">; // FIXME: Remove these entirely once functionality/tests have been excised. def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -277,6 +277,9 @@ LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime") LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files") LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime") +BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0, + "compatibility mode for type checking block parameters " + "involving qualified id types") LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits