aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/pr104869.C
blob: 851d65355de834e9e12e6fb97f6a4339e6a75cb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// PR rtl-optimization/104869
// { dg-do run }
// { dg-options "-O2 -fvisibility=hidden -std=c++11" }
// { dg-require-visibility "" }

struct QBasicAtomicInteger {
  [[gnu::noipa]] int loadRelaxed() { return 1; }
};
struct RefCount {
  bool deref() {
    int count = atomic.loadRelaxed();
    if (count)
      return false;
    return deref();
  }
  QBasicAtomicInteger atomic;
};
struct QArrayData {
  RefCount ref;
};
struct QString {
  ~QString();
  QArrayData d;
};
int ok;
QString::~QString() { d.ref.deref(); }
struct Label {
  bool isValid() { return generator; }
  int *generator;
  int index;
};
struct ControlFlow;
struct Codegen {
  [[gnu::noipa]] bool visit();
  ControlFlow *controlFlow;
};
struct ControlFlow {
  enum UnwindType { EE };
  struct UnwindTarget {
    Label linkLabel;
  };
  ControlFlow *parent;
  UnwindType unwindTarget_type;
  UnwindTarget unwindTarget() {
    QString label;
    ControlFlow *flow = this;
    while (flow) {
      Label l = getUnwindTarget(unwindTarget_type, label);
      if (l.isValid())
        return {l};
      flow = flow->parent;
    }
    return UnwindTarget();
  }
  [[gnu::noipa]] Label getUnwindTarget(UnwindType, QString &) {
    Label l = { &ok, 0 };
    return l;
  }
};
[[gnu::noipa]] void foo(int) {
  ok = 1;
}
[[gnu::noipa]] bool Codegen::visit() {
  if (!controlFlow)
    return false;
  ControlFlow::UnwindTarget target = controlFlow->unwindTarget();
  if (target.linkLabel.isValid())
    foo(2);
  return false;
}
#ifdef __hpux__
extern int main(void) __attribute__ ((visibility ("default")));
#endif
int
main() {
  ControlFlow cf = { nullptr, ControlFlow::UnwindType::EE };
  Codegen c = { &cf };
  c.visit();
  if (!ok)
    __builtin_abort ();
}