Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
      2 
      3 // Tests for c11 atomics. Many of these tests currently yield unknown
      4 // because we don't fully model the atomics and instead imprecisely
      5 // treat their arguments as escaping.
      6 
      7 typedef unsigned int uint32_t;
      8 typedef enum memory_order {
      9   memory_order_relaxed = __ATOMIC_RELAXED,
     10   memory_order_consume = __ATOMIC_CONSUME,
     11   memory_order_acquire = __ATOMIC_ACQUIRE,
     12   memory_order_release = __ATOMIC_RELEASE,
     13   memory_order_acq_rel = __ATOMIC_ACQ_REL,
     14   memory_order_seq_cst = __ATOMIC_SEQ_CST
     15 } memory_order;
     16 
     17 void clang_analyzer_eval(int);
     18 
     19 struct RefCountedStruct {
     20   uint32_t refCount;
     21   void *ptr;
     22 };
     23 
     24 void test_atomic_fetch_add(struct RefCountedStruct *s) {
     25   s->refCount = 1;
     26 
     27   uint32_t result = __c11_atomic_fetch_add((volatile _Atomic(uint32_t) *)&s->refCount,- 1, memory_order_relaxed);
     28 
     29   // When we model atomics fully this should (probably) be FALSE. It should never
     30   // be TRUE (because the operation mutates the passed in storage).
     31   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
     32 
     33   // When fully modeled this should be TRUE
     34   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
     35 }
     36 
     37 void test_atomic_load(struct RefCountedStruct *s) {
     38   s->refCount = 1;
     39 
     40   uint32_t result = __c11_atomic_load((volatile _Atomic(uint32_t) *)&s->refCount, memory_order_relaxed);
     41 
     42   // When we model atomics fully this should (probably) be TRUE.
     43   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
     44 
     45   // When fully modeled this should be TRUE
     46   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
     47 }
     48 
     49 void test_atomic_store(struct RefCountedStruct *s) {
     50   s->refCount = 1;
     51 
     52   __c11_atomic_store((volatile _Atomic(uint32_t) *)&s->refCount, 2, memory_order_relaxed);
     53 
     54   // When we model atomics fully this should (probably) be FALSE. It should never
     55   // be TRUE (because the operation mutates the passed in storage).
     56   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
     57 }
     58 
     59 void test_atomic_exchange(struct RefCountedStruct *s) {
     60   s->refCount = 1;
     61 
     62   uint32_t result = __c11_atomic_exchange((volatile _Atomic(uint32_t) *)&s->refCount, 2, memory_order_relaxed);
     63 
     64   // When we model atomics fully this should (probably) be FALSE. It should never
     65   // be TRUE (because the operation mutates the passed in storage).
     66   clang_analyzer_eval(s->refCount == 1); // expected-warning {{UNKNOWN}}
     67 
     68   // When fully modeled this should be TRUE
     69   clang_analyzer_eval(result == 1); // expected-warning {{UNKNOWN}}
     70 }
     71 
     72 
     73 void test_atomic_compare_exchange_strong(struct RefCountedStruct *s) {
     74   s->refCount = 1;
     75   uint32_t expected = 2;
     76   uint32_t desired = 3;
     77   _Bool result = __c11_atomic_compare_exchange_strong((volatile _Atomic(uint32_t) *)&s->refCount, &expected, desired, memory_order_relaxed, memory_order_relaxed);
     78 
     79   // For now we expect both expected and refCount to be invalidated by the
     80   // call. In the future we should model more precisely.
     81   clang_analyzer_eval(s->refCount == 3); // expected-warning {{UNKNOWN}}
     82   clang_analyzer_eval(expected == 2); // expected-warning {{UNKNOWN}}
     83 }
     84 
     85 void test_atomic_compare_exchange_weak(struct RefCountedStruct *s) {
     86   s->refCount = 1;
     87   uint32_t expected = 2;
     88   uint32_t desired = 3;
     89   _Bool result = __c11_atomic_compare_exchange_weak((volatile _Atomic(uint32_t) *)&s->refCount, &expected, desired, memory_order_relaxed, memory_order_relaxed);
     90 
     91   // For now we expect both expected and refCount to be invalidated by the
     92   // call. In the future we should model more precisely.
     93   clang_analyzer_eval(s->refCount == 3); // expected-warning {{UNKNOWN}}
     94   clang_analyzer_eval(expected == 2); // expected-warning {{UNKNOWN}}
     95 }
     96