#include <stdio.h>
#include <stdlib.h>
#if HAVE_IGNORE_ANNOTATIONS
#  include <valgrind/memcheck.h>
#else 
#  define VALGRIND_UNCHECKED_MEM_WRITE(a, b) {*(a) = b; }
#  define VALGRIND_UNCHECKED_MEM_TYPED_READ(type, a)     (a)
#  define VALGRIND_UNCHECKED_MEM_READ(a) (a)
#endif

template<class T>
int test_memcheck_annotations() {
  T *m = new T[10];

  // Out of bounds write.
  VALGRIND_UNCHECKED_MEM_WRITE(&m[10], 1);
  
  // Out of bounds read. (C syntax)
  if (VALGRIND_UNCHECKED_MEM_TYPED_READ(T, m[-1]) == 77) {
    printf("m[-1] = 77\n");
  }

  // Uninitialized access. (C++ syntax)
  if (VALGRIND_UNCHECKED_MEM_READ(m[5]) == 77) {  
    printf("m[5] = 77\n");
  }
  delete [] m;
} 

int main() {
  test_memcheck_annotations<int8_t>();
  test_memcheck_annotations<int16_t>();
  test_memcheck_annotations<int32_t>();
  test_memcheck_annotations<int64_t>();
}