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