[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
NoQ planned changes to this revision. NoQ added a comment. Todo: - See if the extra __kindofs leak into diagnostic messages. - Test how this behaves in cases (2) and (4), add tests. - Add tests for the recursive `__kindof` specifier merge (i.e. properly merge the second `__kindof` in `NSSet<__kindof NSArray<__kindof NSString>>`). https://reviews.llvm.org/D33191 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
xazax.hun added a comment. In https://reviews.llvm.org/D33191#758583, @NoQ wrote: > I think i found a relatively clean way of storing the kindof specifiers, > which is within the most-specialized type object itself. > > Like, if we see `Foo` being casted to `Foo<__kindof X, Y>` and in > another place to `Foo `, then we'd store `Foo<__kindof X, > __kindof Y>` in our map. Great idea! I also think this approach is superior to the previous one. https://reviews.llvm.org/D33191 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
NoQ updated this revision to Diff 99444. NoQ added a comment. Added a bit more info in the code comments. https://reviews.llvm.org/D33191 Files: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp test/Analysis/generics.m Index: test/Analysis/generics.m === --- test/Analysis/generics.m +++ test/Analysis/generics.m @@ -390,6 +390,39 @@ [arrayOfStrings containsObject:someString]; // no-warning } +NSArray *getStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray *getStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +void testKindofPropagation() { + NSArray *arr1 = + (NSArray *)getKindofStringMutableArray(); // no-warning + NSArray *arr2 = + (NSArray *)getKindofStringMutableArraySpecialized(); // no-warning + NSArray *arr3 = + (NSArray *)getStringMutableArray(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} + NSArray *arr4 = + (NSArray *)getStringMutableArraySpecialized(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -7140,4 +7173,644 @@ // CHECK-NEXT:file0 // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col37 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col57 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col59 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line393 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entered call from testKindofPropagation +// CHECK-NEXT: message +// CHECK-NEXT: Entered call from
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
NoQ updated this revision to Diff 99443. NoQ added a comment. I think i found a relatively clean way of storing the kindof specifiers, which is within the most-specialized type object itself. Like, if we see `Foo` being casted to `Foo<__kindof X, Y>` and in another place to `Foo `, then we'd store `Foo<__kindof X, __kindof Y>` in our map. https://reviews.llvm.org/D33191 Files: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp test/Analysis/generics.m Index: test/Analysis/generics.m === --- test/Analysis/generics.m +++ test/Analysis/generics.m @@ -390,6 +390,39 @@ [arrayOfStrings containsObject:someString]; // no-warning } +NSArray *getStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray *getStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +void testKindofPropagation() { + NSArray *arr1 = + (NSArray *)getKindofStringMutableArray(); // no-warning + NSArray *arr2 = + (NSArray *)getKindofStringMutableArraySpecialized(); // no-warning + NSArray *arr3 = + (NSArray *)getStringMutableArray(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} + NSArray *arr4 = + (NSArray *)getStringMutableArraySpecialized(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -7140,4 +7173,644 @@ // CHECK-NEXT:file0 // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col37 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col57 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col59 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line393 +// CHECK-NEXT: col1 +//
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
zaks.anna added inline comments. Comment at: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp:464 ASTContext ) { + if (hasKindofArgs(StaticUpperBound)) { +// If the upper bound type has more __kindof specs, we drop all the info, I am concerned that this might cause regressions as other logic in this function is not triggered when this condition fires. For example, this would only be safe if Current and StaticUpperBoound are the same type apart from __kindof modifier. https://reviews.llvm.org/D33191 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
xazax.hun added a comment. In https://reviews.llvm.org/D33191#756174, @NoQ wrote: > @Gábor: I didn't want to bother you with this, but i'm not entirely sure > about how to deal with these false positives; since you're the original > author of this check, if you see anything obviously wrong here please comment > on me :) I do not see anything obviously wrong. Of course this approach is very conservative, but in order to do it less conservatively probably we would need to store the type information separately for every type argument. Converting to that approach would be a lot of work, and it might make the check more complex. https://reviews.llvm.org/D33191 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
NoQ updated this revision to Diff 99150. NoQ added a comment. Cover more cases and be more conservative. @Gábor: I didn't want to bother you with this, but i'm not entirely sure about how to deal with these false positives; since you're the original author of this check, if you see anything obviously wrong here please comment on me :) https://reviews.llvm.org/D33191 Files: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp test/Analysis/generics.m Index: test/Analysis/generics.m === --- test/Analysis/generics.m +++ test/Analysis/generics.m @@ -390,6 +390,39 @@ [arrayOfStrings containsObject:someString]; // no-warning } +NSArray *getStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray *getStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArray() { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArraySpecialized() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +void testKindofPropagation() { + NSArray *arr1 = + (NSArray *)getKindofStringMutableArray(); // no-warning + NSArray *arr2 = + (NSArray *)getKindofStringMutableArraySpecialized(); // no-warning + NSArray *arr3 = + (NSArray *)getStringMutableArray(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} + NSArray *arr4 = + (NSArray *)getStringMutableArraySpecialized(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -7140,4 +7173,644 @@ // CHECK-NEXT:file0 // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line416 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line420 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col37 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line421 +// CHECK-NEXT:col57 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line421 +// CHECK-NEXT: col59 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: message +// CHECK-NEXT: Calling getStringMutableArray +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line393 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0
[PATCH] D33191: [analyzer] ObjCGenerics: account for __kindof specifiers met along a chain of casts.
NoQ created this revision. Herald added a subscriber: xazax.hun. `__kindof` type specifiers allow the developers to express their intent in discriminating between generic type arguments being matched exactly or allowing sub-types. When generics were introduced, it was already too late to add `__kindof` specifiers consistently across all the code. So for now in most code we believe it's all right not to have them, but we need to expect to have them at least in some places (which would normally be API declarations) and pick them up when they're present by loosening our dynamic type information from non-`__kindof` to `__kindof`, which would suppress some of the false "invalid cast" warnings. In the test provided, the `__kindof` is only present on the API return value; direct cast from the object created within the callee function is an error, however casting indirectly through a `__kindof` type should be possible, because just one `__kindof` annotation at the API declaration is considered to be enough to express the intent of "it was `__kindof` from the start but we didn't bother adding it". For now, we discard the original type information when we find `__kindof` specifiers in a chain of casts. https://reviews.llvm.org/D33191 Files: lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp test/Analysis/generics.m Index: test/Analysis/generics.m === --- test/Analysis/generics.m +++ test/Analysis/generics.m @@ -390,6 +390,25 @@ [arrayOfStrings containsObject:someString]; // no-warning } +NSArray *getStringMutableArray() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +NSArray<__kindof NSString *> *getKindofStringMutableArray() { + NSMutableArray *arr = + [[NSMutableArray alloc] init]; + return arr; +} + +void testKindofPropagation() { + NSArray *arr1 = + (NSArray *)getKindofStringMutableArray(); // no-warning + NSArray *arr2 = + (NSArray *)getStringMutableArray(); // expected-warning{{Conversion from value of type 'NSMutableArray *' to incompatible type 'NSArray *'}} +} + // CHECK: diagnostics // CHECK-NEXT: // CHECK-NEXT: @@ -7140,4 +7159,324 @@ // CHECK-NEXT:file0 // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line406 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line406 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line408 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line408 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line408 +// CHECK-NEXT:col3 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line408 +// CHECK-NEXT:col9 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line409 +// CHECK-NEXT:col37 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT:line409 +// CHECK-NEXT:col57 +// CHECK-NEXT:file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line409 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line409 +// CHECK-NEXT: col37 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line409 +// CHECK-NEXT: col59 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: