In the following example, the block passed to the function is marked as noescape, which is incorrect as the noescape attribute applies to the reference:
typedef void (^BlockTy)();
__block S6 b5;
void noescapeFuncRefParam1(__attribute__((noescape)) BlockTy &&);
noescapeFuncRefParam1(^{ (void)b5; });This partially fixes PR50043.
rdar://77030453
We need to be checking that the parameter type is a block pointer type. A parameter of a type like id or void* does not have the enhanced semantics of noescape for blocks.
The inevitable weird C++ test case is:
struct NoescapeCtor { NoescapeCtor(__attribute__((noescape)) void (^)()); }; struct EscapeCtor { EscapeCtor(void (^)()); }; void helper1(NoescapeCtor a); void test1() { helper1(^{}); } // <- should be noescape void helper2(NoescapeCtor &&a); void test2() { helper2(^{}); } // <- should be noescape void helper3(__attribute__((noescape)) EscapeCtor &&a); void test3() { helper3(^{}); } // <- should not be noescapeYou should probably also test that calls to function templates behave according to the instantiated type of the parameter. I expect that that should just fall out from this implementation, which I think only triggers on non-dependent calls.