]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/doc/gcc/extensions-to-the-c-language-family/statements-and-declarations-in-expressions.rst
sphinx: add missing trailing newline
[thirdparty/gcc.git] / gcc / doc / gcc / extensions-to-the-c-language-family / statements-and-declarations-in-expressions.rst
1 ..
2 Copyright 1988-2022 Free Software Foundation, Inc.
3 This is part of the GCC manual.
4 For copying conditions, see the copyright.rst file.
5
6 .. index:: statements inside expressions, declarations inside expressions, expressions containing statements, macros, statements in expressions
7
8 .. _statement-exprs:
9
10 Statements and Declarations in Expressions
11 ******************************************
12
13 .. the above section title wrapped and causes an underfull hbox.. i
14 changed it from "within" to "in". -mew 4feb93
15
16 A compound statement enclosed in parentheses may appear as an expression
17 in GNU C. This allows you to use loops, switches, and local variables
18 within an expression.
19
20 Recall that a compound statement is a sequence of statements surrounded
21 by braces; in this construct, parentheses go around the braces. For
22 example:
23
24 .. code-block:: c++
25
26 ({ int y = foo (); int z;
27 if (y > 0) z = y;
28 else z = - y;
29 z; })
30
31 is a valid (though slightly more complex than necessary) expression
32 for the absolute value of ``foo ()``.
33
34 The last thing in the compound statement should be an expression
35 followed by a semicolon; the value of this subexpression serves as the
36 value of the entire construct. (If you use some other kind of statement
37 last within the braces, the construct has type ``void``, and thus
38 effectively no value.)
39
40 This feature is especially useful in making macro definitions 'safe' (so
41 that they evaluate each operand exactly once). For example, the
42 'maximum' function is commonly defined as a macro in standard C as
43 follows:
44
45 .. code-block:: c++
46
47 #define max(a,b) ((a) > (b) ? (a) : (b))
48
49 .. index:: side effects, macro argument
50
51 But this definition computes either :samp:`{a}` or :samp:`{b}` twice, with bad
52 results if the operand has side effects. In GNU C, if you know the
53 type of the operands (here taken as ``int``), you can avoid this
54 problem by defining the macro as follows:
55
56 .. code-block:: c++
57
58 #define maxint(a,b) \
59 ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
60
61 Note that introducing variable declarations (as we do in ``maxint``) can
62 cause variable shadowing, so while this example using the ``max`` macro
63 produces correct results:
64
65 .. code-block:: c++
66
67 int _a = 1, _b = 2, c;
68 c = max (_a, _b);
69
70 this example using maxint will not:
71
72 .. code-block:: c++
73
74 int _a = 1, _b = 2, c;
75 c = maxint (_a, _b);
76
77 This problem may for instance occur when we use this pattern recursively, like
78 so:
79
80 .. code-block:: c++
81
82 #define maxint3(a, b, c) \
83 ({int _a = (a), _b = (b), _c = (c); maxint (maxint (_a, _b), _c); })
84
85 Embedded statements are not allowed in constant expressions, such as
86 the value of an enumeration constant, the width of a bit-field, or
87 the initial value of a static variable.
88
89 If you don't know the type of the operand, you can still do this, but you
90 must use ``typeof`` or ``__auto_type`` (see :ref:`typeof`).
91
92 In G++, the result value of a statement expression undergoes array and
93 function pointer decay, and is returned by value to the enclosing
94 expression. For instance, if ``A`` is a class, then
95
96 .. code-block:: c++
97
98 A a;
99
100 ({a;}).Foo ()
101
102 constructs a temporary ``A`` object to hold the result of the
103 statement expression, and that is used to invoke ``Foo``.
104 Therefore the ``this`` pointer observed by ``Foo`` is not the
105 address of ``a``.
106
107 In a statement expression, any temporaries created within a statement
108 are destroyed at that statement's end. This makes statement
109 expressions inside macros slightly different from function calls. In
110 the latter case temporaries introduced during argument evaluation are
111 destroyed at the end of the statement that includes the function
112 call. In the statement expression case they are destroyed during
113 the statement expression. For instance,
114
115 .. code-block:: c++
116
117 #define macro(a) ({__typeof__(a) b = (a); b + 3; })
118 template<typename T> T function(T a) { T b = a; return b + 3; }
119
120 void foo ()
121 {
122 macro (X ());
123 function (X ());
124 }
125
126 has different places where temporaries are destroyed. For the
127 ``macro`` case, the temporary ``X`` is destroyed just after
128 the initialization of ``b``. In the ``function`` case that
129 temporary is destroyed when the function returns.
130
131 These considerations mean that it is probably a bad idea to use
132 statement expressions of this form in header files that are designed to
133 work with C++. (Note that some versions of the GNU C Library contained
134 header files using statement expressions that lead to precisely this
135 bug.)
136
137 Jumping into a statement expression with ``goto`` or using a
138 ``switch`` statement outside the statement expression with a
139 ``case`` or ``default`` label inside the statement expression is
140 not permitted. Jumping into a statement expression with a computed
141 ``goto`` (see :ref:`labels-as-values`) has undefined behavior.
142 Jumping out of a statement expression is permitted, but if the
143 statement expression is part of a larger expression then it is
144 unspecified which other subexpressions of that expression have been
145 evaluated except where the language definition requires certain
146 subexpressions to be evaluated before or after the statement
147 expression. A ``break`` or ``continue`` statement inside of
148 a statement expression used in ``while``, ``do`` or ``for``
149 loop or ``switch`` statement condition
150 or ``for`` statement init or increment expressions jumps to an
151 outer loop or ``switch`` statement if any (otherwise it is an error),
152 rather than to the loop or ``switch`` statement in whose condition
153 or init or increment expression it appears.
154 In any case, as with a function call, the evaluation of a
155 statement expression is not interleaved with the evaluation of other
156 parts of the containing expression. For example,
157
158 .. code-block:: c++
159
160 foo (), (({ bar1 (); goto a; 0; }) + bar2 ()), baz();
161
162 calls ``foo`` and ``bar1`` and does not call ``baz`` but
163 may or may not call ``bar2``. If ``bar2`` is called, it is
164 called after ``foo`` and before ``bar1``.