summaryrefslogtreecommitdiff
path: root/test/Parser/cxx-casting.cpp
blob: b1ae591865eb1dce7e8dc1063aeebd6db9e1d1d3 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s

char *const_cast_test(const char *var)
{
  return const_cast<char*>(var);
}

struct A {
  virtual ~A() {}
};

struct B : public A {
};

struct B *dynamic_cast_test(struct A *a)
{
  return dynamic_cast<struct B*>(a);
}

char *reinterpret_cast_test()
{
  return reinterpret_cast<char*>(0xdeadbeef);
}

double static_cast_test(int i)
{
  return static_cast<double>(i);
}

char postfix_expr_test()
{
  return reinterpret_cast<char*>(0xdeadbeef)[0];
}

// This was being incorrectly tentatively parsed.
namespace test1 {
  template <class T> class A {}; // expected-note 2{{here}}
  void foo() { A<int>(*(A<int>*)0); } // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}}
}

typedef char* c;
typedef A* a;
void test2(char x, struct B * b) {
  (void)const_cast<::c>(&x);
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a const_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  (void)dynamic_cast<::a>(b);
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a dynamic_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  (void)reinterpret_cast<::c>(x);
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a reinterpret_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  (void)static_cast<::c>(&x);
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a static_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  // Do not do digraph correction.
  (void)static_cast<: :c>(&x); //\
       expected-error {{expected '<' after 'static_cast'}} \
       expected-error {{expected expression}}\
       expected-error {{expected ']'}}\
       expected-note {{to match this '['}}
  (void)static_cast<: // expected-error {{expected '<' after 'static_cast'}} \
                         expected-note {{to match this '['}}
  :c>(&x); // expected-error {{expected expression}} \
              expected-error {{expected ']'}}
#define LC <:
#define C :
  test1::A LC:B> c; // expected-error {{class template 'test1::A' requires template arguments}} expected-error 2{{}}
  (void)static_cast LC:c>(&x); // expected-error {{expected '<' after 'static_cast'}} expected-error 2{{}} expected-note{{}}
  test1::A<:C B> d; // expected-error {{class template 'test1::A' requires template arguments}} expected-error 2{{}}
  (void)static_cast<:C c>(&x); // expected-error {{expected '<' after 'static_cast'}} expected-error 2{{}} expected-note{{}}

#define LCC <::
  test1::A LCC B> e;
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  (void)static_cast LCC c>(&x);
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a static_cast which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif
}

                               // This note comes from "::D[:F> A5;"
template <class T> class D {}; // expected-note{{template is declared here}}
template <class T> void E() {};
class F {};

void test3() {
  ::D<::F> A1;
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  D<::F> A2;
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  ::E<::F>();
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  E<::F>();
#if __cplusplus <= 199711L
  // expected-error@-2 {{found '<::' after a template name which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?}}
#endif

  ::D< ::F> A3;
  D< ::F> A4;
  ::E< ::F>();
  E< ::F>();

  // Make sure that parser doesn't expand '[:' to '< ::'
  ::D[:F> A5; // expected-error {{class template '::D' requires template arguments}} \
              // expected-error {{expected expression}} \
              // expected-error {{expected unqualified-id}}
}

// Ensure that a C-style cast doesn't turn off colon protection.
void PR19748() {
  struct A {};
  int A = 0, b;
  int test1 = true ? (int)A : b;

  struct f {};
  extern B f(), (*p)();
  (true ? (B(*)())f : p)();
}

void PR19751(int n) {
  struct T { void operator++(int); };
  (T())++; // ok, not an ill-formed cast to function type
  (T())++n; // expected-error {{C-style cast from 'int' to 'T ()' is not allowed}}
}

// PR13619. Must be at end of file.
int n = reinterpret_cast // expected-error {{expected '<'}} expected-error {{expected ';'}}