summaryrefslogtreecommitdiff
path: root/test/SemaCXX/switch.cpp
blob: 0c60ce02097bbf47ae2b62b69c3db4b7f3d3b861 (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
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s

void test() {
  bool x = true;
  switch (x) { // expected-warning {{bool}}
    case 0:
      break;
  }

  int n = 3;
  switch (n && true) { // expected-warning {{bool}}
    case 1:
      break;
  }
}

// PR5518
struct A { 
  operator int(); // expected-note{{conversion to integral type}}
};

void x() { 
  switch(A()) {
  }
}

enum E { e1, e2 };
struct B : A {
  operator E() const; // expected-note{{conversion to enumeration type}}
};

void x2() {
  switch (B()) { // expected-error{{multiple conversions}}
  }
}

struct C; // expected-note{{forward declaration}}

void x3(C &c) {
  switch (c) { // expected-error{{incomplete class type}}
  }
}

namespace test3 {
  enum En { A, B, C };
  template <En how> void foo() {
    int x = 0, y = 5;

    switch (how) { //expected-warning {{no case matching constant switch condition '2'}}
    case A: x *= y; break;
    case B: x += y; break;
    // No case for C, but it's okay because we have a constant condition.
    }
  }

  template void foo<A>();
  template void foo<B>();
  template void foo<C>(); //expected-note {{in instantiation}}
}

// PR9304 and rdar://9045501
void click_check_header_sizes() {
  switch (0 == 8) {  // expected-warning {{switch condition has boolean value}}
  case 0: ;
  }
}

void local_class(int n) {
  for (;;) switch (n) {
  case 0:
    struct S {
      void f() {
        case 1: // expected-error {{'case' statement not in switch statement}}
        break; // expected-error {{'break' statement not in loop or switch statement}}
        default: // expected-error {{'default' statement not in switch statement}}
        continue; // expected-error {{'continue' statement not in loop statement}}
      }
    };
    S().f();
    []{
      case 2: // expected-error {{'case' statement not in switch statement}}
      break; // expected-error {{'break' statement not in loop or switch statement}}
      default: // expected-error {{'default' statement not in switch statement}}
      continue; // expected-error {{'continue' statement not in loop statement}}
    }();
  }
}

namespace Conversion {
  struct S {
    explicit operator int(); // expected-note {{conversion}}
  };
  template<typename T> void f(T t) {
    switch (t) { // expected-error {{explicit conversion}}
    case 0:
      return;
    default:
      break;
    }
  }
  template void f(S); // expected-note {{instantiation of}}
}

// rdar://29230764
namespace OpaqueEnumWarnings {

enum Opaque : int;
enum class OpaqueClass : int;

enum class Defined : int;
enum class Defined : int { a };

void test(Opaque o, OpaqueClass oc, Defined d) {
  // Don't warn that case value is not present in opaque enums.
  switch (o) {
  case (Opaque)1:
    break;
  }
  switch (oc) {
  case (OpaqueClass)1:
    break;
  }

  switch (d) {
  case Defined::a:
    break;
  case (Defined)2: // expected-warning {{case value not in enumerated type 'OpaqueEnumWarnings::Defined'}}
    break;
  }
}

}