Clang Project

clang_source_code/test/CXX/basic/basic.types/p10.cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y
3
4struct NonLiteral { NonLiteral(); };
5
6// A type is a literal type if it is:
7
8// [C++1y] - void
9constexpr void f() {}
10#ifndef CXX1Y
11// expected-error@-2 {{'void' is not a literal type}}
12#endif
13
14// - a scalar type
15constexpr int f1(double) { return 0; }
16
17// - a reference type
18struct S { S(); };
19constexpr int f2(S &) { return 0; }
20
21struct BeingDefined;
22extern BeingDefined beingdefined;
23struct 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
31struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
32template<class T> struct ClassTemp {};
33
34constexpr Incomplete incomplete = {}; // expected-error {{constexpr variable cannot have non-literal type 'const Incomplete'}} expected-note {{incomplete type 'const Incomplete' is not a literal type}}
35constexpr Incomplete incomplete2[] = {}; // expected-error {{constexpr variable cannot have non-literal type 'Incomplete const[]'}} expected-note {{incomplete type 'Incomplete const[]' is not a literal type}}
36constexpr ClassTemp<int> classtemplate = {};
37constexpr ClassTemp<int> classtemplate2[] = {};
38
39//  - it has a trivial destructor
40struct UserProvDtor {
41  ~UserProvDtor(); // expected-note {{has a user-provided destructor}}
42};
43constexpr int f(UserProvDtor) { return 0; } // expected-error {{'UserProvDtor' is not a literal type}}
44struct NonTrivDtor {
45  constexpr NonTrivDtor();
46  virtual ~NonTrivDtor() = default; // expected-note {{has a non-trivial destructor}} expected-note {{because it is virtual}}
47};
48constexpr int f(NonTrivDtor) { return 0; } // expected-error {{'NonTrivDtor' is not a literal type}}
49struct NonTrivDtorBase {
50  ~NonTrivDtorBase();
51};
52template<typename T>
53struct DerivedFromNonTrivDtor : T { // expected-note {{'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not literal because it has base class 'NonTrivDtorBase' of non-literal type}}
54  constexpr DerivedFromNonTrivDtor();
55};
56constexpr int f(DerivedFromNonTrivDtor<NonTrivDtorBase>) { return 0; } // expected-error {{constexpr function's 1st parameter type 'DerivedFromNonTrivDtor<NonTrivDtorBase>' is not a literal type}}
57struct TrivDtor {
58  constexpr TrivDtor();
59};
60constexpr int f(TrivDtor) { return 0; }
61struct TrivDefaultedDtor {
62  constexpr TrivDefaultedDtor();
63  ~TrivDefaultedDtor() = default;
64};
65constexpr 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
69struct Agg {
70  int a;
71  char *b;
72};
73constexpr int f3(Agg a) { return a.a; }
74struct CtorTemplate {
75  template<typename T> constexpr CtorTemplate(T);
76};
77struct 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};
80constexpr int f(CopyCtorOnly) { return 0; } // expected-error {{'CopyCtorOnly' is not a literal type}}
81struct MoveCtorOnly { // expected-note {{no constexpr constructors other than copy or move constructors}}
82  constexpr MoveCtorOnly(MoveCtorOnly&&);
83};
84constexpr int f(MoveCtorOnly) { return 0; } // expected-error {{'MoveCtorOnly' is not a literal type}}
85template<typename T>
86struct CtorArg {
87  constexpr CtorArg(T);
88};
89constexpr int f(CtorArg<int>) { return 0; } // ok
90constexpr int f(CtorArg<NonLiteral>) { return 0; } // ok, ctor is still constexpr
91// We have a special-case diagnostic for classes with virtual base classes.
92struct VBase {};
93struct HasVBase : virtual VBase {}; // expected-note 2{{virtual base class declared here}}
94struct Derived : HasVBase {
95  constexpr Derived() {} // expected-error {{constexpr constructor not allowed in struct with virtual base class}}
96};
97template<typename T> struct DerivedFromVBase : T { // expected-note {{struct with virtual base class is not a literal type}}
98  constexpr DerivedFromVBase();
99};
100constexpr int f(DerivedFromVBase<HasVBase>) {} // expected-error {{constexpr function's 1st parameter type 'DerivedFromVBase<HasVBase>' is not a literal type}}
101template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
102constexpr 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
105struct NonLitMember {
106  S s; // expected-note {{has data member 's' of non-literal type 'S'}}
107};
108constexpr int f(NonLitMember) {} // expected-error {{1st parameter type 'NonLitMember' is not a literal type}}
109struct NonLitBase :
110  S { // expected-note {{base class 'S' of non-literal type}}
111  constexpr NonLitBase();
112};
113constexpr int f(NonLitBase) { return 0; } // expected-error {{'NonLitBase' is not a literal type}}
114struct LitMemBase : Agg {
115  Agg agg;
116};
117template<typename T>
118struct 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};
122constexpr int f(MemberType<int>) { return 0; }
123constexpr 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
126struct ArrGood {
127  Agg agg[24];
128  double d[12];
129  TrivDtor td[3];
130  TrivDefaultedDtor tdd[3];
131};
132constexpr int f(ArrGood) { return 0; }
133
134struct ArrBad {
135  S s[3]; // expected-note {{data member 's' of non-literal type 'S [3]'}}
136};
137constexpr int f(ArrBad) { return 0; } // expected-error {{1st parameter type 'ArrBad' is not a literal type}}
138
139constexpr 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}
142constexpr 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
145namespace 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