|
| 1 | +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++20 %s 2>&1 | FileCheck %s |
| 2 | + |
| 3 | +struct A { |
| 4 | + static A a; |
| 5 | + char b; |
| 6 | + friend bool operator==(A, A) = default; |
| 7 | +}; |
| 8 | +bool _ = A() == A::a; |
| 9 | + |
| 10 | +// FIXME: steps 1 and 5 show anonymous function parameters are |
| 11 | +// not handled correctly. |
| 12 | + |
| 13 | +// CHECK-LABEL: bool operator==(A, A) noexcept = default |
| 14 | +// CHECK-NEXT: [B2 (ENTRY)] |
| 15 | +// CHECK-NEXT: Succs (1): B1 |
| 16 | +// CHECK: [B1] |
| 17 | +// CHECK-NEXT: 1: function-parameter-0-0 |
| 18 | +// CHECK-NEXT: 2: [B1.1].b |
| 19 | +// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, LValueToRValue, char) |
| 20 | +// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, IntegralCast, int) |
| 21 | +// CHECK-NEXT: 5: function-parameter-0-1 |
| 22 | +// CHECK-NEXT: 6: [B1.5].b |
| 23 | +// CHECK-NEXT: 7: [B1.6] (ImplicitCastExpr, LValueToRValue, char) |
| 24 | +// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, IntegralCast, int) |
| 25 | +// CHECK-NEXT: 9: [B1.4] == [B1.8] |
| 26 | +// CHECK-NEXT: 10: return [B1.9]; |
| 27 | +// CHECK-NEXT: Preds (1): B2 |
| 28 | +// CHECK-NEXT: Succs (1): B0 |
| 29 | +// CHECK: [B0 (EXIT)] |
| 30 | +// CHECK-NEXT: Preds (1): B1 |
| 31 | + |
| 32 | +namespace std { |
| 33 | +template <class> struct iterator_traits; |
| 34 | +template <class, class> struct pair; |
| 35 | +template <class _Tp> struct iterator_traits<_Tp *> { |
| 36 | + typedef _Tp &reference; |
| 37 | +}; |
| 38 | +template <long, class> struct tuple_element; |
| 39 | +template <class> struct tuple_size; |
| 40 | +template <class _T1, class _T2> struct tuple_size<pair<_T1, _T2>> { |
| 41 | + static const int value = 2; |
| 42 | +}; |
| 43 | +template <class _T1, class _T2> struct tuple_element<0, pair<_T1, _T2>> { |
| 44 | + using type = _T1; |
| 45 | +}; |
| 46 | +template <class _T1, class _T2> struct tuple_element<1, pair<_T1, _T2>> { |
| 47 | + using type = _T2; |
| 48 | +}; |
| 49 | +template <long _Ip, class _T1, class _T2> |
| 50 | +tuple_element<_Ip, pair<_T1, _T2>>::type get(pair<_T1, _T2> &); |
| 51 | +struct __wrap_iter { |
| 52 | + iterator_traits<pair<int, int> *>::reference operator*(); |
| 53 | + void operator++(); |
| 54 | +}; |
| 55 | +bool operator!=(__wrap_iter, __wrap_iter); |
| 56 | +struct vector { |
| 57 | + __wrap_iter begin(); |
| 58 | + __wrap_iter end(); |
| 59 | +}; |
| 60 | +} // namespace std |
| 61 | +int main() { |
| 62 | + std::vector v; |
| 63 | + for (auto &[a, b] : v) |
| 64 | + ; |
| 65 | +} |
| 66 | + |
| 67 | +// FIXME: On steps 8 and 14, a decomposition is referred by name, which they never have. |
| 68 | + |
| 69 | +// CHECK-LABEL: int main() |
| 70 | +// CHECK: [B3] |
| 71 | +// CHECK-NEXT: 1: operator* |
| 72 | +// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, iterator_traits<pair<int, int> *>::reference (*)(void)) |
| 73 | +// CHECK-NEXT: 3: __begin1 |
| 74 | +// CHECK-NEXT: 4: * [B3.3] (OperatorCall) |
| 75 | +// CHECK-NEXT: 5: auto &; |
| 76 | +// CHECK-NEXT: 6: get<0UL> |
| 77 | +// CHECK-NEXT: 7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, typename tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &)) |
| 78 | +// CHECK-NEXT: 8: decomposition-a-b |
| 79 | +// CHECK-NEXT: 9: [B3.7]([B3.8]) |
| 80 | +// CHECK-NEXT: 10: [B3.9] |
| 81 | +// CHECK-NEXT: 11: std::tuple_element<0, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b); |
| 82 | +// CHECK-NEXT: 12: get<1UL> |
| 83 | +// CHECK-NEXT: 13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, typename tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &)) |
| 84 | +// CHECK-NEXT: 14: decomposition-a-b |
| 85 | +// CHECK-NEXT: 15: [B3.13]([B3.14]) |
| 86 | +// CHECK-NEXT: 16: [B3.15] |
| 87 | +// CHECK-NEXT: 17: std::tuple_element<1, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b); |
| 88 | +// CHECK-NEXT: Preds (1): B1 |
| 89 | +// CHECK-NEXT: Succs (1): B2 |
0 commit comments