llvm-project/clang/test/Index/complete-blocks.m
Ilya Biryukov f27b77e5c5 [Sema] Populate declarations inside TypeLocs for some invalid types
This also reverts 282cae0b9a602267ad7ef622f770066491332a11 as the
particular crash is now handled by the new code.

Before this change Clang would always leave declarations inside the
type-locs as `null` if the declarator had an invalid type. This patch
populates declarations even for invalid types if the structure of the
type and the type-locs match.

There are certain cases that may still cause crashes. These happen when
Clang recovers the type in a way that is not reflected in the
declarator's structure, e.g. adding a pointer when it was not present in
the code for ObjC interfaces or ignoring pointers written in the code
in C++ with auto return type (`auto* foo() -> int`). Those cases look
fixable with a better recovery strategy and I plan to follow up with
more patches to address those.

The first attempt caused 31 tests from `check-clang` to crash due to
different structure of the types and type-locs after certain errors. The
good news is that the failure is localized and mismatch in structures is
discovered by assertions inside `DeclaratorLocFiller`. Some notable
cases caught by existing tests:
- Invalid chunks when type is fully ignored and replace with int or now.
  Crashed in `C/C2x/n2838.c`.
- Invalid return types in lambdas. Crashed in `CXX/drs/dr6xx.cpp`.
- Invalid member pointers. Crashed in `CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp`
- ObjC recovery that adds pointers. Crashed in `SemaObjC/blocks.m`

This change also updates the output of `Index/complete-blocks.m`.
Not entirely sure what causes the change, but the new function signature
is closer to the source code, so this seems like an improvement.

Reviewed By: aaron.ballman, erichkeane

Differential Revision: https://reviews.llvm.org/D146971
2023-04-06 19:02:41 +02:00

89 lines
3.2 KiB
Objective-C

// The line and column layout of this test is significant. Run lines
// are at the end.
typedef void (^block_t)(float f, double d);
void f(int (^block)(int x, int y));
void g(block_t b);
void test_f() {
}
@interface A
- method:(int (^)(int x, int y))b;
- method2:(block_t)b;
@end
void test_A(A *a) {
[a method:0];
}
@interface B
- method3:(int (^)(void))b;
@end
void test_B(B *b) {
[b method3:^int(void){ return 0; }];
}
@interface C
- method4:(void(^)(void))arg;
- method5:(void(^)())arg5;
@end
void test_C(C *c) {
[c method4:^{}];
}
@interface D
- method6:(void(^)(block_t block))arg;
@end
void test_D(D *d) {
[d method6:0];
}
@interface I1
- method7:(int (^_Nullable)(int x, int y))b;
@end
void f2(int (^_Nullable block)(int x, int y));
void test_f2(I1 *o) {
[o method7:0];
}
// Crash regression test. Param info for broken function types isn't available.
typedef UnresolvedType *(^XXX)(float);
@interface Foo
-(void) foo:(XXX)arg;
@end
void testUnresolved(Foo* f) {
[f foo:0];
}
// RUN: c-index-test -code-completion-at=%s:8:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText f}{LeftParen (}{Placeholder ^int(int x, int y)block}{RightParen )} (50)
// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{Placeholder ^(float f, double d)b}{RightParen )} (50)
// RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method2:}{Placeholder ^(float f, double d)b} (35)
// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method:}{Placeholder ^int(int x, int y)b} (35)
// RUN: c-index-test -code-completion-at=%s:25:6 %s | FileCheck -check-prefix=CHECK-CC3 %s
// CHECK-CC3: ObjCInstanceMethodDecl:{ResultType id}{TypedText method3:}{Placeholder ^int(void)b} (35)
// RUN: c-index-test -code-completion-at=%s:34:6 %s | FileCheck -check-prefix=CHECK-CC4 %s
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType id}{TypedText method4:}{Placeholder ^(void)arg} (35)
// CHECK-CC4: ObjCInstanceMethodDecl:{ResultType id}{TypedText method5:}{Placeholder ^(void)arg5} (35)
// RUN: c-index-test -code-completion-at=%s:25:15 %s | FileCheck -check-prefix=CHECK-CC5 %s
// CHECK-CC5: TypedefDecl:{TypedText block_t} (50)
// CHECK-CC5: TypedefDecl:{TypedText Class} (50)
// CHECK-CC5-NOT: test_A
// CHECK-CC5: {TypedText union} (50)
// RUN: c-index-test -code-completion-at=%s:42:6 %s | FileCheck -check-prefix=CHECK-CC6 %s
// CHECK-CC6: ObjCInstanceMethodDecl:{ResultType id}{TypedText method6:}{Placeholder ^(block_t block)arg} (35)
// RUN: c-index-test -code-completion-at=%s:50:1 %s | FileCheck -check-prefix=CHECK-CC7 %s
// CHECK-CC7: FunctionDecl:{ResultType void}{TypedText f2}{LeftParen (}{Placeholder ^int(int x, int y)block}{RightParen )} (50)
// RUN: c-index-test -code-completion-at=%s:50:6 %s | FileCheck -check-prefix=CHECK-CC8 %s
// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{TypedText method7:}{Placeholder ^int(int x, int y)b} (35)
// RUN: c-index-test -code-completion-at=%s:59:6 %s | FileCheck -check-prefix=CHECK-CC9 %s
// CHECK-CC9: ObjCInstanceMethodDecl:{ResultType void}{TypedText foo:}{Placeholder ^int *(float)arg} (35)