Home | History | Annotate | Download | only in basic.types
      1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
      2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y
      3 
      4 struct NonLiteral { NonLiteral(); };
      5 
      6 // A type is a literal type if it is:
      7 
      8 // [C++1y] - void
      9 constexpr void f() {}
     10 #ifndef CXX1Y
     11 // expected-error@-2 {{'void' is not a literal type}}
     12 #endif
     13 
     14 // - a scalar type
     15 constexpr int f1(double) { return 0; }
     16 
     17 // - a reference type
     18 struct S { S(); };
     19 constexpr int f2(S &) { return 0; }
     20 
     21 struct BeingDefined;
     22 extern BeingDefined beingdefined;
     23 struct BeingDefined {
     24   static constexpr BeingDefined& t = beingdefined;
     25 };
     26 
     27 // - a class type that has all of the following properties:
     28 
     29 // (implied) - it is complete
     30 
     31 struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
     32 template<class T> struct ClassTemp {};
     33 
     34 constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} expected-note {{incomplete type 'const Incomplete' is not a literal type}}
     35 constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'Incomplete const[]'}} expected-note {{incomplete type 'Incomplete const[]' is not a literal type}}
     36 constexpr ClassTemp<int> classtemplate = {};
     37 constexpr ClassTemp<int> classtemplate2[] = {};
     38 
     39 //  - it has a trivial destructor
     40 struct UserProvDtor {
     41   ~UserProvDtor(); // expected-note {{has a user-provided destructor}}
     42 };
     43 constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
     44 struct NonTrivDtor {
     45   constexpr NonTrivDtor();
     46   virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
     47 };
     48 constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
     49 struct NonTrivDtorBase {
     50   ~NonTrivDtorBase();
     51 };
     52 template<typename T>
     53 struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
     54   constexpr DerivedFromNonTrivDtor();
     55 };
     56 constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
     57 struct TrivDtor {
     58   constexpr TrivDtor();
     59 };
     60 constexpr int f(TrivDtor) { return 0; }
     61 struct TrivDefaultedDtor {
     62   constexpr TrivDefaultedDtor();
     63   ~TrivDefaultedDtor() = default;
     64 };
     65 constexpr int f(TrivDefaultedDtor) { return 0; }
     66 
     67 //  - it is an aggregate type or has at least one constexpr constructor or
     68 //    constexpr constructor template that is not a copy or move constructor
     69 struct Agg {
     70   int a;
     71   char *b;
     72 };
     73 constexpr int f3(Agg a) { return a.a; }
     74 struct CtorTemplate {
     75   template<typename T> constexpr CtorTemplate(T);
     76 };
     77 struct CopyCtorOnly { // expected-note {{'CopyCtorOnly' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     78   constexpr CopyCtorOnly(CopyCtorOnly&);
     79 };
     80 constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
     81 struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
     82   constexpr MoveCtorOnly(MoveCtorOnly&&);
     83 };
     84 constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
     85 template<typename T>
     86 struct CtorArg {
     87   constexpr CtorArg(T);
     88 };
     89 constexpr int f(CtorArg<int>) { return 0; } // ok
     90 constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr
     91 // We have a special-case diagnostic for classes with virtual base classes.
     92 struct VBase {};
     93 struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}}
     94 struct Derived : HasVBase {
     95   constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
     96 };
     97 template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
     98   constexpr DerivedFromVBase();
     99 };
    100 constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
    101 template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
    102 constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}}
    103 
    104 //  - it has all non-static data members and base classes of literal types
    105 struct NonLitMember {
    106   S s; // expected-note {{has data member 's' of non-literal type 'S'}}
    107 };
    108 constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
    109 struct NonLitBase :
    110   S { // expected-note {{base class 'S' of non-literal type}}
    111   constexpr NonLitBase();
    112 };
    113 constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
    114 struct LitMemBase : Agg {
    115   Agg agg;
    116 };
    117 template<typename T>
    118 struct MemberType {
    119   T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}}
    120   constexpr MemberType();
    121 };
    122 constexpr int f(MemberType<int>) { return 0; }
    123 constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}}
    124 
    125 // - an array of literal type [C++1y] other than an array of runtime bound
    126 struct ArrGood {
    127   Agg agg[24];
    128   double d[12];
    129   TrivDtor td[3];
    130   TrivDefaultedDtor tdd[3];
    131 };
    132 constexpr int f(ArrGood) { return 0; }
    133 
    134 struct ArrBad {
    135   S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}}
    136 };
    137 constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
    138 
    139 constexpr int arb(int n) {
    140   int a[n]; // expected-error {{variable of non-literal type 'int [n]' cannot be defined in a constexpr function}}
    141 }
    142 constexpr long Overflow[ // expected-error {{constexpr variable cannot have non-literal type 'long const[(1 << 30) << 2]'}}
    143     (1 << 30) << 2]{};   // expected-warning {{requires 34 bits to represent}}
    144 
    145 namespace inherited_ctor {
    146   struct A { constexpr A(int); };
    147   struct B : A {
    148     B();
    149     using A::A;
    150   };
    151   constexpr int f(B) { return 0; } // ok
    152 
    153   struct C { constexpr C(int); };
    154   struct D : C { // expected-note {{because}}
    155     D(int);
    156     using C::C;
    157   };
    158   constexpr int f(D) { return 0; } // expected-error {{not a literal type}}
    159 
    160   // This one is a bit odd: F inherits E's default constructor, which is
    161   // constexpr. Because F has a constructor of its own, it doesn't declare a
    162   // default constructor hiding E's one.
    163   struct E {};
    164   struct F : E {
    165     F(int);
    166     using E::E;
    167   };
    168   constexpr int f(F) { return 0; }
    169 
    170   // FIXME: Is this really the right behavior? We presumably should be checking
    171   // whether the inherited constructor would be a copy or move constructor for
    172   // the derived class, not for the base class.
    173   struct G { constexpr G(const G&); };
    174   struct H : G { // expected-note {{because}}
    175     using G::G;
    176   };
    177   constexpr int f(H) { return 0; } // expected-error {{not a literal type}}
    178 
    179   struct J;
    180   struct I { constexpr I(const J&); };
    181   struct J : I {
    182     using I::I;
    183   };
    184   constexpr int f(J) { return 0; }
    185 }
    186