summaryrefslogtreecommitdiffstats
path: root/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
blob: 2a10b0832f3849a405db603b0111dec5ac525341 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// RUN: %clang_cc1 -verify -std=c++0x %s

namespace N {
  typedef char C;
}

namespace M {
  typedef double D;
}

struct NonLiteral { // expected-note 4{{no constexpr constructors}}
  NonLiteral() {}
  NonLiteral(int) {}
};
struct Literal {
  constexpr Literal() {}
  operator int() const { return 0; }
};

struct S {
  virtual int ImplicitlyVirtual() const = 0; // expected-note {{overridden virtual function}}
};
struct SS : S { 
  int ImplicitlyVirtual() const;
};

// Note, the wording applies constraints to the definition of constexpr
// functions, but we intentionally apply all that we can to the declaration
// instead. See DR1360.

// The definition of a constexpr function shall satisfy the following
// constraints:
struct T : SS { // expected-note {{base class 'SS' of non-literal type}}
  constexpr T(); // expected-error {{non-literal type 'T' cannot have constexpr members}}

  //  - it shall not be virtual;
  virtual constexpr int ExplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}}

  constexpr int ImplicitlyVirtual(); // expected-error {{virtual function cannot be constexpr}}

  //  - its return type shall be a literal type;
  constexpr NonLiteral NonLiteralReturn(); // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
  constexpr ~T(); // expected-error {{destructor cannot be marked constexpr}}
  typedef NonLiteral F();
  constexpr F NonLiteralReturn2; // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}

  //  - each of its parameter types shall be a literal type;
  constexpr int NonLiteralParam(NonLiteral); // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
  typedef int G(NonLiteral);
  constexpr G NonLiteralParam2; // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}

  //  - its function-body shall be = delete, = default,
  constexpr int Deleted() = delete;
  // It's not possible for the function-body to legally be "= default" here.
  // Other than constructors, only the copy- and move-assignment operators and
  // destructor can be defaulted. Destructors can't be constexpr since they
  // don't have a literal return type. Defaulted assignment operators can't be
  // constexpr since they can't be const.
  constexpr T &operator=(const T&) = default; // expected-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}}
};
struct U {
  constexpr U SelfReturn();
  constexpr int SelfParam(U);
};

//  or a compound-statememt that contains only
constexpr int AllowedStmts() {
  //  - null statements
  ;

  //  - static_assert-declarations
  static_assert(true, "the impossible happened!");

  //  - typedef declarations and alias-declarations that do not define classes
  //    or enumerations
  typedef int I;
  typedef struct S T;
  using J = int;
  using K = int[sizeof(I) + sizeof(J)];
  // Note, the standard requires we reject this.
  struct U;

  //  - using-declarations
  using N::C;

  //  - using-directives
  using namespace N;

  //  - and exactly one return statement
  return sizeof(K) + sizeof(C) + sizeof(K);
}
constexpr int ForStmt() {
  for (int n = 0; n < 10; ++n) // expected-error {{statement not allowed in constexpr function}}
    return 0;
}
constexpr int VarDecl() {
  constexpr int a = 0; // expected-error {{variables cannot be declared in a constexpr function}}
  return 0;
}
constexpr int FuncDecl() {
  constexpr int ForwardDecl(int); // expected-error {{statement not allowed in constexpr function}}
  return ForwardDecl(42);
}
constexpr int ClassDecl1() {
  typedef struct { } S1; // expected-error {{types cannot be defined in a constexpr function}}
  return 0;
}
constexpr int ClassDecl2() {
  using S2 = struct { }; // expected-error {{types cannot be defined in a constexpr function}}
  return 0;
}
constexpr int ClassDecl3() {
  struct S3 { }; // expected-error {{types cannot be defined in a constexpr function}}
  return 0;
}
constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}}
constexpr int MultiReturn() {
  return 0; // expected-note {{return statement}}
  return 0; // expected-error {{multiple return statements in constexpr function}}
}

//  - every constructor call and implicit conversion used in initializing the
//    return value shall be one of those allowed in a constant expression.
//
// We implement the proposed resolution of DR1364 and ignore this bullet.