Skip to content

Commit fc67649

Browse files
authored
Merge pull request #82003 from hnrklssn/ignore-unused-bounds-attributes-6.2
[ClangImporter] Look through __ended_by and __null_terminated (#81630)
2 parents 0a70ec0 + 1f1cc3b commit fc67649

8 files changed

+449
-6
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,17 +425,15 @@ namespace {
425425
ImportResult VisitDynamicRangePointerType(
426426
const clang::DynamicRangePointerType *type) {
427427
// DynamicRangePointerType is a clang type representing a pointer with
428-
// an "ended_by" type attribute for -fbounds-safety. For now, we don't
429-
// import these into Swift.
430-
return Type();
428+
// an "ended_by" type attribute for -fbounds-safety.
429+
return Visit(type->desugar());
431430
}
432431

433432
ImportResult VisitValueTerminatedType(
434433
const clang::ValueTerminatedType *type) {
435434
// ValueTerminatedType is a clang type representing a pointer with
436-
// a "terminated_by" type attribute for -fbounds-safety. For now, we don't
437-
// import these into Swift.
438-
return Type();
435+
// a "terminated_by" type attribute for -fbounds-safety.
436+
return Visit(type->desugar());
439437
}
440438

441439
ImportResult VisitMemberPointerType(const clang::MemberPointerType *type) {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#pragma once
2+
3+
#include <ptrcheck.h>
4+
#include <stdarg.h>
5+
6+
// Test __counted_by, __sized_by, __ended_by, __single, __indexable and __bidi_indexable pointers
7+
// in function parameters, return values, nested and unnested, pointing to void, char and int.
8+
// Also test VLAs, and incomplete pointer type with __counted_by, since they are pretty much the same
9+
// as __counted_by pointers in the -fbounds-safety model.
10+
11+
#ifndef __unsafe_late_const
12+
#define __unsafe_late_const
13+
#endif
14+
15+
int * __counted_by(len) a(int *__counted_by(len) p, int len);
16+
char * __counted_by(len) b(char *__counted_by(len) p, int len);
17+
char * __sized_by(len) c(char *__sized_by(len) p, int len);
18+
void * __sized_by(len) d(void *__sized_by(len) p, int len);
19+
int * __sized_by(len) e(int *__sized_by(len) p, int len);
20+
21+
int * __ended_by(end) f(int *__ended_by(end) p, int * end);
22+
void * __ended_by(end) g(void *__ended_by(end) p, void * end);
23+
24+
char * __null_terminated h(char *__null_terminated p);
25+
const char * i(const char * p);
26+
27+
char * __single j(char *__single p);
28+
void *__single k(void *__single p);
29+
30+
#if __has_ptrcheck
31+
// __indexable and __bidi_indexable are not defined unless -fbounds-safety is enabled
32+
char * __indexable l(char *__indexable p);
33+
void *__indexable m(void *__indexable p);
34+
35+
char * __bidi_indexable n(char *__bidi_indexable p);
36+
void * __bidi_indexable o(void *__bidi_indexable p);
37+
#endif
38+
39+
#if !__cplusplus
40+
// No VLAs in C++
41+
void p(int len, int p[len]);
42+
#endif
43+
void q(int p[__counted_by(len)], int len);
44+
45+
void r(int * __counted_by(*len) *__single p, int *len);
46+
char * __null_terminated *__null_terminated s(char * __null_terminated *__null_terminated p);
47+
char * __single *__single t(char * __single *__single p);
48+
49+
const int len1 = 7;
50+
int * __counted_by(len1) u(int * __counted_by(len1) p);
51+
52+
int len2 __unsafe_late_const;
53+
int * __counted_by(len2) v(int * __counted_by(len2) p);
54+
55+
// -fbounds-safety can sometimes affect va_list
56+
void w(va_list p);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
#include <ptrcheck.h>
4+
5+
extern int len;
6+
extern int a[__counted_by(len)]; // expected-note{{'a' declared here}}
7+
8+
const char * __null_terminated b = "b";
9+
10+
extern int * __single * __single c;
11+
#if __has_ptrcheck
12+
extern int * __bidi_indexable d;
13+
#endif
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#pragma once
2+
3+
#include <ptrcheck.h>
4+
5+
// Test __counted_by, __sized_by, __ended_by, __single, __indexable and __bidi_indexable pointers
6+
// in function parameters, return values, nested and unnested, pointing to void, char and int.
7+
// Also test VLAs, and incomplete pointer type with __counted_by, since they are pretty much the same
8+
// as __counted_by pointers in the -fbounds-safety model.
9+
10+
struct a {
11+
int * __counted_by(len) a;
12+
int len;
13+
};
14+
struct a *a(struct a);
15+
16+
struct b {
17+
int * __sized_by(len) a;
18+
int len;
19+
};
20+
struct b *b(struct b);
21+
22+
struct c {
23+
char * __sized_by(len) a;
24+
int len;
25+
};
26+
struct c *c(struct c);
27+
28+
struct d {
29+
void * __sized_by(len) a;
30+
int len;
31+
};
32+
struct d *d(struct d);
33+
34+
struct e {
35+
void * __single a;
36+
int * __single b;
37+
};
38+
struct e *e(struct e);
39+
40+
struct f {
41+
const char * a;
42+
char * __null_terminated b;
43+
};
44+
struct f *f(struct f);
45+
46+
#if __has_ptrcheck
47+
struct g {
48+
void * __bidi_indexable a;
49+
int * __bidi_indexable b;
50+
};
51+
struct g *g(struct g);
52+
53+
struct h {
54+
void * __indexable a;
55+
int * __indexable b;
56+
};
57+
struct h *h(struct h);
58+
#endif
59+
60+
struct i {
61+
int len;
62+
int a[__counted_by(len)]; // expected-note {{field 'a' unavailable (cannot import)}}
63+
};
64+
struct i *__single i(struct i *);
65+
66+
const int len1 = 7;
67+
struct j {
68+
int * __counted_by(len1) a;
69+
void * __sized_by(len1) b;
70+
};
71+
struct j *j(struct j);
72+
73+
int len2 __unsafe_late_const;
74+
struct k {
75+
int * __counted_by(len2) a;
76+
void * __sized_by(len2) b;
77+
};
78+
struct k *k(struct k);
79+
80+
struct l {
81+
int * __ended_by(end) a;
82+
int * end;
83+
};
84+
struct l *l(struct l);
85+
86+
struct m {
87+
void * __ended_by(end) a;
88+
void * end;
89+
};
90+
struct m *m(struct m);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module BoundsAttributedFunction {
2+
header "bounds-attributed-function.h"
3+
export *
4+
}
5+
module BoundsAttributedGlobal {
6+
header "bounds-attributed-global.h"
7+
export *
8+
}
9+
module BoundsAttributedStruct {
10+
header "bounds-attributed-struct.h"
11+
export *
12+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %target-swift-ide-test -Xcc -fexperimental-bounds-safety-attributes -print-module -module-to-print=BoundsAttributedFunction -I %S/Inputs -source-filename=x | %FileCheck %s --check-prefixes=CHECK,C-ONLY
2+
// RUN: %target-swift-ide-test -Xcc -fexperimental-bounds-safety-attributes -print-module -module-to-print=BoundsAttributedFunction -I %S/Inputs -source-filename=x -cxx-interoperability-mode=default | %FileCheck %s
3+
// RUN: %target-swift-ide-test -Xcc -fbounds-safety -disable-objc-interop -print-module -module-to-print=BoundsAttributedFunction -I %S/Inputs -source-filename=x | %FileCheck %s --check-prefixes=CHECK,BOUNDS-SAFETY,C-ONLY
4+
5+
// This test case checks that ClangImporter can import declarations using various bounds attributes,
6+
// rather than being marked unavailable because of an unknown type.
7+
8+
// CHECK: func a(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<Int{{[0-9]+}}>!
9+
// CHECK-NEXT: func b(_ p: UnsafeMutablePointer<CChar>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<CChar>!
10+
// CHECK-NEXT: func c(_ p: UnsafeMutablePointer<CChar>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<CChar>!
11+
// CHECK-NEXT: func d(_ p: UnsafeMutableRawPointer!, _ len: Int{{[0-9]+}}) -> UnsafeMutableRawPointer!
12+
// CHECK-NEXT: func e(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<Int{{[0-9]+}}>!
13+
// CHECK-NEXT: func f(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ end: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>!
14+
// CHECK-NEXT: func g(_ p: UnsafeMutableRawPointer!, _ end: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer!
15+
// CHECK-NEXT: func h(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>!
16+
// CHECK-NEXT: func i(_ p: UnsafePointer<CChar>!) -> UnsafePointer<CChar>!
17+
// CHECK-NEXT: func j(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>!
18+
// CHECK-NEXT: func k(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer!
19+
20+
// BOUNDS-SAFETY-NEXT: func l(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>!
21+
// BOUNDS-SAFETY-NEXT: func m(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer!
22+
// BOUNDS-SAFETY-NEXT: func n(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>!
23+
// BOUNDS-SAFETY-NEXT: func o(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer!
24+
25+
// C-ONLY-NEXT: func p(_ len: Int{{[0-9]+}}, _ p: UnsafeMutablePointer<Int{{[0-9]+}}>!)
26+
27+
// CHECK-NEXT: func q(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}})
28+
// CHECK-NEXT: func r(_ p: UnsafeMutablePointer<UnsafeMutablePointer<Int{{[0-9]+}}>?>!, _ len: UnsafeMutablePointer<Int{{[0-9]+}}>!)
29+
// CHECK-NEXT: func s(_ p: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!) -> UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!
30+
// CHECK-NEXT: func t(_ p: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!) -> UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!
31+
// CHECK-NEXT: let len1: Int{{[0-9]+}}
32+
// CHECK-NEXT: func u(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>!
33+
// CHECK-NEXT: var len2: Int{{[0-9]+}}
34+
// CHECK-NEXT: func v(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>!
35+
36+
37+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -D C_ONLY
38+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -cxx-interoperability-mode=default
39+
// RUN: %target-swift-frontend -Xcc -fbounds-safety -disable-objc-interop -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -D C_ONLY -D BOUNDS_SAFETY
40+
41+
import BoundsAttributedFunction
42+
43+
func call(_ mutIntPtr: UnsafeMutablePointer<CInt>,
44+
_ mutCharPtr: UnsafeMutablePointer<CChar>,
45+
_ mutRawPtr: UnsafeMutableRawPointer,
46+
_ constCharPtr: UnsafePointer<CChar>,
47+
_ mutMutIntPtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<CInt>?>!,
48+
_ mutMutCharPtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!,
49+
_ int: CInt,
50+
_ args: CVaListPointer) {
51+
let _ = a(mutIntPtr, int)
52+
let _ = b(mutCharPtr, int)
53+
let _ = c(mutCharPtr, int)
54+
let _ = d(mutRawPtr, int)
55+
let _ = e(mutIntPtr, int)
56+
let _ = f(mutIntPtr, mutIntPtr)
57+
let _ = g(mutRawPtr, mutRawPtr)
58+
let _ = h(mutCharPtr)
59+
let _ = i(constCharPtr)
60+
let _ = j(mutCharPtr)
61+
let _ = k(mutRawPtr)
62+
63+
#if BOUNDS_SAFETY
64+
let _ = l(mutIntPtr)
65+
let _ = m(mutRawPtr)
66+
let _ = n(mutIntPtr)
67+
let _ = o(mutRawPtr)
68+
#endif
69+
70+
#if C_ONLY
71+
let _ = p(int, mutIntPtr)
72+
#endif
73+
74+
let _ = q(mutIntPtr, int)
75+
let _ = r(mutMutIntPtrPtr, mutIntPtr)
76+
let _ = s(mutMutCharPtrPtr)
77+
let _ = t(mutMutCharPtrPtr)
78+
let _ = len1
79+
let _ = u(mutIntPtr)
80+
let _ = len2
81+
len2 = 37
82+
let _ = v(mutIntPtr)
83+
84+
let _ = w(args)
85+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-swift-ide-test -Xcc -fexperimental-bounds-safety-attributes -print-module -module-to-print=BoundsAttributedGlobal -I %S/Inputs -source-filename=x | %FileCheck %s --check-prefixes=CHECK,C-ONLY
2+
// RUN: %target-swift-ide-test -Xcc -fexperimental-bounds-safety-attributes -print-module -module-to-print=BoundsAttributedGlobal -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 -Xcc -std=c++20 | %FileCheck %s
3+
// RUN: %target-swift-ide-test -Xcc -fbounds-safety -disable-objc-interop -print-module -module-to-print=BoundsAttributedGlobal -I %S/Inputs -source-filename=x | %FileCheck %s --check-prefixes=CHECK,BOUNDS-SAFETY,C-ONLY
4+
5+
// This test case checks that ClangImporter can import declarations using various bounds attributes,
6+
// rather than being marked unavailable because of an unknown type.
7+
8+
// CHECK: var len: Int32
9+
// CHECK-NEXT: var a: <<error type>>
10+
// CHECK-NEXT: var b: UnsafePointer<CChar>!
11+
// CHECK-NEXT: var c: UnsafeMutablePointer<UnsafeMutablePointer<Int32>?>!
12+
// BOUNDS-SAFETY-NEXT: var d: UnsafeMutablePointer<Int32>!
13+
14+
15+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s
16+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -cxx-interoperability-mode=swift-6
17+
// RUN: %target-swift-frontend -Xcc -fbounds-safety -disable-objc-interop -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -D BOUNDS_SAFETY
18+
19+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -verify -verify-additional-file %S/Inputs/bounds-attributed-global.h -D VERIFY
20+
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -cxx-interoperability-mode=swift-6 -verify -verify-additional-file %S/Inputs/bounds-attributed-global.h -D VERIFY
21+
// RUN: %target-swift-frontend -Xcc -fbounds-safety -disable-objc-interop -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -verify -verify-additional-file %S/Inputs/bounds-attributed-global.h -D BOUNDS_SAFETY -D VERIFY
22+
23+
import BoundsAttributedGlobal
24+
25+
func access() {
26+
#if VERIFY
27+
// rdar://152293598 ([ClangImporter] Importing global array errors on macOS and Linux, but not on Windows)
28+
// XFAIL: OS=windows-msvc
29+
let _ = a // expected-error{{cannot reference invalid declaration 'a'}} rdar://151665752
30+
#endif
31+
let _ = b.pointee
32+
let _ = c.pointee!.pointee
33+
#if BOUNDS_SAFETY
34+
let _ = d.pointee
35+
#endif
36+
}

0 commit comments

Comments
 (0)