reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
// RUN: %clang_cc1 -triple x86_64-linux -fblocks -emit-llvm -o - %s -std=c++1y | FileCheck %s

// CHECK: @"_ZZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEvE2l2" =
// CHECK: internal global i32* @"_ZZNK17pr18020_constexpr3$_1clEvE2l1"
// CHECK: @_ZZL14deduced_returnvE1n = internal global i32 42
// CHECK: @_ZZZL20block_deduced_returnvEUb_E1n = internal global i32 42
// CHECK: @_ZZ18static_local_labelPvE1q = linkonce_odr global i8* blockaddress(@_Z18static_local_labelPv, %{{.*}})
// CHECK: @"_ZZNK3$_2clEvE1x" = internal global i32 42

namespace pr6769 {
struct X {
  static void f();
};

void X::f() {
  static int *i;
  {
    struct Y {
      static void g() {
        i = new int();
	*i = 100;
	(*i) = (*i) +1;
      }
    };
    (void)Y::g();
  }
  (void)i;
}
}

namespace pr7101 {
void foo() {
    static int n = 0;
    struct Helper {
        static void Execute() {
            n++;
        }
    };
    Helper::Execute();
}
}

// These tests all break the assumption that the static var decl has to be
// emitted before use of the var decl.  This happens because we defer emission
// of variables with internal linkage and no initialization side effects, such
// as 'x'.  Then we hit operator()() in 'f', and emit the callee before we emit
// the arguments, so we emit the innermost function first.

namespace pr18020_lambda {
// Referring to l1 before emitting it used to crash.
auto x = []() {
  static int l1 = 0;
  return [] { return l1; };
};
int f() { return x()(); }
}

// CHECK-LABEL: define internal i32 @"_ZZNK14pr18020_lambda3$_0clEvENKUlvE_clEv"
// CHECK: load i32, i32* @"_ZZNK14pr18020_lambda3$_0clEvE2l1"

namespace pr18020_constexpr {
// Taking the address of l1 in a constant expression used to crash.
auto x = []() {
  static int l1 = 0;
  return [] {
    static int *l2 = &l1;
    return *l2;
  };
};
int f() { return x()(); }
}

// CHECK-LABEL: define internal i32 @"_ZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEv"
// CHECK: load i32*, i32** @"_ZZZNK17pr18020_constexpr3$_1clEvENKUlvE_clEvE2l2"

// Lambda-less reduction that references l1 before emitting it.  This didn't
// crash if you put it in a namespace.
struct pr18020_class {
  auto operator()() {
    static int l1 = 0;
    struct U {
      int operator()() { return l1; }
    };
    return U();
  }
};
static pr18020_class x;
int pr18020_f() { return x()(); }

// CHECK-LABEL: define linkonce_odr i32 @_ZZN13pr18020_classclEvEN1UclEv
// CHECK: load i32, i32* @_ZZN13pr18020_classclEvE2l1

// In this test case, the function containing the static local will not be
// emitted because it is unneeded. However, the operator call of the inner class
// is called, and the static local is referenced and must be emitted.
static auto deduced_return() {
  static int n = 42;
  struct S { int *operator()() { return &n; } };
  return S();
}
extern "C" int call_deduced_return_operator() {
  return *decltype(deduced_return())()();
}

// CHECK-LABEL: define i32 @call_deduced_return_operator()
// CHECK: call i32* @_ZZL14deduced_returnvEN1SclEv(
// CHECK: load i32, i32* %
// CHECK: ret i32 %

// CHECK-LABEL: define internal i32* @_ZZL14deduced_returnvEN1SclEv(%struct.S* %this)
// CHECK: ret i32* @_ZZL14deduced_returnvE1n

static auto block_deduced_return() {
  auto (^b)() = ^() {
    static int n = 42;
    struct S { int *operator()() { return &n; } };
    return S();
  };
  return b();
}
extern "C" int call_block_deduced_return() {
  return *decltype(block_deduced_return())()();
}

// CHECK-LABEL: define i32 @call_block_deduced_return()
// CHECK: call i32* @_ZZZL20block_deduced_returnvEUb_EN1SclEv(
// CHECK: load i32, i32* %
// CHECK: ret i32 %

// CHECK-LABEL: define internal i32* @_ZZZL20block_deduced_returnvEUb_EN1SclEv(%struct.S.6* %this) #1 align 2 {
// CHECK: ret i32* @_ZZZL20block_deduced_returnvEUb_E1n

inline auto static_local_label(void *p) {
  if (p)
    goto *p;
  static void *q = &&label;
  struct S { static void *get() { return q; } };
  return S();
label:
  __builtin_abort();
}
void *global_label = decltype(static_local_label(0))::get();

// CHECK-LABEL: define linkonce_odr i8* @_ZZ18static_local_labelPvEN1S3getEv()
// CHECK: %[[lbl:[^ ]*]] = load i8*, i8** @_ZZ18static_local_labelPvE1q
// CHECK: ret i8* %[[lbl]]

auto global_lambda = []() {
  static int x = 42;
  struct S { static int *get() { return &x; } };
  return S();
};
extern "C" int use_global_lambda() {
  return *decltype(global_lambda())::get();
}
// CHECK-LABEL: define i32 @use_global_lambda()
// CHECK: call i32* @"_ZZNK3$_2clEvEN1S3getEv"()

// CHECK-LABEL: define internal i32* @"_ZZNK3$_2clEvEN1S3getEv"()
// CHECK: ret i32* @"_ZZNK3$_2clEvE1x"