]>
Commit | Line | Data |
---|---|---|
b42b0c7f JR |
1 | From c35a3f519007af44c3b364b9af86f6a336f6411b Mon Sep 17 00:00:00 2001 |
2 | From: Thiago Macieira <thiago.macieira@intel.com> | |
3 | Date: Tue, 11 Feb 2014 16:17:46 -0800 | |
4 | Subject: [PATCH] Redo the Q_FOREACH loop control without GCC statement | |
5 | expressions | |
6 | ||
7 | It's possible to do without them, which probably makes the number of | |
8 | supported compilers a lot bigger: they just need to support decltype() | |
9 | or __typeof__. | |
10 | ||
11 | That includes the Intel compiler. The old code was also apparently | |
12 | working, but no one had realized the old workaround for some old version | |
13 | was still in place. | |
14 | ||
15 | The loop overhead is more or less the same. I have not done benchmarks, | |
16 | but inspection of the generated assembly shows more or less the same | |
17 | number of instructions. | |
18 | ||
19 | Change-Id: I32d499c84a6ddd19d994b49f17a469acb5c3a3f1 | |
20 | Reviewed-by: Olivier Goffart <ogoffart@woboq.com> | |
21 | Reviewed-by: Marc Mutz <marc.mutz@kdab.com> | |
22 | ||
23 | Backported to Qt 4 | |
24 | ||
25 | --- a/src/corelib/global/qglobal.h | |
26 | +++ b/src/corelib/global/qglobal.h | |
27 | @@ -2482,22 +2482,32 @@ typedef uint Flags; | |
28 | ||
29 | #endif /* Q_NO_TYPESAFE_FLAGS */ | |
30 | ||
31 | -#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_RVCT) | |
32 | +#if (defined(Q_CC_GNU) && !defined(Q_CC_RVCT)) | |
33 | /* make use of typeof-extension */ | |
34 | template <typename T> | |
35 | class QForeachContainer { | |
36 | public: | |
37 | - inline QForeachContainer(const T& t) : c(t), brk(0), i(c.begin()), e(c.end()) { } | |
38 | + inline QForeachContainer(const T& t) : c(t), i(c.begin()), e(c.end()), control(1) { } | |
39 | const T c; | |
40 | int brk; | |
41 | typename T::const_iterator i, e; | |
42 | + int control; | |
43 | }; | |
44 | ||
45 | +// Explanation of the control word: | |
46 | +// - it's initialized to 1 | |
47 | +// - that means both the inner and outer loops start | |
48 | +// - if there were no breaks, at the end of the inner loop, it's set to 0, which | |
49 | +// causes it to exit (the inner loop is run exactly once) | |
50 | +// - at the end of the outer loop, it's inverted, so it becomes 1 again, allowing | |
51 | +// the outer loop to continue executing | |
52 | +// - if there was a break inside the inner loop, it will exit with control still | |
53 | +// set to 1; in that case, the outer loop will invert it to 0 and will exit too | |
54 | #define Q_FOREACH(variable, container) \ | |
55 | for (QForeachContainer<__typeof__(container)> _container_(container); \ | |
56 | - !_container_.brk && _container_.i != _container_.e; \ | |
57 | - __extension__ ({ ++_container_.brk; ++_container_.i; })) \ | |
58 | - for (variable = *_container_.i;; __extension__ ({--_container_.brk; break;})) | |
59 | + _container_.control && _container_.i != _container_.e; \ | |
60 | + ++_container_.i, _container_.control ^= 1) \ | |
61 | + for (variable = *_container_.i; _container_.control; _container_.control = 0) | |
62 | ||
63 | #else | |
64 |