Home | History | Annotate | Download | only in basic.types
      1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
      2 
      3 struct NonLiteral { NonLiteral(); };
      4 
      5 // A type is a literal type if it is:
      6 
      7 // - a scalar type
      8 constexpr int f1(double);
      9 
     10 // - a reference type
     11 struct S { S(); };
     12 constexpr int f2(S &);
     13 
     14 // - a class type that has all of the following properties:
     15 
     16 //  - it has a trivial destructor
     17 struct UserProvDtor {
     18   constexpr UserProvDtor(); // expected-error {{non-literal type 'UserProvDtor' cannot have constexpr members}}
     19   ~UserProvDtor(); // expected-note {{has a user-provided destructor}}
     20 };
     21 struct NonTrivDtor {
     22   constexpr NonTrivDtor(); // expected-error {{non-literal type 'NonTrivDtor' cannot have constexpr members}}
     23   virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}}
     24 };
     25 struct NonTrivDtorBase {
     26   ~NonTrivDtorBase();
     27 };
     28 template<typename T>
     29 struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
     30   constexpr DerivedFromNonTrivDtor();
     31 };
     32 constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
     33 struct TrivDtor {
     34   constexpr TrivDtor();
     35 };
     36 // FIXME: when building DefinitionData we look at 'isUserProvided' before it's set up!
     37 #if 0
     38 struct TrivDefaultedDtor {
     39   constexpr TrivDefaultedDtor();
     40   ~TrivDefaultedDtor() = default;
     41 };
     42 #endif
     43 
     44 //  - it is an aggregate type or has at least one constexpr constructor or
     45 //    constexpr constructor template that is not a copy or move constructor
     46 struct Agg {
     47   int a;
     48   char *b;
     49 };
     50 constexpr int f3(Agg a) { return a.a; }
     51 struct CtorTemplate {
     52   template<typename T> constexpr CtorTemplate(T);
     53 };
     54 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}}
     55   constexpr CopyCtorOnly(CopyCtorOnly&); // expected-error {{non-literal type 'CopyCtorOnly' cannot have constexpr members}}
     56 };
     57 struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
     58   constexpr MoveCtorOnly(MoveCtorOnly&&); // expected-error {{non-literal type 'MoveCtorOnly' cannot have constexpr members}}
     59 };
     60 template<typename T>
     61 struct CtorArg { // expected-note {{no constexpr constructors other than copy or move constructors}}
     62   constexpr CtorArg(T); // expected-note {{constructor template instantiation is not constexpr because 1st parameter type 'NonLiteral' is not a literal type}}
     63 };
     64 constexpr int f(CtorArg<int>);
     65 constexpr int f(CtorArg<NonLiteral>); // expected-error {{not a literal type}}
     66 // We have a special-case diagnostic for classes with virtual base classes.
     67 struct VBase {};
     68 struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}}
     69 struct Derived : HasVBase {
     70   constexpr Derived(); // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
     71 };
     72 template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
     73   constexpr DerivedFromVBase();
     74 };
     75 constexpr int f(DerivedFromVBase<HasVBase>); // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
     76 
     77 //  - it has all non-static data members and base classes of literal types
     78 struct NonLitMember {
     79   S s; // expected-note {{has data member 's' of non-literal type 'S'}}
     80 };
     81 constexpr int f(NonLitMember); // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
     82 struct NonLitBase :
     83   S { // expected-note {{base class 'S' of non-literal type}}
     84   constexpr NonLitBase(); // expected-error {{non-literal type 'NonLitBase' cannot have constexpr members}}
     85 };
     86 struct LitMemBase : Agg {
     87   Agg agg;
     88 };
     89 template<typename T>
     90 struct MemberType {
     91   T t; // expected-note {{'MemberType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}}
     92   constexpr MemberType();
     93 };
     94 constexpr int f(MemberType<int>);
     95 constexpr int f(MemberType<NonLiteral>); // expected-error {{not a literal type}}
     96 
     97 // - an array of literal type
     98 struct ArrGood {
     99   Agg agg[24];
    100   double d[12];
    101   TrivDtor td[3];
    102 };
    103 constexpr int f(ArrGood);
    104 
    105 struct ArrBad {
    106   S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}}
    107 };
    108 constexpr int f(ArrBad); // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
    109 
    110 
    111 // As a non-conforming tweak to the standard, we do not allow a literal type to
    112 // have any mutable data members.
    113 namespace MutableMembers {
    114   struct MM {
    115     mutable int n; // expected-note {{'MM' is not literal because it has a mutable data member}}
    116   };
    117   constexpr int f(MM); // expected-error {{not a literal type}}
    118 
    119   // Here's one reason why allowing this would be a disaster...
    120   template<int n> struct Id { int k = n; };
    121   int f() {
    122     // FIXME: correctly check whether the initializer is a constant expression.
    123     constexpr MM m = { 0 }; // desired-error {{must be a constant expression}}
    124     ++m.n;
    125     return Id<m.n>().k; // expected-error {{not an integral constant expression}}
    126   }
    127 }
    128