Home | History | Annotate | Download | only in SemaCXX
      1 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++0x -ffreestanding %s
      2 #include <stdint.h>
      3 
      4 typedef decltype(nullptr) nullptr_t;
      5 
      6 struct A {};
      7 
      8 int o1(char*);
      9 void o1(uintptr_t);
     10 void o2(char*); // expected-note {{candidate}}
     11 void o2(int A::*); // expected-note {{candidate}}
     12 
     13 nullptr_t f(nullptr_t null)
     14 {
     15   // Implicit conversions.
     16   null = nullptr;
     17   void *p = nullptr;
     18   p = null;
     19   int *pi = nullptr;
     20   pi = null;
     21   null = 0;
     22   int A::*pm = nullptr;
     23   pm = null;
     24   void (*pf)() = nullptr;
     25   pf = null;
     26   void (A::*pmf)() = nullptr;
     27   pmf = null;
     28   bool b = nullptr;
     29 
     30   // Can't convert nullptr to integral implicitly.
     31   uintptr_t i = nullptr; // expected-error {{cannot initialize}}
     32 
     33   // Operators
     34   (void)(null == nullptr);
     35   (void)(null <= nullptr);
     36   (void)(null == (void*)0);
     37   (void)((void*)0 == nullptr);
     38   (void)(null <= (void*)0);
     39   (void)((void*)0 <= nullptr);
     40   (void)(0 == nullptr);
     41   (void)(nullptr == 0);
     42   (void)(nullptr <= 0);
     43   (void)(0 <= nullptr);
     44   (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}}
     45   (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}}
     46   (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}}
     47   (void)(0 ? nullptr : 0); // expected-error {{non-pointer operand type 'int' incompatible with nullptr}}
     48   (void)(0 ? nullptr : (void*)0);
     49   (void)(0 ? nullptr : A()); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}}
     50   (void)(0 ? A() : nullptr); // expected-error {{non-pointer operand type 'A' incompatible with nullptr}}
     51 
     52   // Overloading
     53   int t = o1(nullptr);
     54   t = o1(null);
     55   o2(nullptr); // expected-error {{ambiguous}}
     56 
     57   // nullptr is an rvalue, null is an lvalue
     58   (void)&nullptr; // expected-error {{address expression must be an lvalue}}
     59   nullptr_t *pn = &null;
     60 
     61   // You can reinterpret_cast nullptr to an integer.
     62   (void)reinterpret_cast<uintptr_t>(nullptr);
     63   (void)reinterpret_cast<uintptr_t>(*pn);
     64 
     65   int *ip = *pn;
     66   if (*pn) { }
     67 
     68   // You can throw nullptr.
     69   throw nullptr;
     70 }
     71 
     72 // Template arguments can be nullptr.
     73 template <int *PI, void (*PF)(), int A::*PM, void (A::*PMF)()>
     74 struct T {};
     75 
     76 typedef T<nullptr, nullptr, nullptr, nullptr> NT;
     77 
     78 namespace test1 {
     79 template<typename T, typename U> struct is_same {
     80   static const bool value = false;
     81 };
     82 
     83 template<typename T> struct is_same<T, T> {
     84   static const bool value = true;
     85 };
     86 
     87 void *g(void*);
     88 bool g(bool);
     89 
     90 // Test that we prefer g(void*) over g(bool).
     91 static_assert(is_same<decltype(g(nullptr)), void*>::value, "");
     92 }
     93 
     94 namespace test2 {
     95   void f(int, ...) __attribute__((sentinel));
     96 
     97   void g() {
     98     // nullptr can be used as the sentinel value.
     99     f(10, nullptr);
    100   }
    101 }
    102 
    103 namespace test3 {
    104   void f(const char*, ...) __attribute__((format(printf, 1, 2)));
    105 
    106   void g() {
    107     // Don't warn when using nullptr with %p.
    108     f("%p", nullptr);
    109   }
    110 }
    111 
    112 int array0[__is_scalar(nullptr_t)? 1 : -1];
    113 int array1[__is_pod(nullptr_t)? 1 : -1];
    114 int array2[sizeof(nullptr_t) == sizeof(void*)? 1 : -1];
    115 
    116 // FIXME: when we implement constexpr, this will be testable.
    117 #if 0
    118 int relational0[nullptr < nullptr? -1 : 1];
    119 int relational1[nullptr > nullptr? -1 : 1];
    120 int relational2[nullptr <= nullptr? 1 : -1];
    121 int relational3[nullptr >= nullptr? 1 : -1];
    122 int equality[nullptr == nullptr? 1 : -1];
    123 int inequality[nullptr != nullptr? -1 : 1];
    124 #endif
    125 
    126 namespace overloading {
    127   int &f1(int*);
    128   float &f1(bool);
    129 
    130   void test_f1() {
    131     int &ir = (f1)(nullptr);
    132   }
    133 
    134   struct ConvertsToNullPtr {
    135     operator nullptr_t() const;
    136   };
    137 
    138   void test_conversion(ConvertsToNullPtr ctn) {
    139     (void)(ctn == ctn);
    140     (void)(ctn != ctn);
    141     (void)(ctn <= ctn);
    142     (void)(ctn >= ctn);
    143     (void)(ctn < ctn);
    144     (void)(ctn > ctn);
    145   }
    146 }
    147 
    148 namespace templates {
    149   template<typename T, nullptr_t Value>
    150   struct X {
    151     X() { ptr = Value; }
    152 
    153     T *ptr;
    154   };
    155 
    156   X<int, nullptr> x;
    157 
    158 
    159   template<int (*fp)(int), int* p, int A::* pmd, int (A::*pmf)(int)>
    160   struct X2 {};
    161 
    162   X2<nullptr, nullptr, nullptr, nullptr> x2;
    163 }
    164