brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · ae20cf3 Raw
83 lines · c
1// RUN: %clang_cc1 -fsyntax-only -verify=expected,c -std=c99 %s2// RUN: %clang_cc1 -fsyntax-only -verify=expected,c -std=c11 %s3// RUN: %clang_cc1 -fsyntax-only -verify=expected,cpp -std=c++11 -x c++ %s4 5/* WG14 N1285: Clang 216 * Extending the lifetime of temporary objects (factored approach)7 *8 * This paper introduced the notion of an object with a temporary lifetime. Any9 * operation resulting in an rvalue of structure or union type which contains10 * an array results in an object with temporary lifetime.11 *12 * Even though this is a change for C11, we treat it as a DR and apply it13 * retroactively to earlier C language modes.14 */15 16// C11 6.2.4p8: A non-lvalue expression with structure or union type, where the17// structure or union contains a member with array type (including,18// recursively, members of all contained structures and unions) refers to an19// object with automatic storage duration and temporary lifetime. Its lifetime20// begins when the expression is evaluated and its initial value is the value21// of the expression. Its lifetime ends when the evaluation of the containing22// full expression or full declarator ends. Any attempt to modify an object23// with temporary lifetime results in undefined behavior.24 25struct X { int a[5]; };26struct X f(void);27 28union U { int a[10]; double d; };29union U g(void);30 31void sink(int *);32 33int func_return(void) {34  int *p = f().a; // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}35  p = f().a;      // expected-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}36  p = g().a;      // expected-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}37  sink(f().a);    // Ok38  return *f().a;  // Ok39}40 41int ternary(void) {42  int *p = (1 ? (struct X){ 0 } : f()).a; // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}43  int *r = (1 ? (union U){ 0 } : g()).a;  // expected-warning {{temporary whose address is used as value of local variable 'r' will be destroyed at the end of the full-expression}}44  p = (1 ? (struct X){ 0 } : f()).a;      // expected-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}45  sink((1 ? (struct X){ 0 } : f()).a);    // Ok46 47  // This intentionally gets one diagnostic in C and two in C++. In C, the48  // compound literal results in an lvalue, not an rvalue as it does in C++. So49  // only one branch results in a temporary in C but both branches do in C++.50  int *q = 1 ? (struct X){ 0 }.a : f().a; // expected-warning {{temporary whose address is used as value of local variable 'q' will be destroyed at the end of the full-expression}} \51                                             cpp-warning {{temporary whose address is used as value of local variable 'q' will be destroyed at the end of the full-expression}}52  q = 1 ? (struct X){ 0 }.a : f().a; // expected-warning {{object backing the pointer 'q' will be destroyed at the end of the full-expression}} \53                                        cpp-warning {{object backing the pointer 'q' will be destroyed at the end of the full-expression}}54  q = 1 ? (struct X){ 0 }.a : g().a; // expected-warning {{object backing the pointer 'q' will be destroyed at the end of the full-expression}} \55                                        cpp-warning {{object backing the pointer 'q' will be destroyed at the end of the full-expression}}56  sink(1 ? (struct X){ 0 }.a : f().a); // Ok57  return *(1 ? (struct X){ 0 }.a : f().a); // Ok58}59 60int comma(void) {61  struct X x;62  int *p = ((void)0, x).a; // c-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}63  p = ((void)0, x).a;      // c-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}64  sink(((void)0, x).a);    // Ok65  return *(((void)0, x).a);// Ok66}67 68int cast(void) {69  struct X x;70  int *p = ((struct X)x).a;  // expected-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}71  p = ((struct X)x).a;       // expected-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}72  sink(((struct X)x).a);     // Ok73  return *(((struct X)x).a); // Ok74}75 76int assign(void) {77  struct X x, s;78  int *p = (x = s).a;  // c-warning {{temporary whose address is used as value of local variable 'p' will be destroyed at the end of the full-expression}}79  p = (x = s).a;       // c-warning {{object backing the pointer 'p' will be destroyed at the end of the full-expression}}80  sink((x = s).a);     // Ok81  return *((x = s).a); // Ok82}83