1
Fork 0

Auto merge of #39876 - frewsxcv:rollup, r=frewsxcv

Rollup of 12 pull requests

- Successful merges: #39775, #39793, #39804, #39834, #39836, #39839, #39840, #39843, #39844, #39846, #39857, #39861
- Failed merges:
This commit is contained in:
bors 2017-02-16 05:52:46 +00:00
commit d77af7f639
16 changed files with 363 additions and 131 deletions

View file

@ -26,6 +26,12 @@ use std::process::{Command, Stdio};
use build_helper::output;
#[cfg(not(target_os = "solaris"))]
const SH_CMD: &'static str = "sh";
// On Solaris, sh is the historical bourne shell, not a POSIX shell, or bash.
#[cfg(target_os = "solaris")]
const SH_CMD: &'static str = "bash";
use {Build, Compiler, Mode};
use util::{cp_r, libdir, is_dylib, cp_filtered, copy};
@ -69,7 +75,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
let src = build.out.join(host).join("doc");
cp_r(&src, &dst);
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust-Documentation")
.arg("--rel-manifest-dir=rustlib")
@ -119,7 +125,7 @@ pub fn mingw(build: &Build, host: &str) {
.arg(host);
build.run(&mut cmd);
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust-MinGW")
.arg("--rel-manifest-dir=rustlib")
@ -185,7 +191,7 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
}
// Finally, wrap everything up in a nice tarball!
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
@ -290,7 +296,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
let src = build.sysroot(compiler).join("lib/rustlib");
cp_r(&src.join(target), &dst);
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
@ -343,9 +349,10 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
let image_src = src.join("save-analysis");
let dst = image.join("lib/rustlib").join(target).join("analysis");
t!(fs::create_dir_all(&dst));
println!("image_src: {:?}, dst: {:?}", image_src, dst);
cp_r(&image_src, &dst);
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
@ -452,7 +459,7 @@ pub fn rust_src(build: &Build) {
build.run(&mut cmd);
// Create source tarball in rust-installer format
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/gen-installer.sh")))
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")
@ -610,7 +617,7 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
input_tarballs.push_str(&sanitize_sh(&mingw_installer));
}
let mut cmd = Command::new("sh");
let mut cmd = Command::new(SH_CMD);
cmd.arg(sanitize_sh(&build.src.join("src/rust-installer/combine-installers.sh")))
.arg("--product-name=Rust")
.arg("--rel-manifest-dir=rustlib")

View file

@ -261,36 +261,34 @@ The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution.
Another common problem in macro systems is variable capture. Heres a C
macro, using [a GNU C extension] to emulate Rusts expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
macro using a block with multiple statements.
```text
#define LOG(msg) ({ \
#define LOG(msg) do { \
int state = get_log_state(); \
if (state > 0) { \
printf("log(%d): %s\n", state, msg); \
} \
})
} while (0)
```
Heres a simple use case that goes terribly wrong:
```text
const char *state = "reticulating splines";
LOG(state)
LOG(state);
```
This expands to
```text
const char *state = "reticulating splines";
{
do {
int state = get_log_state();
if (state > 0) {
printf("log(%d): %s\n", state, state);
}
}
} while (0);
```
The second variable named `state` shadows the first one. This is a problem

View file

@ -99,7 +99,7 @@ created, we'll add it to our toml:
hello-world-derive = { path = "hello-world-derive" }
```
As for our the source of our `hello-world-derive` crate, here's an example:
As for the source of our `hello-world-derive` crate, here's an example:
```rust,ignore
extern crate proc_macro;

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="collections::vec::Vec&lt;*&gt;">
    <DisplayString>{{ size={len} }}</DisplayString>
    <Expand>
<Item Name="[size]" ExcludeView="simple">len</Item>
<Item Name="[capacity]" ExcludeView="simple">buf.cap</Item>
<ArrayItems>
<Size>len</Size>
<ValuePointer>buf.ptr.pointer.__0</ValuePointer>
</ArrayItems>
    </Expand>
  </Type>
