Home | History | Annotate | Download | only in dcl.constexpr
      1 // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++11 -Werror=c++1y-extensions %s
      2 // RUN: %clang_cc1 -verify -fcxx-exceptions -triple=x86_64-linux-gnu -std=c++1y -DCXX1Y %s
      3 
      4 namespace N {
      5   typedef char C;
      6 }
      7 
      8 namespace M {
      9   typedef double D;
     10 }
     11 
     12 struct NonLiteral { // expected-note 3{{no constexpr constructors}}
     13   NonLiteral() {}
     14   NonLiteral(int) {}
     15 };
     16 struct Literal {
     17   constexpr Literal() {}
     18   operator int() const { return 0; }
     19 };
     20 
     21 struct S {
     22   virtual int ImplicitlyVirtual() const = 0; // expected-note {{overridden virtual function}}
     23 };
     24 struct SS : S {
     25   int ImplicitlyVirtual() const;
     26 };
     27 
     28 // The definition of a constexpr function shall satisfy the following
     29 // constraints:
     30 struct T : SS, NonLiteral { // expected-note {{base class 'NonLiteral' of non-literal type}}
     31   constexpr T();
     32   constexpr int f() const; // expected-error {{non-literal type 'T' cannot have constexpr members}}
     33 
     34   //  - it shall not be virtual;
     35   virtual constexpr int ExplicitlyVirtual() const { return 0; } // expected-error {{virtual function cannot be constexpr}}
     36 
     37   constexpr int ImplicitlyVirtual() const { return 0; } // expected-error {{virtual function cannot be constexpr}}
     38 
     39   //  - its return type shall be a literal type;
     40   constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
     41   constexpr void VoidReturn() const { return; }
     42 #ifndef CXX1Y
     43   // expected-error@-2 {{constexpr function's return type 'void' is not a literal type}}
     44 #endif
     45   constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}}
     46   typedef NonLiteral F() const;
     47   constexpr F NonLiteralReturn2; // ok until definition
     48 
     49   //  - each of its parameter types shall be a literal type;
     50   constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
     51   typedef int G(NonLiteral) const;
     52   constexpr G NonLiteralParam2; // ok until definition
     53 
     54   //  - its function-body shall be = delete, = default,
     55   constexpr int Deleted() const = delete;
     56   // It's not possible for the function-body to legally be "= default" here
     57   // (that is, for a non-constructor function) in C++11.
     58   // Other than constructors, only the copy- and move-assignment operators and
     59   // destructor can be defaulted. Destructors can't be constexpr since they
     60   // don't have a literal return type. Defaulted assignment operators can't be
     61   // constexpr since they can't be const.
     62   constexpr T &operator=(const T&) = default;
     63 #ifndef CXX1Y
     64   // expected-error@-2 {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
     65   // expected-warning@-3 {{C++1y}}
     66 #else
     67   // expected-error@-5 {{defaulted definition of copy assignment operator is not constexpr}}
     68 #endif
     69 };
     70 #ifdef CXX1Y
     71 struct T2 {
     72   int n = 0;
     73   constexpr T2 &operator=(const T2&) = default; // ok
     74 };
     75 struct T3 {
     76   constexpr T3 &operator=(const T3&) const = default;
     77   // expected-error@-1 {{an explicitly-defaulted copy assignment operator may not have 'const' or 'volatile' qualifiers}}
     78 };
     79 #endif
     80 struct U {
     81   constexpr U SelfReturn() const;
     82   constexpr int SelfParam(U) const;
     83 };
     84 
     85 struct V : virtual U { // expected-note {{here}}
     86   constexpr int F() const { return 0; } // expected-error {{constexpr member function not allowed in struct with virtual base class}}
     87 };
     88 
     89 //  or a compound-statememt that contains only [CXX11]
     90 constexpr int AllowedStmtsCXX11() {
     91   //  - null statements
     92   ;
     93 
     94   //  - static_assert-declarations
     95   static_assert(true, "the impossible happened!");
     96 
     97   //  - typedef declarations and alias-declarations that do not define classes
     98   //    or enumerations
     99   typedef int I;
    100   typedef struct S T;
    101   using J = int;
    102   using K = int[sizeof(I) + sizeof(J)];
    103   // Note, the standard requires we reject this.
    104   struct U;
    105 
    106   //  - using-declarations
    107   using N::C;
    108 
    109   //  - using-directives
    110   using namespace N;
    111 
    112   //  - and exactly one return statement
    113   return sizeof(K) + sizeof(C) + sizeof(K);
    114 }
    115 
    116 //  or a compound-statement that does not contain [CXX1Y]
    117 constexpr int DisallowedStmtsCXX1Y_1() {
    118   //  - an asm-definition
    119   asm("int3"); // expected-error {{statement not allowed in constexpr function}}
    120   return 0;
    121 }
    122 constexpr int DisallowedStmtsCXX1Y_2() {
    123   //  - a goto statement
    124   goto x; // expected-error {{statement not allowed in constexpr function}}
    125 x:
    126   return 0;
    127 }
    128 constexpr int DisallowedStmtsCXX1Y_3() {
    129   //  - a try-block,
    130   try {} catch (...) {} // expected-error {{statement not allowed in constexpr function}}
    131   return 0;
    132 }
    133 constexpr int DisallowedStmtsCXX1Y_4() {
    134   //  - a definition of a variable of non-literal type
    135   NonLiteral nl; // expected-error {{variable of non-literal type 'NonLiteral' cannot be defined in a constexpr function}}
    136   return 0;
    137 }
    138 constexpr int DisallowedStmtsCXX1Y_5() {
    139   //  - a definition of a variable of static storage duration
    140   static constexpr int n = 123; // expected-error {{static variable not permitted in a constexpr function}}
    141   return n;
    142 }
    143 constexpr int DisallowedStmtsCXX1Y_6() {
    144   //  - a definition of a variable of thread storage duration
    145   thread_local constexpr int n = 123; // expected-error {{thread_local variable not permitted in a constexpr function}}
    146   return n;
    147 }
    148 constexpr int DisallowedStmtsCXX1Y_7() {
    149   //  - a definition of a variable for which no initialization is performed
    150   int n; // expected-error {{variables defined in a constexpr function must be initialized}}
    151   return 0;
    152 }
    153 
    154 constexpr int ForStmt() {
    155   for (int n = 0; n < 10; ++n)
    156 #ifndef CXX1Y
    157   // expected-error@-2 {{statement not allowed in constexpr function}}
    158 #endif
    159     return 0;
    160 }
    161 constexpr int VarDecl() {
    162   int a = 0;
    163 #ifndef CXX1Y
    164   // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
    165 #endif
    166   return 0;
    167 }
    168 constexpr int ConstexprVarDecl() {
    169   constexpr int a = 0;
    170 #ifndef CXX1Y
    171   // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
    172 #endif
    173   return 0;
    174 }
    175 constexpr int VarWithCtorDecl() {
    176   Literal a;
    177 #ifndef CXX1Y
    178   // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
    179 #endif
    180   return 0;
    181 }
    182 NonLiteral nl;
    183 constexpr NonLiteral &ExternNonLiteralVarDecl() {
    184   extern NonLiteral nl;
    185 #ifndef CXX1Y
    186   // expected-error@-2 {{variable declaration in a constexpr function is a C++1y extension}}
    187 #endif
    188   return nl;
    189 }
    190 static_assert(&ExternNonLiteralVarDecl() == &nl, "");
    191 constexpr int FuncDecl() {
    192   constexpr int ForwardDecl(int);
    193 #ifndef CXX1Y
    194   // expected-error@-2 {{use of this statement in a constexpr function is a C++1y extension}}
    195 #endif
    196   return ForwardDecl(42);
    197 }
    198 constexpr int ClassDecl1() {
    199   typedef struct { } S1;
    200 #ifndef CXX1Y
    201   // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
    202 #endif
    203   return 0;
    204 }
    205 constexpr int ClassDecl2() {
    206   using S2 = struct { };
    207 #ifndef CXX1Y
    208   // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
    209 #endif
    210   return 0;
    211 }
    212 constexpr int ClassDecl3() {
    213   struct S3 { };
    214 #ifndef CXX1Y
    215   // expected-error@-2 {{type definition in a constexpr function is a C++1y extension}}
    216 #endif
    217   return 0;
    218 }
    219 constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}}
    220 constexpr int MultiReturn() {
    221   return 0;
    222   return 0;
    223 #ifndef CXX1Y
    224   // expected-error@-2 {{multiple return statements in constexpr function}}
    225   // expected-note@-4 {{return statement}}
    226 #endif
    227 }
    228 
    229 //  - every constructor call and implicit conversion used in initializing the
    230 //    return value shall be one of those allowed in a constant expression.
    231 //
    232 // We implement the proposed resolution of DR1364 and ignore this bullet.
    233 // However, we implement the spirit of the check as part of the p5 checking that
    234 // a constexpr function must be able to produce a constant expression.
    235 namespace DR1364 {
    236   constexpr int f(int k) {
    237     return k; // ok, even though lvalue-to-rvalue conversion of a function
    238               // parameter is not allowed in a constant expression.
    239   }
    240   int kGlobal; // expected-note {{here}}
    241   constexpr int f() { // expected-error {{constexpr function never produces a constant expression}}
    242     return kGlobal; // expected-note {{read of non-const}}
    243   }
    244 }
    245 
    246 namespace rdar13584715 {
    247   typedef __PTRDIFF_TYPE__ ptrdiff_t;
    248 
    249   template<typename T> struct X {
    250     static T value() {};
    251   };
    252 
    253   void foo(ptrdiff_t id) {
    254     switch (id) {
    255     case reinterpret_cast<ptrdiff_t>(&X<long>::value):  // expected-error{{case value is not a constant expression}} \
    256       // expected-note{{reinterpret_cast is not allowed in a constant expression}}
    257       break;
    258     }
    259   }
    260 }
    261 
    262 namespace std_example {
    263   constexpr int square(int x) {
    264     return x * x;
    265   }
    266   constexpr long long_max() {
    267     return 2147483647;
    268   }
    269   constexpr int abs(int x) {
    270     if (x < 0)
    271 #ifndef CXX1Y
    272       // expected-error@-2 {{C++1y}}
    273 #endif
    274       x = -x;
    275     return x;
    276   }
    277   constexpr int first(int n) {
    278     static int value = n; // expected-error {{static variable not permitted}}
    279     return value;
    280   }
    281   constexpr int uninit() {
    282     int a; // expected-error {{must be initialized}}
    283     return a;
    284   }
    285   constexpr int prev(int x) {
    286     return --x;
    287   }
    288 #ifndef CXX1Y
    289   // expected-error@-4 {{never produces a constant expression}}
    290   // expected-note@-4 {{subexpression}}
    291 #endif
    292   constexpr int g(int x, int n) {
    293     int r = 1;
    294     while (--n > 0) r *= x;
    295     return r;
    296   }
    297 #ifndef CXX1Y
    298     // expected-error@-5 {{C++1y}}
    299     // expected-error@-5 {{statement not allowed}}
    300 #endif
    301 }
    302