Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s -fblocks
      2 
      3 void tovoid(void*);
      4 
      5 void tovoid_test(int (^f)(int, int)) {
      6   tovoid(f);
      7 }
      8 
      9 void reference_lvalue_test(int& (^f)()) {
     10   f() = 10;
     11 }
     12 
     13 // PR 7165
     14 namespace test1 {
     15   void g(void (^)());
     16   struct Foo {
     17     void foo();
     18     void test() {
     19       (void) ^{ foo(); };
     20     }
     21   };
     22 }
     23 
     24 namespace test2 {
     25   int repeat(int value, int (^block)(int), unsigned n) {
     26     while (n--) value = block(value);
     27     return value;
     28   }
     29 
     30   class Power {
     31     int base;
     32 
     33   public:
     34     Power(int base) : base(base) {}
     35     int calculate(unsigned n) {
     36       return repeat(1, ^(int v) { return v * base; }, n);
     37     }
     38   };
     39 
     40   int test() {
     41     return Power(2).calculate(10);
     42   }
     43 }
     44 
     45 // rdar: // 8382559
     46 namespace radar8382559 {
     47   void func(bool& outHasProperty);
     48 
     49   int test3() {
     50     __attribute__((__blocks__(byref))) bool hasProperty = false;
     51     bool has = true;
     52 
     53     bool (^b)() = ^ {
     54      func(hasProperty);
     55      if (hasProperty)
     56        hasProperty = 0;
     57      if (has)
     58        hasProperty = 1;
     59      return hasProperty;
     60      };
     61     func(hasProperty);
     62     func(has);
     63     b();
     64     if (hasProperty)
     65       hasProperty = 1;
     66     if (has)
     67       has = 2;
     68     return hasProperty = 1;
     69   }
     70 }
     71 
     72 // Move __block variables to the heap when possible.
     73 class MoveOnly {
     74 public:
     75   MoveOnly();
     76   MoveOnly(const MoveOnly&) = delete;
     77   MoveOnly(MoveOnly&&);
     78 };
     79 
     80 void move_block() {
     81   __block MoveOnly mo;
     82 }
     83 
     84 // Don't crash after failing to build a block due to a capture of an
     85 // invalid declaration.
     86 namespace test5 {
     87   struct B { // expected-note 2 {{candidate constructor}}
     88     void *p;
     89     B(int); // expected-note {{candidate constructor}}
     90   };
     91 
     92   void use_block(void (^)());
     93   void use_block_2(void (^)(), const B &a);
     94 
     95   void test() {
     96     B x; // expected-error {{no matching constructor for initialization}}
     97     use_block(^{
     98         int y;
     99         use_block_2(^{ (void) y; }, x);
    100       });
    101   }
    102 }
    103 
    104 
    105 // rdar://16356628
    106 //
    107 // Ensure that we can end function bodies while parsing an
    108 // expression that requires an explicitly-tracked cleanup object
    109 // (i.e. a block literal).
    110 
    111 // The nested function body in this test case is a template
    112 // instantiation.  The template function has to be constexpr because
    113 // we'll otherwise delay its instantiation to the end of the
    114 // translation unit.
    115 namespace test6a {
    116   template <class T> constexpr int func() { return 0; }
    117   void run(void (^)(), int);
    118 
    119   void test() {
    120     int aCapturedVar = 0;
    121     run(^{ (void) aCapturedVar; }, func<int>());
    122   }
    123 }
    124 
    125 // The nested function body in this test case is a method of a local
    126 // class.
    127 namespace test6b {
    128   void run(void (^)(), void (^)());
    129   void test() {
    130     int aCapturedVar = 0;
    131     run(^{ (void) aCapturedVar; },
    132         ^{ struct A { static void foo() {} };
    133             A::foo(); });
    134   }
    135 }
    136 
    137 // The nested function body in this test case is a lambda invocation
    138 // function.
    139 namespace test6c {
    140   void run(void (^)(), void (^)());
    141   void test() {
    142     int aCapturedVar = 0;
    143     run(^{ (void) aCapturedVar; },
    144         ^{ struct A { static void foo() {} };
    145             A::foo(); });
    146   }
    147 }
    148