<Type Name="collections::vec_deque::VecDeque&lt;*&gt;">
<DisplayString>{{ size={tail &lt;= head ? head - tail : buf.cap - tail + head} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">tail &lt;= head ? head - tail : buf.cap - tail + head</Item>
<Item Name="[capacity]" ExcludeView="simple">buf.cap</Item>
<CustomListItems>
<Variable Name="i" InitialValue="tail" />
<Size>tail &lt;= head ? head - tail : buf.cap - tail + head</Size>
<Loop>
<If Condition="i == head">
<Break/>
</If>
<Item>buf.ptr.pointer.__0 + i</Item>
<Exec>i = (i + 1 == buf.cap ? 0 : i + 1)</Exec>
</Loop>
</CustomListItems>
</Expand>
</Type>
<Type Name="collections::linked_list::LinkedList&lt;*&gt;">
<DisplayString>{{ size={len} }}</DisplayString>
<Expand>
<LinkedListItems>
<Size>len</Size>
<HeadPointer>*(collections::linked_list::Node&lt;$T1&gt; **)&amp;head</HeadPointer>
<NextPointer>*(collections::linked_list::Node&lt;$T1&gt; **)&amp;next</NextPointer>
<ValueNode>element</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="collections::string::String">
<DisplayString>{*(char**)this,[vec.len]}</DisplayString>
<StringView>*(char**)this,[vec.len]</StringView>
<Expand>
<Item Name="[size]" ExcludeView="simple">vec.len</Item>
<Item Name="[capacity]" ExcludeView="simple">vec.buf.cap</Item>
<ArrayItems>
<Size>vec.len</Size>
<ValuePointer>*(char**)this</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="core::ptr::Unique&lt;*&gt;">
<DisplayString>{{ Unique {*pointer.__0} }}</DisplayString>
<Expand>
<Item Name="[ptr]">pointer.__0</Item>
</Expand>
</Type>
<Type Name="core::ptr::Shared&lt;*&gt;">
<DisplayString>{{ Shared {*pointer.__0} }}</DisplayString>
<Expand>
<Item Name="[ptr]">pointer.__0</Item>
</Expand>
</Type>
<Type Name="core::option::Option&lt;*&gt;">
<DisplayString Condition="RUST$ENUM$DISR == 0x0">{{ None }}</DisplayString>
<DisplayString Condition="RUST$ENUM$DISR == 0x1">{{ Some {__0} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">(ULONG)(RUST$ENUM$DISR != 0)</Item>
<Item Name="[value]" ExcludeView="simple">__0</Item>
<ArrayItems>
<Size>(ULONG)(RUST$ENUM$DISR != 0)</Size>
<ValuePointer>&amp;__0</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="core::option::Option&lt;*&gt;" Priority="MediumLow">
<DisplayString Condition="*(PVOID *)this == nullptr">{{ None }}</DisplayString>
<DisplayString>{{ Some {($T1 *)this} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">(ULONG)(*(PVOID *)this != nullptr)</Item>
<Item Name="[value]" ExcludeView="simple" Condition="*(PVOID *)this != nullptr">($T1 *)this</Item>
<ArrayItems>
<Size>(ULONG)(*(PVOID *)this != nullptr)</Size>
<ValuePointer>($T1 *)this</ValuePointer>
</ArrayItems>
</Expand>
</Type>
</AutoVisualizer>

View file

@ -8,7 +8,7 @@ The build of the rust part is included with `make tidy` and can be run with `mak
# Manual build
To use manually, assuming antlr4 ist installed at `/usr/share/java/antlr-complete.jar`:
To use manually, assuming antlr4 is installed at `/usr/share/java/antlr-complete.jar`:
```
antlr4 RustLexer.g4
@ -20,8 +20,8 @@ for file in ../*/**.rs; do
done
```
Note That the `../*/**.rs` glob will match every `*.rs` file in the above
directory and all of its recursive children. This is a zsh extension.
Note that the `../*/**.rs` glob will match every `*.rs` file in the above
directory and all of its recursive children. This is a Zsh extension.
## Cleanup

View file

@ -52,11 +52,11 @@ pub trait ToOwned {
/// Basic usage:
///
/// ```
/// let s = "a"; // &str
/// let ss = s.to_owned(); // String
/// let s: &str = "a";
/// let ss: String = s.to_owned();
///
/// let v = &[1, 2]; // slice
/// let vv = v.to_owned(); // Vec
/// let v: &[i32] = &[1, 2];
/// let vv: Vec<i32> = v.to_owned();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn to_owned(&self) -> Self::Owned;

View file

@ -213,6 +213,102 @@ impl<T:Copy> Cell<T> {
pub fn get(&self) -> T {
unsafe{ *self.value.get() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T> Send for Cell<T> where T: Send {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for Cell<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Copy> Clone for Cell<T> {
#[inline]
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default> Default for Cell<T> {
/// Creates a `Cell<T>`, with the `Default` value for T.
#[inline]
fn default() -> Cell<T> {
Cell::new(Default::default())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:PartialEq + Copy> PartialEq for Cell<T> {
#[inline]
fn eq(&self, other: &Cell<T>) -> bool {
self.get() == other.get()
}
}
#[stable(feature = "cell_eq", since = "1.2.0")]
impl<T:Eq + Copy> Eq for Cell<T> {}
#[stable(feature = "cell_ord", since = "1.10.0")]
impl<T:PartialOrd + Copy> PartialOrd for Cell<T> {
#[inline]
fn partial_cmp(&self, other: &Cell<T>) -> Option<Ordering> {
self.get().partial_cmp(&other.get())
}
#[inline]
fn lt(&self, other: &Cell<T>) -> bool {
self.get() < other.get()
}
#[inline]
fn le(&self, other: &Cell<T>) -> bool {
self.get() <= other.get()
}
#[inline]
fn gt(&self, other: &Cell<T>) -> bool {
self.get() > other.get()
}
#[inline]
fn ge(&self, other: &Cell<T>) -> bool {
self.get() >= other.get()
}
}
#[stable(feature = "cell_ord", since = "1.10.0")]
impl<T:Ord + Copy> Ord for Cell<T> {
#[inline]
fn cmp(&self, other: &Cell<T>) -> Ordering {
self.get().cmp(&other.get())
}
}
#[stable(feature = "cell_from", since = "1.12.0")]
impl<T> From<T> for Cell<T> {
fn from(t: T) -> Cell<T> {
Cell::new(t)
}
}
impl<T> Cell<T> {
/// Creates a new `Cell` containing the given value.
///
/// # Examples
///
/// ```
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub const fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
}
}
/// Returns a reference to the underlying `UnsafeCell`.
///
@ -273,102 +369,6 @@ impl<T:Copy> Cell<T> {
&mut *self.value.get()
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T> Send for Cell<T> where T: Send {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> !Sync for Cell<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Copy> Clone for Cell<T> {
#[inline]
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default + Copy> Default for Cell<T> {
/// Creates a `Cell<T>`, with the `Default` value for T.
#[inline]
fn default() -> Cell<T> {
Cell::new(Default::default())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:PartialEq + Copy> PartialEq for Cell<T> {
#[inline]
fn eq(&self, other: &Cell<T>) -> bool {
self.get() == other.get()
}
}
#[stable(feature = "cell_eq", since = "1.2.0")]
impl<T:Eq + Copy> Eq for Cell<T> {}
#[stable(feature = "cell_ord", since = "1.10.0")]
impl<T:PartialOrd + Copy> PartialOrd for Cell<T> {
#[inline]
fn partial_cmp(&self, other: &Cell<T>) -> Option<Ordering> {
self.get().partial_cmp(&other.get())
}
#[inline]
fn lt(&self, other: &Cell<T>) -> bool {
self.get() < other.get()
}
#[inline]
fn le(&self, other: &Cell<T>) -> bool {
self.get() <= other.get()
}
#[inline]
fn gt(&self, other: &Cell<T>) -> bool {
self.get() > other.get()
}
#[inline]
fn ge(&self, other: &Cell<T>) -> bool {
self.get() >= other.get()
}
}
#[stable(feature = "cell_ord", since = "1.10.0")]
impl<T:Ord + Copy> Ord for Cell<T> {
#[inline]
fn cmp(&self, other: &Cell<T>) -> Ordering {
self.get().cmp(&other.get())
}
}
#[stable(feature = "cell_from", since = "1.12.0")]
impl<T: Copy> From<T> for Cell<T> {
fn from(t: T) -> Cell<T> {
Cell::new(t)
}
}
impl<T> Cell<T> {
/// Creates a new `Cell` containing the given value.
///
/// # Examples
///
/// ```
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub const fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
}
}
/// Sets the contained value.
///

View file

@ -36,7 +36,6 @@ use ty::fold::TypeFolder;
use ty::subst::Subst;
use util::nodemap::{FxHashMap, FxHashSet};
use std::cmp;
use std::fmt;
use syntax::ast;
use hir::{intravisit, Local, Pat};
@ -392,12 +391,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
return;
}
let end = cmp::min(4, impl_candidates.len());
let end = if impl_candidates.len() <= 5 {
impl_candidates.len()
} else {
4
};
err.help(&format!("the following implementations were found:{}{}",
&impl_candidates[0..end].iter().map(|candidate| {
format!("\n {:?}", candidate)
}).collect::<String>(),
if impl_candidates.len() > 4 {
if impl_candidates.len() > 5 {
format!("\nand {} others", impl_candidates.len() - 4)
} else {
"".to_owned()

View file

@ -441,7 +441,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>)
/// Perform robin hood bucket stealing at the given `bucket`. You must
/// also pass that bucket's displacement so we don't have to recalculate it.
///
/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
/// `hash`, `key`, and `val` are the elements to "robin hood" into the hashtable.
fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
mut displacement: usize,
mut hash: SafeHash,

View file

@ -13,11 +13,11 @@
//! The `std::sys` module is the abstracted interface through which
//! `std` talks to the underlying operating system. It has different
//! implementations for different operating system families, today
//! just Unix and Windows.
//! just Unix and Windows, and initial support for Redox.
//!
//! The centralization of platform-specific code in this module is
//! enforced by the "platform abstraction layer" tidy script in
//! `tools/tidy/pal.rs`.
//! `tools/tidy/src/pal.rs`.
//!
//! This module is closely related to the platform-independent system
//! integration code in `std::sys_common`. See that module's
@ -34,10 +34,6 @@
pub use self::imp::*;
#[cfg(target_os = "redox")]
#[path = "redox/mod.rs"]
mod imp;
#[cfg(unix)]
#[path = "unix/mod.rs"]
mod imp;
@ -45,3 +41,7 @@ mod imp;
#[cfg(windows)]
#[path = "windows/mod.rs"]
mod imp;
#[cfg(target_os = "redox")]
#[path = "redox/mod.rs"]
mod imp;

View file

@ -912,7 +912,7 @@ extern "system" {
pub fn Sleep(dwMilliseconds: DWORD);
pub fn GetProcessId(handle: HANDLE) -> DWORD;
pub fn GetUserProfileDirectoryW(hToken: HANDLE,
lpProfileDir: LPCWSTR,
lpProfileDir: LPWSTR,
lpcchSize: *mut DWORD) -> BOOL;
pub fn SetHandleInformation(hObject: HANDLE,
dwMask: DWORD,

View file

@ -0,0 +1,49 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
//~^ ERROR recursive static (see issue #29719)
struct StaticDoubleLinked {
prev: &'static StaticDoubleLinked,
next: &'static StaticDoubleLinked,
data: i32,
head: bool,
}
static L1: StaticDoubleLinked = StaticDoubleLinked{prev: &L3, next: &L2, data: 1, head: true};
//~^ ERROR recursive static (see issue #29719)
//~^^ ERROR recursive static (see issue #29719)
//~^^^ ERROR recursive static (see issue #29719)
static L2: StaticDoubleLinked = StaticDoubleLinked{prev: &L1, next: &L3, data: 2, head: false};
static L3: StaticDoubleLinked = StaticDoubleLinked{prev: &L2, next: &L1, data: 3, head: false};
pub fn main() {
unsafe { assert_eq!(S, *(S as *const *const u8)); }
let mut test_vec = Vec::new();
let mut cur = &L1;
loop {
test_vec.push(cur.data);
cur = cur.next;
if cur.head { break }
}
assert_eq!(&test_vec, &[1,2,3]);
let mut test_vec = Vec::new();
let mut cur = &L1;
loop {
cur = cur.prev;
test_vec.push(cur.data);
if cur.head { break }
}
assert_eq!(&test_vec, &[3,2,1]);
}

View file

@ -0,0 +1,37 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo<B> {
fn bar(&self){}
}
impl Foo<u8> for i8 {}
impl Foo<u16> for i8 {}
impl Foo<u32> for i8 {}
impl Foo<u64> for i8 {}
impl Foo<bool> for i8 {}
impl Foo<u16> for u8 {}
impl Foo<u32> for u8 {}
impl Foo<u64> for u8 {}
impl Foo<bool> for u8 {}
impl Foo<u8> for bool {}
impl Foo<u16> for bool {}
impl Foo<u32> for bool {}
impl Foo<u64> for bool {}
impl Foo<bool> for bool {}
impl Foo<i8> for bool {}
fn main() {
Foo::<i32>::bar(&1i8);
Foo::<i32>::bar(&1u8);
Foo::<i32>::bar(&true);
}

View file

@ -0,0 +1,43 @@
error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:34:5
|
34 | Foo::<i32>::bar(&1i8);
| ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `i8`
|
= help: the following implementations were found:
<i8 as Foo<u8>>
<i8 as Foo<u16>>
<i8 as Foo<u32>>
<i8 as Foo<u64>>
<i8 as Foo<bool>>
= note: required by `Foo::bar`
error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:35:5
|
35 | Foo::<i32>::bar(&1u8);
| ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `u8`
|
= help: the following implementations were found:
<u8 as Foo<u16>>
<u8 as Foo<u32>>
<u8 as Foo<u64>>
<u8 as Foo<bool>>
= note: required by `Foo::bar`
error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
--> $DIR/issue-39802-show-5-trait-impls.rs:36:5
|
36 | Foo::<i32>::bar(&true);
| ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
|
= help: the following implementations were found:
<bool as Foo<u8>>
<bool as Foo<u16>>
<bool as Foo<u32>>
<bool as Foo<u64>>
and 2 others
= note: required by `Foo::bar`
error: aborting due to 3 previous errors

View file

@ -166,7 +166,7 @@ pub fn check(path: &Path, bad: &mut bool) {
// FIXME get this whitelist empty.
let whitelist = vec![
"abi_ptx", "simd", "static_recursion",
"abi_ptx", "simd",
"cfg_target_has_atomic",
"unboxed_closures", "stmt_expr_attributes",
"cfg_target_thread_local", "unwind_attributes",