-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[ClangImporter] Look through __ended_by and __null_terminated #81630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fbb02a3
2fba980
51eb212
13080dc
048e43d
2840929
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#pragma once | ||
|
||
#include <ptrcheck.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this header file guaranteed to be on every platform we deploy to? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah probably not, no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or actually, maybe? We ship it with clang, and we ship clang with swift. So I think it ought to be there |
||
#include <stdarg.h> | ||
|
||
// Test __counted_by, __sized_by, __ended_by, __single, __indexable and __bidi_indexable pointers | ||
// in function parameters, return values, nested and unnested, pointing to void, char and int. | ||
// Also test VLAs, and incomplete pointer type with __counted_by, since they are pretty much the same | ||
// as __counted_by pointers in the -fbounds-safety model. | ||
|
||
#ifndef __unsafe_late_const | ||
#define __unsafe_late_const | ||
#endif | ||
|
||
int * __counted_by(len) a(int *__counted_by(len) p, int len); | ||
char * __counted_by(len) b(char *__counted_by(len) p, int len); | ||
char * __sized_by(len) c(char *__sized_by(len) p, int len); | ||
void * __sized_by(len) d(void *__sized_by(len) p, int len); | ||
int * __sized_by(len) e(int *__sized_by(len) p, int len); | ||
|
||
int * __ended_by(end) f(int *__ended_by(end) p, int * end); | ||
void * __ended_by(end) g(void *__ended_by(end) p, void * end); | ||
|
||
char * __null_terminated h(char *__null_terminated p); | ||
const char * i(const char * p); | ||
|
||
char * __single j(char *__single p); | ||
void *__single k(void *__single p); | ||
|
||
#if __has_ptrcheck | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are only There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Other macros defined in |
||
// __indexable and __bidi_indexable are not defined unless -fbounds-safety is enabled | ||
char * __indexable l(char *__indexable p); | ||
void *__indexable m(void *__indexable p); | ||
|
||
char * __bidi_indexable n(char *__bidi_indexable p); | ||
void * __bidi_indexable o(void *__bidi_indexable p); | ||
#endif | ||
|
||
#if !__cplusplus | ||
// No VLAs in C++ | ||
void p(int len, int p[len]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this isn't allowed in C++? (And can you add a comment with your explanation?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. VLAs are a C only feature |
||
#endif | ||
void q(int p[__counted_by(len)], int len); | ||
|
||
void r(int * __counted_by(*len) *__single p, int *len); | ||
char * __null_terminated *__null_terminated s(char * __null_terminated *__null_terminated p); | ||
char * __single *__single t(char * __single *__single p); | ||
|
||
const int len1 = 7; | ||
int * __counted_by(len1) u(int * __counted_by(len1) p); | ||
|
||
int len2 __unsafe_late_const; | ||
int * __counted_by(len2) v(int * __counted_by(len2) p); | ||
|
||
// -fbounds-safety can sometimes affect va_list | ||
void w(va_list p); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
#include <ptrcheck.h> | ||
|
||
extern int len; | ||
extern int a[__counted_by(len)]; // expected-note{{'a' declared here}} | ||
|
||
const char * __null_terminated b = "b"; | ||
|
||
extern int * __single * __single c; | ||
#if __has_ptrcheck | ||
extern int * __bidi_indexable d; | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#pragma once | ||
|
||
#include <ptrcheck.h> | ||
|
||
// Test __counted_by, __sized_by, __ended_by, __single, __indexable and __bidi_indexable pointers | ||
// in function parameters, return values, nested and unnested, pointing to void, char and int. | ||
// Also test VLAs, and incomplete pointer type with __counted_by, since they are pretty much the same | ||
// as __counted_by pointers in the -fbounds-safety model. | ||
|
||
struct a { | ||
int * __counted_by(len) a; | ||
int len; | ||
}; | ||
struct a *a(struct a); | ||
|
||
struct b { | ||
int * __sized_by(len) a; | ||
int len; | ||
}; | ||
struct b *b(struct b); | ||
|
||
struct c { | ||
char * __sized_by(len) a; | ||
int len; | ||
}; | ||
struct c *c(struct c); | ||
|
||
struct d { | ||
void * __sized_by(len) a; | ||
int len; | ||
}; | ||
struct d *d(struct d); | ||
|
||
struct e { | ||
void * __single a; | ||
int * __single b; | ||
}; | ||
struct e *e(struct e); | ||
|
||
struct f { | ||
const char * a; | ||
char * __null_terminated b; | ||
}; | ||
struct f *f(struct f); | ||
|
||
#if __has_ptrcheck | ||
struct g { | ||
void * __bidi_indexable a; | ||
int * __bidi_indexable b; | ||
}; | ||
struct g *g(struct g); | ||
|
||
struct h { | ||
void * __indexable a; | ||
int * __indexable b; | ||
}; | ||
struct h *h(struct h); | ||
#endif | ||
|
||
struct i { | ||
int len; | ||
int a[__counted_by(len)]; // expected-note {{field 'a' unavailable (cannot import)}} | ||
}; | ||
struct i *__single i(struct i *); | ||
|
||
const int len1 = 7; | ||
struct j { | ||
int * __counted_by(len1) a; | ||
void * __sized_by(len1) b; | ||
}; | ||
struct j *j(struct j); | ||
|
||
int len2 __unsafe_late_const; | ||
struct k { | ||
int * __counted_by(len2) a; | ||
void * __sized_by(len2) b; | ||
}; | ||
struct k *k(struct k); | ||
|
||
struct l { | ||
int * __ended_by(end) a; | ||
int * end; | ||
}; | ||
struct l *l(struct l); | ||
|
||
struct m { | ||
void * __ended_by(end) a; | ||
void * end; | ||
}; | ||
struct m *m(struct m); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module BoundsAttributedFunction { | ||
header "bounds-attributed-function.h" | ||
export * | ||
} | ||
module BoundsAttributedGlobal { | ||
header "bounds-attributed-global.h" | ||
export * | ||
} | ||
module BoundsAttributedStruct { | ||
header "bounds-attributed-struct.h" | ||
export * | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// 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 | ||
hnrklssn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// 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 | ||
// 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 | ||
|
||
// This test case checks that ClangImporter can import declarations using various bounds attributes, | ||
// rather than being marked unavailable because of an unknown type. | ||
|
||
// CHECK: func a(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<Int{{[0-9]+}}>! | ||
// CHECK-NEXT: func b(_ p: UnsafeMutablePointer<CChar>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<CChar>! | ||
// CHECK-NEXT: func c(_ p: UnsafeMutablePointer<CChar>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<CChar>! | ||
// CHECK-NEXT: func d(_ p: UnsafeMutableRawPointer!, _ len: Int{{[0-9]+}}) -> UnsafeMutableRawPointer! | ||
// CHECK-NEXT: func e(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}}) -> UnsafeMutablePointer<Int{{[0-9]+}}>! | ||
// CHECK-NEXT: func f(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ end: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>! | ||
// CHECK-NEXT: func g(_ p: UnsafeMutableRawPointer!, _ end: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer! | ||
// CHECK-NEXT: func h(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>! | ||
// CHECK-NEXT: func i(_ p: UnsafePointer<CChar>!) -> UnsafePointer<CChar>! | ||
// CHECK-NEXT: func j(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>! | ||
// CHECK-NEXT: func k(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer! | ||
|
||
// BOUNDS-SAFETY-NEXT: func l(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>! | ||
// BOUNDS-SAFETY-NEXT: func m(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer! | ||
// BOUNDS-SAFETY-NEXT: func n(_ p: UnsafeMutablePointer<CChar>!) -> UnsafeMutablePointer<CChar>! | ||
// BOUNDS-SAFETY-NEXT: func o(_ p: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer! | ||
|
||
// C-ONLY-NEXT: func p(_ len: Int{{[0-9]+}}, _ p: UnsafeMutablePointer<Int{{[0-9]+}}>!) | ||
|
||
// CHECK-NEXT: func q(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!, _ len: Int{{[0-9]+}}) | ||
// CHECK-NEXT: func r(_ p: UnsafeMutablePointer<UnsafeMutablePointer<Int{{[0-9]+}}>?>!, _ len: UnsafeMutablePointer<Int{{[0-9]+}}>!) | ||
// CHECK-NEXT: func s(_ p: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!) -> UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>! | ||
// CHECK-NEXT: func t(_ p: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!) -> UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>! | ||
// CHECK-NEXT: var len1: Int{{[0-9]+}} { get } | ||
// CHECK-NEXT: func u(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>! | ||
// CHECK-NEXT: var len2: Int{{[0-9]+}} | ||
// CHECK-NEXT: func v(_ p: UnsafeMutablePointer<Int{{[0-9]+}}>!) -> UnsafeMutablePointer<Int{{[0-9]+}}>! | ||
|
||
|
||
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -D C_ONLY | ||
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -cxx-interoperability-mode=default | ||
// 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 | ||
|
||
import BoundsAttributedFunction | ||
|
||
func call(_ mutIntPtr: UnsafeMutablePointer<CInt>, | ||
_ mutCharPtr: UnsafeMutablePointer<CChar>, | ||
_ mutRawPtr: UnsafeMutableRawPointer, | ||
_ constCharPtr: UnsafePointer<CChar>, | ||
_ mutMutIntPtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<CInt>?>!, | ||
_ mutMutCharPtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>!, | ||
_ int: CInt, | ||
_ args: CVaListPointer) { | ||
let _ = a(mutIntPtr, int) | ||
let _ = b(mutCharPtr, int) | ||
let _ = c(mutCharPtr, int) | ||
let _ = d(mutRawPtr, int) | ||
let _ = e(mutIntPtr, int) | ||
let _ = f(mutIntPtr, mutIntPtr) | ||
let _ = g(mutRawPtr, mutRawPtr) | ||
let _ = h(mutCharPtr) | ||
let _ = i(constCharPtr) | ||
let _ = j(mutCharPtr) | ||
let _ = k(mutRawPtr) | ||
|
||
#if BOUNDS_SAFETY | ||
let _ = l(mutIntPtr) | ||
let _ = m(mutRawPtr) | ||
let _ = n(mutIntPtr) | ||
let _ = o(mutRawPtr) | ||
#endif | ||
|
||
#if C_ONLY | ||
let _ = p(int, mutIntPtr) | ||
#endif | ||
|
||
let _ = q(mutIntPtr, int) | ||
let _ = r(mutMutIntPtrPtr, mutIntPtr) | ||
let _ = s(mutMutCharPtrPtr) | ||
let _ = t(mutMutCharPtrPtr) | ||
let _ = len1 | ||
let _ = u(mutIntPtr) | ||
let _ = len2 | ||
len2 = 37 | ||
let _ = v(mutIntPtr) | ||
|
||
let _ = w(args) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// 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 | ||
// 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 | ||
// 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 | ||
|
||
// This test case checks that ClangImporter can import declarations using various bounds attributes, | ||
// rather than being marked unavailable because of an unknown type. | ||
|
||
// CHECK: var len: Int32 | ||
// CHECK-NEXT: var a: <<error type>> | ||
// CHECK-NEXT: var b: UnsafePointer<CChar>! | ||
// CHECK-NEXT: var c: UnsafeMutablePointer<UnsafeMutablePointer<Int32>?>! | ||
// BOUNDS-SAFETY-NEXT: var d: UnsafeMutablePointer<Int32>! | ||
|
||
|
||
// RUN: %target-swift-frontend -Xcc -fexperimental-bounds-safety-attributes -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s | ||
// 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 | ||
// RUN: %target-swift-frontend -Xcc -fbounds-safety -disable-objc-interop -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs %s -D BOUNDS_SAFETY | ||
|
||
// 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 | ||
// 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 | ||
// 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 | ||
|
||
import BoundsAttributedGlobal | ||
|
||
func access() { | ||
#if VERIFY | ||
// rdar://152293598 ([ClangImporter] Importing global array errors on macOS and Linux, but not on Windows) | ||
// XFAIL: OS=windows-msvc | ||
let _ = a // expected-error{{cannot reference invalid declaration 'a'}} rdar://151665752 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @egorzhdan Do you have any idea why this wouldn't error on Windows? |
||
#endif | ||
let _ = b.pointee | ||
let _ = c.pointee!.pointee | ||
#if BOUNDS_SAFETY | ||
let _ = d.pointee | ||
#endif | ||
} |
Uh oh!
There was an error while loading. Please reload this page.