new file mode 100644
@@ -0,0 +1,8 @@
+fn main() -> i32 {
+ let ret = {
+ 1;
+ 2;
+ 0
+ };
+ ret
+}
new file mode 100644
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(
+ "%s\n" as *const str as *const i8,
+ s as *const str as *const i8,
+ );
+ }
+}
+
+fn main() -> i32 {
+ let cfg = cfg!(A);
+ if cfg {
+ print("A");
+ }
+ let cfg = cfg!(B);
+ if cfg {
+ print("B");
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,29 @@
+// { dg-output "\ntest10btrue2.15\ntest10bfalse2.151\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(
+ "%s\n" as *const str as *const i8,
+ s as *const str as *const i8,
+ );
+ }
+}
+
+fn main() -> i32 {
+ let a = concat!();
+ let b = concat!("test", 10, 'b', true, 2.15);
+ let c = concat!("test", 10, 'b', false, 2.15, 1u64);
+ print(a);
+ print(b);
+ print(c);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,31 @@
+// { dg-output "VALUE\nVALUE\n" }
+// { dg-set-compiler-env-var ENV_MACRO_TEST "VALUE" }
+#[rustc_builtin_macro]
+macro_rules! env {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(
+ "%s\n" as *const str as *const i8,
+ s as *const str as *const i8,
+ );
+ }
+}
+
+fn main() -> i32 {
+ let val0 = env!("ENV_MACRO_TEST");
+
+ print(val0);
+
+ let val1 = env!("ENV_MACRO_TEST",);
+
+ print(val1);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,46 @@
+// { dg-output "104\n33\n1\n" }
+#[rustc_builtin_macro]
+macro_rules! include_bytes {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(s, value);
+ }
+}
+
+fn main() -> i32 {
+ let bytes = include_bytes!("include.txt");
+
+ print_int(bytes[0] as i32);
+ print_int(bytes[14] as i32);
+
+ let the_bytes = b"hello, include!\n";
+
+ let x = bytes[0] == the_bytes[0]
+ && bytes[1] == the_bytes[1]
+ && bytes[2] == the_bytes[2]
+ && bytes[3] == the_bytes[3]
+ && bytes[4] == the_bytes[4]
+ && bytes[5] == the_bytes[5]
+ && bytes[6] == the_bytes[6]
+ && bytes[7] == the_bytes[7]
+ && bytes[8] == the_bytes[8]
+ && bytes[9] == the_bytes[9]
+ && bytes[10] == the_bytes[10]
+ && bytes[11] == the_bytes[11]
+ && bytes[12] == the_bytes[12]
+ && bytes[13] == the_bytes[13]
+ && bytes[14] == the_bytes[14]
+ && bytes[15] == the_bytes[15];
+
+ print_int(x as i32);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,27 @@
+// { dg-output "hello, include!\n" }
+#[rustc_builtin_macro]
+macro_rules! include_str {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(
+ "%s" as *const str as *const i8,
+ s as *const str as *const i8,
+ );
+ }
+}
+
+fn main() -> i32 {
+ // include_str! (and include_bytes!) allow for an optional trailing comma.
+ let my_str = include_str!("include.txt",);
+
+ print(my_str);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,25 @@
+// { dg-output "18\n21\n" }
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+ unsafe {
+ printf("%u\n\0" as *const str as *const i8, s);
+ }
+}
+
+#[rustc_builtin_macro]
+macro_rules! line {
+ () => {{}};
+}
+
+fn main() -> i32 {
+ let a = line!();
+ print(a);
+
+ let b = line!();
+ print(b);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,21 @@
+// { dg-output "rust/execute/torture/builtin_macros1.rs" }
+#[rustc_builtin_macro]
+macro_rules! file {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf("%s\n\0" as *const str as *const i8, s);
+ }
+}
+
+fn main() -> i32 {
+ print(file!());
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,28 @@
+// { dg-output "14\n42\n" }
+#[rustc_builtin_macro]
+macro_rules! column {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+ unsafe {
+ printf("%u\n\0" as *const str as *const i8, s);
+ }
+}
+
+fn main() -> i32 {
+ let c0 = column!();
+
+ print(c0);
+
+ let c1 = column!();
+
+ print(c1);
+
+ 0
+}
+
new file mode 100644
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[cfg(A)]
+fn test() {
+ unsafe {
+ let a = "test1\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+}
+
+#[cfg(B)]
+fn test() {
+ unsafe {
+ let a = "test2\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+}
+
+fn main() -> i32 {
+ test();
+ 0
+}
new file mode 100644
@@ -0,0 +1,31 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn test() {
+ #[cfg(A)]
+ unsafe {
+ let a = "test1\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ #[cfg(B)]
+ unsafe {
+ let a = "test2\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+}
+
+fn main() -> i32 {
+ test();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,37 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+ #[cfg(A)]
+ fn test(&self) {
+ unsafe {
+ let a = "test1\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+
+ #[cfg(B)]
+ fn test(&self) {
+ unsafe {
+ let a = "test2\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(123);
+ a.test();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,38 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "test1\ntest2\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+ #[cfg(A)]
+ fn test(&self) {
+ unsafe {
+ let a = "test1\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+
+ #[cfg(not(B))]
+ fn test2(&self) {
+ unsafe {
+ let a = "test2\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(123);
+ a.test();
+ a.test2();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+
+fn main() -> i32 {
+ let mut a = 0;
+
+ #[cfg(A)]
+ a = 3;
+
+ #[cfg(B)]
+ a = 40;
+
+ a - 3
+}
new file mode 100644
@@ -0,0 +1,41 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+ t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+ t.baz();
+}
+
+fn main() -> i32 {
+ let a;
+ a = Foo(123);
+ static_dispatch(&a);
+
+ let b: &dyn Bar;
+ b = &a;
+ dynamic_dispatch(b);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+ t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+ t.baz();
+}
+
+fn main() -> i32 {
+ let a;
+ a = &Foo(123);
+
+ static_dispatch(a);
+ dynamic_dispatch(a);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w" }
+const fn const_fn() -> usize {
+ 4
+}
+
+const FN_TEST: usize = const_fn();
+
+const TEST: usize = 2 + FN_TEST;
+
+fn main() -> i32 {
+ let a: [_; 12] = [5; TEST * 2];
+ a[6] - 5
+}
new file mode 100644
@@ -0,0 +1,16 @@
+// { dg-additional-options "-w" }
+const A: i32 = 1;
+const B: i32 = { A + 2 };
+
+const fn test() -> i32 {
+ B
+}
+
+const C: i32 = {
+ const a: i32 = 4;
+ test() + a
+};
+
+fn main() -> i32 {
+ C - 7
+}
new file mode 100644
@@ -0,0 +1,17 @@
+extern "rust-intrinsic" {
+ pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+}
+
+fn main() -> i32 {
+ let i = 15;
+ let mut i_copy = 16;
+
+ let i = &i as *const i32;
+ let i_copy = &mut i_copy as *mut i32;
+
+ unsafe {
+ copy_nonoverlapping(i, i_copy, 1);
+
+ *i_copy - *i
+ }
+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,3 @@
+fn main() -> i32 {
+ 0
+}
new file mode 100644
@@ -0,0 +1,33 @@
+# Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Execute tests, torture testing.
+
+# Load support procs.
+load_lib rust-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+set saved-dg-do-what-default ${dg-do-what-default}
+
+set dg-do-what-default "run"
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.rs]] "" ""
+set dg-do-what-default ${saved-dg-do-what-default}
+
+# All done.
+dg-finish
new file mode 100644
@@ -0,0 +1,5 @@
+// { dg-xfail-run-if "" { *-*-* } }
+
+fn main() -> i32 {
+ 1
+}
new file mode 100644
@@ -0,0 +1,19 @@
+// { dg-additional-options "-w" }
+// { dg-output "12" }
+mod modules;
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+ unsafe {
+ let fmt_s = "%d\n\0";
+ let fmt_p = fmt_s as *const str;
+ let fmt_i8 = fmt_p as *const i8;
+
+ printf(fmt_i8, modules::return_12());
+ }
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,5 @@
+fn main() -> i32 {
+ 1;
+ 2;
+ 0
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World" }*/
+extern "C" {
+ fn puts(s: *const i8);
+}
+
+fn main() -> i32 {
+ unsafe {
+ let a = "Hello World";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ puts(c);
+ }
+ 0
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn main() -> i32 {
+ unsafe {
+ let a = "Hello World %i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+ 0
+}
new file mode 100644
@@ -0,0 +1 @@
+hello, include!
new file mode 100644
@@ -0,0 +1,28 @@
+// { dg-additional-options "-w" }
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+struct Foo(i32, i32);
+impl Index<isize> for Foo {
+ type Output = i32;
+
+ fn index(&self, index: isize) -> &i32 {
+ if index == 0 {
+ &self.0
+ } else {
+ &self.1
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(1, 2);
+ let b = a[0];
+ let c = a[1];
+
+ c - b - 1
+}
new file mode 100644
@@ -0,0 +1,123 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+ None,
+ Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ fn get(self, slice: &T) -> Option<&Self::Output>;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.start > self.end
+ /* || self.end > slice.len() */
+ {
+ Option::None
+ } else {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,146 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+ None,
+ Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ fn get(self, slice: &T) -> Option<&Self::Output>;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+ type Output = T;
+
+ fn get(self, slice: &[T]) -> Option<&T> {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+ // SAFETY: the caller guarantees that `slice` is not dangling, so it
+ // cannot be longer than `isize::MAX`. They also guarantee that
+ // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+ // so the call to `add` is safe.
+ unsafe { slice.as_ptr().add(self) }
+ }
+
+ fn index(self, slice: &[T]) -> &T {
+ // N.B., use intrinsic indexing
+ // &(*slice)[self]
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.start > self.end
+ /* || self.end > slice.len() */
+ {
+ Option::None
+ } else {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+ let c = b[1];
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+fn main() -> i32 {
+ let foo: Foo<i32> = Foo(123);
+ let bar: &i32 = &foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,36 @@
+// { dg-additional-options "-w" }
+// { dg-output "outer\ninner\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn machin() {
+ unsafe {
+ let a = "outer\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+}
+
+fn bidule() {
+ fn machin() {
+ unsafe {
+ let a = "inner\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 123);
+ }
+ }
+
+ self::machin();
+ machin();
+}
+
+fn main() -> i32 {
+ bidule();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,159 @@
+// { dg-additional-options "-w" }
+// { dg-output "slice_access=3\n" }
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+ None,
+ Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ fn get(self, slice: &T) -> Option<&Self::Output>;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+ type Output = T;
+
+ fn get(self, slice: &[T]) -> Option<&T> {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+ // SAFETY: the caller guarantees that `slice` is not dangling, so it
+ // cannot be longer than `isize::MAX`. They also guarantee that
+ // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+ // so the call to `add` is safe.
+ unsafe { slice.as_ptr().add(self) }
+ }
+
+ fn index(self, slice: &[T]) -> &T {
+ // N.B., use intrinsic indexing
+ // &(*slice)[self]
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.start > self.end
+ /* || self.end > slice.len() */
+ {
+ Option::None
+ } else {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let array = [1, 2, 3, 4, 5];
+ let slice = &array[1..3];
+ let slice_access = slice[1];
+
+ unsafe {
+ let a = "slice_access=%i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, slice_access);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+// { dg-options "-w" }
+// { dg-output "1\n2\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait T {
+ fn foo(&self);
+}
+
+impl dyn T {
+ fn bar(&self) {
+ unsafe {
+ let a = "1\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf(c);
+ }
+ self.foo()
+ }
+}
+
+struct S;
+impl T for S {
+ fn foo(&self) {
+ unsafe {
+ let a = "2\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ printf(c);
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ <dyn T>::bar(&S);
+ 0
+}
new file mode 100644
@@ -0,0 +1,172 @@
+// { dg-options "-w" }
+// { dg-output "" }
+mod intrinsics {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
+ }
+}
+
+mod mem {
+ extern "rust-intrinsic" {
+ fn size_of<T>() -> usize;
+ }
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+pub enum Option<T> {
+ None,
+ Some(T),
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { intrinsics::offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+impl<T> [T] {
+ pub const fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ pub const fn len(&self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ fn get(self, slice: &T) -> Option<&Self::Output>;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for usize {
+ type Output = T;
+
+ fn get(self, slice: &[T]) -> Option<&T> {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
+ // SAFETY: the caller guarantees that `slice` is not dangling, so it
+ // cannot be longer than `isize::MAX`. They also guarantee that
+ // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+ // so the call to `add` is safe.
+ unsafe { slice.as_ptr().add(self) }
+ }
+
+ fn index(self, slice: &[T]) -> &T {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.start > self.end || self.end > slice.len() {
+ Option::None
+ } else {
+ unsafe { Option::Some(&*self.get_unchecked(slice)) }
+ }
+ }
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ unsafe {
+ let a = "slice-index\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = a[1];
+
+ b - 2
+}
new file mode 100644
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+fn main() -> i32 {
+ let foo = Foo(123);
+ let bar = &foo as &i32;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,33 @@
+/* { dg-output "Hello World 123\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo<T>(T);
+
+struct Bar<T> {
+ a: Foo<T>,
+ b: bool,
+ // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+fn test<T>(a: Bar<T>) -> Foo<T> {
+ a.a
+}
+
+fn main() -> i32 {
+ let a: Bar<i32> = Bar::<i32> {
+ a: Foo::<i32>(123),
+ b: true,
+ };
+ let result: Foo<i32> = test(a);
+
+ unsafe {
+ let a = "Hello World %i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, result.0);
+ }
+ 0
+}
new file mode 100644
@@ -0,0 +1,47 @@
+// { dg-output "Foo::bar\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo {}
+
+trait Bar {
+ fn bar(&self) {
+ unsafe {
+ let _a = "Bar::bar\n\0";
+ let _b = _a as *const str;
+ let _c = _b as *const i8;
+ printf(_c);
+ }
+ }
+}
+
+impl Foo {
+ fn bar(&self) {
+ unsafe {
+ let _a = "Foo::bar\n\0";
+ let _b = _a as *const str;
+ let _c = _b as *const i8;
+ printf(_c);
+ }
+ }
+}
+
+impl Bar for Foo {
+ fn bar(&self) {
+ unsafe {
+ let _a = "<Bar as Foo>::bar\n\0";
+ let _b = _a as *const str;
+ let _c = _b as *const i8;
+ printf(_c);
+ }
+ }
+}
+
+pub fn main() -> i32 {
+ let mut f = Foo {};
+ f.bar();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,35 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+ A,
+ B(T),
+}
+
+fn inspect(a: Foo<i32>) {
+ match a {
+ Foo::A => unsafe {
+ let a = "A\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ Foo::B(x) => unsafe {
+ let a = "Result: %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x);
+ },
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::B(123);
+ inspect(a);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,32 @@
+/* { dg-output "Result: 123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo<T> {
+ A,
+ B(T),
+}
+
+fn main() -> i32 {
+ let result = Foo::B(123);
+
+ match result {
+ Foo::A => unsafe {
+ let a = "A\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ Foo::B(x) => unsafe {
+ let a = "Result: %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x);
+ },
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-output "hi" } */
+fn main() -> i32 {
+ {
+ extern "C" {
+ fn puts(s: *const i8);
+ }
+
+ unsafe {
+ puts("hi\0" as *const str as *const i8);
+ }
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,9 @@
+struct Pattern(i32);
+
+fn pattern_as_arg(Pattern(value): Pattern) -> i32 {
+ value
+}
+
+fn main() -> i32 {
+ pattern_as_arg(Pattern(15)) - 15
+}
new file mode 100644
@@ -0,0 +1,13 @@
+macro_rules! add {
+ ($a:expr,$b:expr) => {
+ $a + $b
+ };
+}
+
+fn test() -> i32 {
+ add!(1 + 2, 3)
+}
+
+fn main() -> i32 {
+ test() - 6
+}
new file mode 100644
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(s, value);
+ }
+}
+
+macro_rules! add_exprs {
+ ($($e:expr)*) => (0 $(+ $e)*)
+}
+
+fn main() -> i32 {
+ // 1 + 2 + 15 => 18
+ print_int(add_exprs!(1 2 15));
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,25 @@
+// { dg-output "2" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0";
+ let s_p = s as *const str;
+ let c_p = s_p as *const i8;
+ unsafe {
+ printf(c_p, value);
+ }
+}
+
+macro_rules! add_exprs {
+ ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+ // 2
+ let a = add_exprs!(2);
+ print_int(a);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,22 @@
+// { dg-output "0\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(s, value);
+ }
+}
+
+macro_rules! add_exprs {
+ ($($e:expr)?) => (0 $(+ $e)?)
+}
+
+fn main() -> i32 {
+ // 0
+ print_int(add_exprs!());
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,22 @@
+// { dg-output "18\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(s, value);
+ }
+}
+
+macro_rules! add_exprs {
+ ($($e:expr)+) => (0 $(+ $e)+)
+}
+
+fn main() -> i32 {
+ // 1 + 2 + 15 => 18
+ print_int(add_exprs!(1 2 15));
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,22 @@
+// { dg-output "15\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn print_int(value: i32) {
+ let s = "%d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(s, value);
+ }
+}
+
+macro_rules! add_exprs {
+ ($($e:expr)*) => (15 $(+ $e)*)
+}
+
+fn main() -> i32 {
+ // 15
+ print_int(add_exprs!());
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,14 @@
+macro_rules! add {
+ ($e:literal) => {
+ 0 + $e
+ };
+ ($e:literal $($es:literal)*) => {
+ $e + add!($($es)*)
+ };
+}
+
+fn main() -> i32 {
+ let a = add!(1 2 3 10); // 16
+
+ a - 16
+}
new file mode 100644
@@ -0,0 +1,17 @@
+macro_rules! two {
+ (2) => {
+ 3
+ };
+}
+
+macro_rules! one {
+ (1) => {{
+ two!(2)
+ }};
+}
+
+fn main() -> i32 {
+ let a = one!(1);
+
+ a - 3
+}
new file mode 100644
@@ -0,0 +1,14 @@
+macro_rules! add {
+ ($e:literal) => {
+ 0 + $e
+ };
+ ($e:literal $($es:literal)*) => {
+ $e + add!($($es)*)
+ };
+}
+
+fn main() -> i32 {
+ let a = add!(3 4); // 7
+
+ a - 7
+}
new file mode 100644
@@ -0,0 +1,14 @@
+macro_rules! add {
+ ($e:expr, $($es:expr),*) => {
+ $e + add!($($es),*)
+ };
+ ($e:expr) => {
+ $e
+ };
+}
+
+fn main() -> i32 {
+ let a = add!(15, 2, 9); // 26
+
+ a - 26
+}
new file mode 100644
@@ -0,0 +1,40 @@
+// { dg-output "arg\narg\narg\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ unsafe {
+ let r_s = "arg\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ printf(c_p);
+ }
+}
+
+macro_rules! kw0 {
+ (keyword) => {
+ f();
+ };
+}
+
+macro_rules! kw1 {
+ (fn) => {
+ f();
+ };
+}
+
+macro_rules! kw2 {
+ (kw0 kw1 kw3) => {
+ f();
+ };
+}
+
+fn main() -> i32 {
+ kw0!(keyword);
+ kw1!(fn);
+ kw2!(kw0 kw1 kw3);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,14 @@
+macro_rules! add {
+ ($e:expr , $($es:expr) , *) => {
+ $e + add!($($es) , *)
+ };
+ ($e:expr) => {
+ $e
+ };
+}
+
+fn main() -> i32 {
+ let a = add!(15, 2, 9); // 26
+
+ a - 26
+}
new file mode 100644
@@ -0,0 +1,15 @@
+macro_rules! add_parens {
+ ($($rep:ident ( ) )*) => {
+ { 0 $(+ $rep ( ))* }
+ };
+}
+
+fn f() -> i32 {
+ 1
+}
+
+fn main() -> i32 {
+ let a = add_parens!(f() f() f());
+
+ a - 3
+}
new file mode 100644
@@ -0,0 +1,27 @@
+// { dg-output "1\n2\nNaN\n3\n" }
+
+macro_rules! print_num {
+ ($l:literal) => {{
+ unsafe {
+ printf("%d\n\0" as *const str as *const i8, $l);
+ }
+ }};
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+// Check to make sure that expanding macros does not break the flow of calls
+fn main() -> i32 {
+ print_num!(1);
+ print_num!(2);
+
+ unsafe {
+ printf("NaN\n\0" as *const str as *const i8);
+ }
+
+ print_num!(3);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,19 @@
+trait Valuable {
+ const VALUE: i32;
+}
+
+struct Something;
+
+macro_rules! implement {
+ () => {
+ const VALUE: i32 = 18;
+ };
+}
+
+impl Valuable for Something {
+ implement!();
+}
+
+fn main() -> i32 {
+ Something::VALUE - 18
+}
new file mode 100644
@@ -0,0 +1,9 @@
+macro_rules! repeat {
+ ( $( $i:literal ),* ; $( $j:literal ),* ) => (( $( ($i,$j) ),* ))
+}
+
+fn main() -> i32 {
+ let t = repeat!(1, 1; 2, 2);
+
+ t.0 .0 + t.0 .1 + t.1 .0 + t.1 .1 - 6
+}
new file mode 100644
@@ -0,0 +1,13 @@
+macro_rules! t {
+ ($t:tt) => {
+ $t
+ };
+}
+
+fn frob() -> i32 {
+ t!(15) + t!((14))
+}
+
+fn main() -> i32 {
+ frob() - 29
+}
new file mode 100644
@@ -0,0 +1,12 @@
+macro_rules! count_tt {
+ ($t:tt) => { 1 };
+ ($t:tt $($ts:tt)*) => { 1 + count_tt!($($ts)*) };
+}
+
+fn main() -> i32 {
+ let count = count_tt!(1 2 let a = 15) + count_tt!(1 2 (let a = 15));
+ // ^ ^ ^^^ ^ ^ ^^ ^ ^ ^^^^^^^^^^^^
+ // 6 token-trees 3 token-trees
+
+ count - 9
+}
new file mode 100644
@@ -0,0 +1,24 @@
+// { dg-additional-options "-frust-cfg=A" }
+
+macro_rules! attr {
+ (#[$attr:meta] $s:stmt) => {
+ #[$attr]
+ $s;
+ };
+}
+
+fn main() -> i32 {
+ let mut a = 0;
+
+ attr! {
+ #[cfg(A)]
+ a = 3
+ };
+
+ attr! {
+ #[cfg(B)]
+ a = 40
+ };
+
+ a - 3
+}
new file mode 100644
@@ -0,0 +1,13 @@
+macro_rules! t {
+ () => {
+ i32
+ };
+}
+
+fn id<T>(arg: T) -> T {
+ arg
+}
+
+fn main() -> i32 {
+ id::<t!()>(15) - 15
+}
new file mode 100644
@@ -0,0 +1,24 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+ unsafe {
+ printf("%u\n\0" as *const str as *const i8, s);
+ }
+}
+
+fn main() -> i32 {
+ let res = concat!("test2") == "test3";
+ if !res {
+ print(1);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,61 @@
+// { dg-output "invok\ninvok\ninvok\ninvok\ninvok\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ unsafe {
+ let r_s = "invok\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ printf(c_p);
+ }
+}
+
+macro_rules! invocation0 {
+ (valid) => {
+ f();
+ };
+ () => {};
+}
+
+macro_rules! invocation1 {
+ (valid) => {};
+ () => {
+ f();
+ };
+}
+
+macro_rules! invocation2 {
+ (valid) => {
+ f();
+ };
+ (invalid) => {};
+}
+
+macro_rules! invocation3 {
+ (this is a valid invocation) => {
+ f();
+ };
+ (not this one) => {};
+}
+
+macro_rules! invocation4 {
+ (fn f() {}) => {
+ f();
+ };
+ (not a keyword) => {};
+}
+
+fn main() -> i32 {
+ invocation0!(valid);
+ invocation1!();
+ invocation2!(valid);
+ invocation3!(this is a valid invocation);
+ invocation4!(
+ fn f() {}
+ );
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,25 @@
+// { dg-output "1\n" }
+#[rustc_builtin_macro]
+macro_rules! concat {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: u32) {
+ unsafe {
+ printf("%u\n\0" as *const str as *const i8, s);
+ }
+}
+
+fn main() -> i32 {
+ let mut x = concat!("x");
+ x = concat!("y");
+ if x == "y" {
+ print(1);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,32 @@
+// { dg-additional-options "-w -frust-cfg=A" }
+// { dg-output "A\nB\n" }
+#[rustc_builtin_macro]
+macro_rules! cfg {
+ () => {{}};
+}
+
+extern "C" {
+ fn printf(fmt: *const i8, ...);
+}
+
+fn print(s: &str) {
+ unsafe {
+ printf(
+ "%s\n" as *const str as *const i8,
+ s as *const str as *const i8,
+ );
+ }
+}
+
+fn main() -> i32 {
+ let cfg = cfg!(A) || cfg!(B);
+ if cfg {
+ print("A");
+ }
+ let cfg = cfg!(A) && cfg!(B);
+ if !cfg {
+ print("B");
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,15 @@
+macro_rules! add {
+ ($a:expr,$b:expr) => {
+ $a + $b
+ };
+ ($a:expr) => {
+ $a
+ };
+}
+
+fn main() -> i32 {
+ let mut x = add!(1);
+ x += add!(2, 3);
+
+ x - 6
+}
new file mode 100644
@@ -0,0 +1,13 @@
+macro_rules! add {
+ ($a:expr,$b:expr) => {{
+ $a + $b
+ }};
+}
+
+fn test() -> i32 {
+ add!(1, 2)
+}
+
+fn main() -> i32 {
+ test() - 3
+}
new file mode 100644
@@ -0,0 +1,12 @@
+macro_rules! Test {
+ ($a:ident, $b:ty) => {
+ struct $a($b);
+ };
+}
+
+Test!(Foo, i32);
+
+fn main() -> i32 {
+ let a = Foo(123);
+ a.0 - 123
+}
new file mode 100644
@@ -0,0 +1,28 @@
+// { dg-output "any\nany\nany\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ let r_s = "any\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ unsafe {
+ printf(c_p);
+ }
+}
+
+macro_rules! any {
+ ($($a:expr)*) => {
+ f();
+ };
+}
+
+fn main() -> i32 {
+ any!();
+ any!(a + b);
+ any!(a + b 14 "gcc");
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,27 @@
+// { dg-output "zo1\nzo1\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ let r_s = "zo1\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ unsafe {
+ printf(c_p);
+ }
+}
+
+macro_rules! zero_or_one {
+ ($($a:expr)?) => {
+ f();
+ };
+}
+
+fn main() -> i32 {
+ zero_or_one!();
+ zero_or_one!(f());
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,28 @@
+// { dg-output "oom\noom\noom\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ let r_s = "oom\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ unsafe {
+ printf(c_p);
+ }
+}
+
+macro_rules! one_or_more {
+ ($($a:expr)+) => {
+ f();
+ };
+}
+
+fn main() -> i32 {
+ one_or_more!(f());
+ one_or_more!(f() f());
+ one_or_more!(f() f() 15 + 12);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,58 @@
+// { dg-output "Foo::A\nFoo::B\nFoo::C x\nFoo::D 20 80\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+ A,
+ B,
+ C(char),
+ D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+ match f {
+ Foo::A => unsafe {
+ let a = "Foo::A\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ Foo::B => unsafe {
+ let a = "Foo::B\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ Foo::C(x) => unsafe {
+ let a = "Foo::C %c\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x);
+ },
+ Foo::D { x, y } => unsafe {
+ let a = "Foo::D %i %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x, y);
+ },
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::A;
+ let b = Foo::B;
+ let c = Foo::C('x');
+ let d = Foo::D { x: 20, y: 80 };
+
+ inspect(a);
+ inspect(b);
+ inspect(c);
+ inspect(d);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,41 @@
+// { dg-output "123\n80\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+ C(i32),
+ D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) -> i32 {
+ match f {
+ Foo::C(x) => x,
+ Foo::D { x, y } => y,
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::C(123);
+ let b = Foo::D { x: 20, y: 80 };
+
+ let result = inspect(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, result);
+ }
+
+ let result = inspect(b);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, result);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,51 @@
+// { dg-output "Foo::A\nwildcard\nwildcard\nFoo::D 20 80\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+ A,
+ B,
+ C(char),
+ D { x: i32, y: i32 },
+}
+
+fn inspect(f: Foo) {
+ match f {
+ Foo::A => unsafe {
+ let a = "Foo::A\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ Foo::D { x, y } => unsafe {
+ let a = "Foo::D %i %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, x, y);
+ },
+ _ => unsafe {
+ let a = "wildcard\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ },
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo::A;
+ let b = Foo::B;
+ let c = Foo::C('x');
+ let d = Foo::D { x: 20, y: 80 };
+
+ inspect(a);
+ inspect(b);
+ inspect(c);
+ inspect(d);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,49 @@
+// { dg-output "182 is more than 100\n55 is less than 100\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn foo(x: bool) -> i32 {
+ match x {
+ true => {
+ return 182;
+ }
+ false => {
+ return 55;
+ }
+ }
+}
+
+fn bar(y: i32) {
+ match y < 100 {
+ true => {
+ let a = "%i is less than 100\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ unsafe {
+ printf(c, y);
+ }
+ }
+ _ => {
+ let a = "%i is more than 100\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ unsafe {
+ printf(c, y);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = foo(true);
+ let b = foo(false);
+
+ bar(a);
+ bar(b);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,56 @@
+// { dg-output "a\nseven\nquote\nelse" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn foo(x: u8) {
+ match x {
+ b'a' => {
+ let a = "a\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ b'\x07' => {
+ let a = "seven\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ b'\'' => {
+ let a = "quote\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "else\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let x: u8 = 7;
+
+ foo(b'a');
+ foo(x);
+ foo(b'\'');
+ foo(b'\\');
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,56 @@
+// { dg-output "amazing\nwildcard\ncompiler\nproductivity\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn foo(x: char) {
+ match x {
+ 'a' => {
+ let a = "amazing\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ 'c' => {
+ let a = "compiler\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ 'p' => {
+ let a = "productivity\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "wildcard\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let p = 'p';
+
+ foo('a');
+ foo('b');
+ foo('c');
+ foo(p);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,109 @@
+// { dg-output "other!\nother!\nother!\nfifteen!\nfifteen!\nother!\nother!\nfifteen!\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn foo_i32(x: i32) {
+ match x {
+ 15 => {
+ let a = "fifteen!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "other!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn foo_isize(x: isize) {
+ match x {
+ 15 => {
+ let a = "fifteen!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "other!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn foo_u32(x: u32) {
+ match x {
+ 15 => {
+ let a = "fifteen!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "other!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn foo_usize(x: usize) {
+ match x {
+ 15 => {
+ let a = "fifteen!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "other!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let x = -2;
+ foo_i32(x);
+ foo_i32(334);
+ foo_isize(-4768);
+ foo_isize(15);
+
+ let y = 127;
+ foo_u32(15);
+ foo_u32(y);
+ foo_usize(2394);
+ foo_usize(15);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,56 @@
+// { dg-output "E::One\nE::Two\nbreak!\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum E {
+ One,
+ Two,
+ Other,
+}
+
+fn foo() {
+ let mut x = E::One;
+
+ loop {
+ match x {
+ E::One => {
+ let a = "E::One\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+
+ x = E::Two;
+ }
+ E::Two => {
+ let a = "E::Two\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+
+ x = E::Other;
+ }
+ _ => {
+ let a = "break!\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ foo();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,37 @@
+// { dg-output "zero to END_RANGE\nzero to END_RANGE\nelse\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+const END_RANGE: i32 = 15;
+
+fn foo(x: i32) {
+ match x {
+ 0..=END_RANGE => {
+ let a = "zero to END_RANGE\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+
+ _ => {
+ let a = "else\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ foo(11);
+ foo(15);
+ foo(21);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,45 @@
+// { dg-output "lowercase\nuppercase\nother\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+const BIG_A: char = 'A';
+const BIG_Z: char = 'Z';
+
+fn bar(x: char) {
+ match x {
+ 'a'..='z' => {
+ let a = "lowercase\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ BIG_A..=BIG_Z => {
+ let a = "uppercase\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ _ => {
+ let a = "other\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+ unsafe {
+ printf(c);
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ bar('b');
+ bar('X');
+ bar('!');
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,45 @@
+// { dg-output "x:15\ny:20\n" }
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+enum Foo {
+ A,
+ B,
+}
+
+fn inspect(f: Foo, g: u8) -> i32 {
+ match (f, g) {
+ (Foo::A, 1) => {
+ return 5;
+ }
+
+ (Foo::A, 2) => {
+ return 10;
+ }
+
+ (Foo::B, 2) => {
+ return 15;
+ }
+
+ _ => {
+ return 20;
+ }
+ }
+ return 25;
+}
+
+fn main() -> i32 {
+ let x = inspect(Foo::B, 2);
+ let y = inspect(Foo::B, 1);
+
+ unsafe {
+ printf("x:%d\n" as *const str as *const i8, x);
+ }
+ unsafe {
+ printf("y:%d\n" as *const str as *const i8, y);
+ }
+
+ y - x - 5
+}
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-output "124\n458" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+impl Foo {
+ fn bar(&self, i: i32) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0 + i);
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(123);
+ a.bar(1);
+
+ let b = &Foo(456);
+ b.bar(2);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,76 @@
+// { dg-additional-options "-w" }
+// { dg-output "foo_deref\nimm_deref\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Bar(i32);
+impl Bar {
+ fn foobar(self) -> i32 {
+ self.0
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+pub fn main() -> i32 {
+ let bar = Bar(123);
+ let foo: Foo<&Bar> = Foo(&bar);
+ let foobar: i32 = foo.foobar();
+
+ foobar - 123
+}
new file mode 100644
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+ fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+pub struct Bar(i32);
+impl Bar {
+ pub fn foobar(&mut self) -> i32 {
+ self.0
+ }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for Foo<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &mut self.0
+ }
+}
+
+pub fn main() -> i32 {
+ let bar = Bar(123);
+ let mut foo: Foo<Bar> = Foo(bar);
+ let foobar = foo.foobar();
+
+ unsafe {
+ let a = "foobar: %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, foobar);
+ }
+
+ foobar - 123
+}
new file mode 100644
@@ -0,0 +1,78 @@
+// { dg-additional-options "-w" }
+// { dg-output "mut_deref\nfoobar: 123\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+ fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+ fn deref(&self) -> &T {
+ *self
+ }
+}
+
+pub struct Bar(i32);
+impl Bar {
+ pub fn foobar(&mut self) -> i32 {
+ self.0
+ }
+}
+
+pub struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<T> DerefMut for Foo<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &mut self.0
+ }
+}
+
+pub fn main() -> i32 {
+ let mut bar = Bar(123);
+ let mut foo: Foo<&mut Bar> = Foo(&mut bar);
+ let foobar = foo.foobar();
+
+ unsafe {
+ let a = "foobar: %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, foobar);
+ }
+
+ foobar - 123
+}
new file mode 100644
@@ -0,0 +1,21 @@
+mod A {
+ pub mod B {
+ pub mod C {
+ pub struct Foo {
+ pub f: i32,
+ }
+ impl Foo {
+ pub fn new() -> Self {
+ Foo { f: 23i32 }
+ }
+ }
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = A::B::C::Foo::new();
+ let b = A::B::C::Foo { f: -23i32 };
+
+ a.f + b.f
+}
new file mode 100644
@@ -0,0 +1,3 @@
+fn return_12() -> i32 {
+ 12
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-output "3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+ type Output = i32;
+
+ fn add(self, other: i32) -> i32 {
+ let res = self + other;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ res
+ }
+}
+
+fn main() -> i32 {
+ let a;
+ a = 1 + 2;
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ unsafe {
+ let a = "foo_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ &self.0
+ }
+}
+
+fn main() -> i32 {
+ let foo: Foo<i32> = Foo(123);
+ let bar: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,37 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand"]
+pub trait BitAnd<Rhs = Self> {
+ type Output;
+
+ fn bitand(self, rhs: Rhs) -> Self::Output;
+}
+
+impl BitAnd for i32 {
+ type Output = i32;
+
+ fn bitand(self, other: i32) -> i32 {
+ let res = self & other;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ res
+ }
+}
+
+fn main() -> i32 {
+ let a;
+ a = 1 & 1;
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,31 @@
+// { dg-output "1\n" }
+// { dg-additional-options "-w" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "bitand_assign"]
+pub trait BitAndAssign<Rhs = Self> {
+ fn bitand_assign(&mut self, rhs: Rhs);
+}
+
+impl BitAndAssign for i32 {
+ fn bitand_assign(&mut self, other: i32) {
+ *self &= other;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *self);
+ }
+ }
+}
+
+fn main() -> i32 {
+ let mut a = 1;
+ a &= 1;
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+struct Foo(i32);
+
+impl Add for Foo {
+ type Output = Foo;
+
+ fn add(self, other: Foo) -> Foo {
+ let res = Foo(self.0 + other.0);
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res.0);
+ }
+
+ res
+ }
+}
+
+fn main() -> i32 {
+ let a;
+ a = Foo(1) + Foo(2);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,55 @@
+/* { dg-output "3\n3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+ type Output;
+
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Add for i32 {
+ type Output = i32;
+
+ fn add(self, other: i32) -> i32 {
+ let res = self + other;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ res
+ }
+}
+
+struct Foo(i32);
+impl Add for Foo {
+ type Output = Foo;
+
+ fn add(self, other: Foo) -> Foo {
+ let res = Foo(self.0 + other.0);
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res.0);
+ }
+
+ res
+ }
+}
+
+fn main() -> i32 {
+ let a;
+ a = Foo(1) + Foo(2);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,33 @@
+/* { dg-output "neg\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "neg"]
+pub trait Neg {
+ type Output;
+
+ fn neg(self) -> Self::Output;
+}
+
+impl Neg for i32 {
+ type Output = i32;
+
+ fn neg(self) -> i32 {
+ unsafe {
+ let a = "neg\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ -self
+ }
+}
+
+fn main() -> i32 {
+ let a: i32 = 1;
+ let _b = -a;
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,33 @@
+/* { dg-output "not\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "not"]
+pub trait Not {
+ type Output;
+
+ fn not(self) -> Self::Output;
+}
+
+impl Not for i32 {
+ type Output = i32;
+
+ fn not(self) -> i32 {
+ unsafe {
+ let a = "not\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ !self
+ }
+}
+
+fn main() -> i32 {
+ let a: i32 = 1;
+ let _b = !a;
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-output "add_assign\n3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "add_assign"]
+pub trait AddAssign<Rhs = Self> {
+ fn add_assign(&mut self, rhs: Rhs);
+}
+
+impl AddAssign for i32 {
+ fn add_assign(&mut self, other: i32) {
+ unsafe {
+ let a = "add_assign\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ *self += other
+ }
+}
+
+fn main() -> i32 {
+ let mut res = 1;
+ res += 2;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,42 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo: &i32 = &123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,58 @@
+/* { dg-output "imm_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo: &i32 = &123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,58 @@
+/* { dg-output "mut_deref\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+ type Target;
+
+ fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "imm_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+impl<T> Deref for &mut T {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe {
+ let a = "mut_deref\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+
+ *self
+ }
+}
+
+fn main() -> i32 {
+ let foo = &mut 123;
+ let res: i32 = *foo;
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, res);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<A> *const [A] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const A {
+ self as *const A
+ }
+}
+
+#[lang = "const_ptr"]
+impl<B> *const B {
+ pub const unsafe fn offset(self, count: isize) -> *const B {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const B {
+ self as *const B
+ }
+}
+
+const fn slice_from_raw_parts<C>(data: *const C, len: usize) -> *const [C] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<X> {
+ type Output;
+
+ unsafe fn get_unchecked(self, slice: *const X) -> *const Self::Output;
+
+ fn index(self, slice: &X) -> &Self::Output;
+}
+
+unsafe impl<Y> SliceIndex<[Y]> for Range<usize> {
+ type Output = [Y];
+
+ unsafe fn get_unchecked(self, slice: *const [Y]) -> *const [Y] {
+ unsafe {
+ let a: *const Y = slice.as_ptr();
+ let b: *const Y = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[Y]) -> &[Y] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,106 @@
+// { dg-additional-options "-w" }
+extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+#[lang = "Range"]
+pub struct Range<Idx> {
+ pub start: Idx,
+ pub end: Idx,
+}
+
+#[lang = "const_slice_ptr"]
+impl<T> *const [T] {
+ pub const fn len(self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+#[lang = "const_ptr"]
+impl<T> *const T {
+ pub const unsafe fn offset(self, count: isize) -> *const T {
+ unsafe { offset(self, count) }
+ }
+
+ pub const unsafe fn add(self, count: usize) -> Self {
+ unsafe { self.offset(count as isize) }
+ }
+
+ pub const fn as_ptr(self) -> *const T {
+ self as *const T
+ }
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ Repr {
+ raw: FatPtr { data, len },
+ }
+ .rust
+ }
+}
+
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+pub unsafe trait SliceIndex<T> {
+ type Output;
+
+ unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
+
+ fn index(self, slice: &T) -> &Self::Output;
+}
+
+unsafe impl<T> SliceIndex<[T]> for Range<usize> {
+ type Output = [T];
+
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ unsafe {
+ let a: *const T = slice.as_ptr();
+ let b: *const T = a.add(self.start);
+ slice_from_raw_parts(b, self.end - self.start)
+ }
+ }
+
+ fn index(self, slice: &[T]) -> &[T] {
+ unsafe { &*self.get_unchecked(slice) }
+ }
+}
+
+impl<T, I> Index<I> for [T]
+where
+ I: SliceIndex<[T]>,
+{
+ type Output = I::Output;
+
+ fn index(&self, index: I) -> &I::Output {
+ index.index(self)
+ }
+}
+
+fn main() -> i32 {
+ let a = [1, 2, 3, 4, 5];
+ let b = &a[1..3];
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,27 @@
+// { dg-additional-options "-w" }
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
+ unsafe {
+ let a = FatPtr { data, len };
+ let b = Repr { raw: a };
+ b.rust
+ }
+}
+
+fn main() -> i32 {
+ let a = 123;
+ let b: *const i32 = &a;
+ let c = slice_from_raw_parts(b, 1);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,57 @@
+// { dg-additional-options "-w" }
+// { dg-output "t1sz=5 t2sz=10" }
+mod mem {
+ extern "rust-intrinsic" {
+ #[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
+ fn transmute<T, U>(_: T) -> U;
+ }
+}
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct FatPtr<T> {
+ data: *const T,
+ len: usize,
+}
+
+pub union Repr<T> {
+ rust: *const [T],
+ rust_mut: *mut [T],
+ raw: FatPtr<T>,
+}
+
+impl<T> [T] {
+ pub const fn len(&self) -> usize {
+ unsafe { Repr { rust: self }.raw.len }
+ }
+}
+
+impl str {
+ pub const fn len(&self) -> usize {
+ self.as_bytes().len()
+ }
+
+ pub const fn as_bytes(&self) -> &[u8] {
+ unsafe { mem::transmute(self) }
+ }
+}
+
+fn main() -> i32 {
+ let t1: &str = "TEST1";
+ let t2: &str = &"TEST_12345";
+
+ let t1sz = t1.len();
+ let t2sz = t2.len();
+
+ unsafe {
+ let a = "t1sz=%i t2sz=%i\n";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, t1sz as i32, t2sz as i32);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,26 @@
+/* { dg-output "bar foo baz foobar\n" } */
+extern "C"
+{
+ fn printf(s: *const i8, ...);
+ fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
+}
+
+pub fn main () -> i32
+{
+ let f = "%s %s %s %s\n\0";
+ let s = "bar\0\
+ foo\
+ \x00\
+ baz\u{0000}\
+ foobar\0";
+ let cf = f as *const str as *const i8;
+ let cs = s as *const str as *const i8;
+ unsafe
+ {
+ let cs2 = memchr (cs, b'f', 5);
+ let cs3 = memchr (cs2, b'b', 5);
+ let cs4 = memchr (cs3, b'f', 5);
+ printf (cf, cs, cs2, cs3, cs4);
+ }
+ 0
+}
new file mode 100644
@@ -0,0 +1,52 @@
+/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct S;
+
+impl S {
+ fn f() {
+ unsafe {
+ let a = "S::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+trait T1 {
+ fn f() {
+ unsafe {
+ let a = "T1::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T1 for S {}
+
+trait T2 {
+ fn f() {
+ unsafe {
+ let a = "T2::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T2 for S {}
+
+fn main() -> i32 {
+ S::f();
+ <S as T1>::f();
+ <S as T2>::f();
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+struct S;
+impl S {
+ fn dynamic_dispatch(self, t: &dyn Bar) {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ t.baz();
+ }
+}
+
+pub fn main() -> i32 {
+ let a;
+ a = &Foo(123);
+
+ let b;
+ b = S;
+
+ b.dynamic_dispatch(a);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+ fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<'a, T> FnLike<&'a T, &'a T> for S {
+ fn call(&self, arg: &'a T) -> &'a T {
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ arg
+ }
+}
+
+fn indirect<F>(f: F)
+where
+ F: for<'a> FnLike<&'a isize, &'a isize>,
+{
+ let x = 3;
+ let y = f.call(&x);
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *y);
+ }
+}
+
+fn main() -> i32 {
+ indirect(S);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-output "3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+ fn call(&self, arg: A) -> R;
+}
+
+type FnObject<'b> = dyn for<'a> FnLike<&'a isize, &'a isize> + 'b;
+
+struct Identity;
+
+impl<'a, T> FnLike<&'a T, &'a T> for Identity {
+ fn call(&self, arg: &'a T) -> &'a T {
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ arg
+ }
+}
+
+fn call_repeatedly(f: &FnObject) {
+ let x = 3;
+ let y = f.call(&x);
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *y);
+ }
+}
+
+fn main() -> i32 {
+ call_repeatedly(&Identity);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,48 @@
+/* { dg-output "123\n456\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+
+ fn qux(&self) {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, 456);
+ }
+ }
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+ t.baz();
+ t.qux();
+}
+
+fn main() -> i32 {
+ let a;
+ a = Foo(123);
+
+ let b: &dyn Bar;
+ b = &a;
+ dynamic_dispatch(b);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-output "Bar::A = 456\n<Foo as Bar>::A = 456\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait Foo {
+ const A: i32 = 123;
+}
+
+struct Bar;
+impl Foo for Bar {
+ const A: i32 = 456;
+}
+
+fn main() -> i32 {
+ let a;
+ a = Bar::A;
+
+ unsafe {
+ let _a = "Bar::A = %i\n\0";
+ let _b = _a as *const str;
+ let _c = _b as *const i8;
+ printf(_c, a);
+ }
+
+ let b;
+ b = <Bar as Foo>::A;
+
+ unsafe {
+ let _a = "<Foo as Bar>::A = %i\n\0";
+ let _b = _a as *const str;
+ let _c = _b as *const i8;
+ printf(_c, b);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,43 @@
+/* { dg-output "123, 777" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait A {
+ fn a() -> i32 {
+ 123
+ }
+}
+
+trait B: A {
+ fn b() -> i32 {
+ <T as A>::a() + 456
+ }
+}
+
+struct T;
+// { dg-warning "struct is never constructed" "" { target *-*-* } .-1 }
+
+impl A for T {
+ fn a() -> i32 {
+ 321
+ }
+}
+
+struct S;
+impl A for S {}
+impl B for S {}
+
+fn main() -> i32 {
+ let aa = S::a();
+ let bb = S::b();
+
+ unsafe {
+ let a = "%i, %i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, aa, bb);
+ }
+ 0
+}
new file mode 100644
@@ -0,0 +1,34 @@
+/* { dg-output "123\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn type_bound<T: Bar>(t: &T) {
+ t.baz();
+}
+
+fn main() -> i32 {
+ let a;
+
+ a = &Foo(123);
+ type_bound(a);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-output "123\n123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn static_dispatch<T: Bar>(t: &T) {
+ t.baz();
+}
+
+fn dynamic_dispatch(t: &dyn Bar) {
+ t.baz();
+}
+
+fn main() -> i32 {
+ let a = &Foo(123);
+ static_dispatch(a);
+
+ let b: &dyn Bar = a;
+ dynamic_dispatch(b);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+ type A;
+
+ fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+ type A = i32;
+
+ fn bar(self) -> Self::A {
+ self.0
+ }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+ x.bar()
+}
+
+fn main() -> i32 {
+ let a;
+ a = S(123);
+
+ let bar: i32 = test_bar::<S>(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+ type A;
+
+ fn bar(self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+ type A = i32;
+
+ fn bar(self) -> Self::A {
+ self.0
+ }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+ x.bar()
+}
+
+fn main() -> i32 {
+ let a;
+ a = S(123);
+
+ let bar: i32 = test_bar(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+ type A;
+
+ fn bar(&self) -> Self::A;
+}
+
+struct S(i32);
+impl Foo for S {
+ type A = i32;
+
+ fn bar(&self) -> Self::A {
+ self.0
+ }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+ x.bar()
+}
+
+fn main() -> i32 {
+ let a;
+ a = S(123);
+
+ let bar: i32 = test_bar(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,35 @@
+/* { dg-output "3\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+trait FnLike<A, R> {
+ fn call(&self, arg: A) -> R;
+}
+
+struct S;
+impl<T> FnLike<&T, &T> for S {
+ fn call(&self, arg: &T) -> &T {
+ // { dg-warning "unused name .self." "" { target *-*-* } .-1 }
+ arg
+ }
+}
+
+fn indirect<F: FnLike<&isize, &isize>>(f: F) {
+ let x = 3;
+ let y = f.call(&x);
+
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, *y);
+ }
+}
+
+fn main() -> i32 {
+ indirect(S);
+
+ 0
+}
new file mode 100644
@@ -0,0 +1,23 @@
+// { dg-additional-options "-w" }
+
+extern "rust-intrinsic" {
+ fn transmute<T, U>(value: T) -> U;
+}
+
+struct WrapI {
+ inner: i32,
+}
+
+struct WrapF {
+ inner: f32,
+}
+
+fn main() -> i32 {
+ let f = 15.4f32;
+ let f_wrap = WrapF { inner: f };
+
+ let fst = unsafe { transmute::<f32, i32>(f) };
+ let snd = unsafe { transmute::<WrapF, WrapI>(f_wrap) };
+
+ fst - snd.inner
+}
new file mode 100644
@@ -0,0 +1,14 @@
+extern "rust-intrinsic" {
+ pub fn wrapping_add<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+ 5
+}
+
+fn main() -> u8 {
+ let l = 255;
+ let r = five();
+
+ unsafe { wrapping_add(l, r) - 4 }
+}
new file mode 100644
@@ -0,0 +1,20 @@
+extern "rust-intrinsic" {
+ pub fn wrapping_add<T>(l: T, r: T) -> T;
+ pub fn wrapping_sub<T>(l: T, r: T) -> T;
+ pub fn wrapping_mul<T>(l: T, r: T) -> T;
+}
+
+fn five() -> u8 {
+ 5
+}
+
+fn main() -> u8 {
+ let l = 255;
+ let r = five();
+
+ let ret0 = unsafe { wrapping_add(l, r) - 4 }; // 4
+ let ret1 = unsafe { wrapping_sub(r, l) - 6 }; // 6
+ let ret2 = unsafe { wrapping_mul(r, l) - 251 }; // 251
+
+ ret0 + ret1 + ret2
+}
new file mode 100644
@@ -0,0 +1,32 @@
+// { dg-output "macro\nmacro\nmacro\nmacro\n" }
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+fn f() {
+ let r_s = "macro\n\0";
+ let s_p = r_s as *const str;
+ let c_p = s_p as *const i8;
+
+ printf(c_p);
+}
+
+macro_rules! empty0 {
+ () => ( f() );
+}
+
+macro_rules! empty1 {
+ {} => { f() };
+}
+
+macro_rules! empty2 {
+ [] => [ f() ];
+}
+
+// using multiple parens/brackets/curlies variants allows us to make sure we
+// parse everything properly
+fn main() {
+ empty0!();
+ empty1!{};
+ empty2![];
+}