aboutsummaryrefslogtreecommitdiff
path: root/clang/test/Sema/implicit-int-enum-conversion.c
blob: 36717f36dd083aa3c58b0191ff910141118cb236 (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
// RUN: %clang_cc1 -fsyntax-only -verify -Wimplicit-int-enum-cast %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wc++-compat %s
// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
// RUN: %clang_cc1 -fsyntax-only -verify=good -Wno-implicit-enum-enum-cast %s
// RUN: %clang_cc1 -fsyntax-only -verify=good -Wc++-compat -Wno-implicit-enum-enum-cast -Wno-implicit-int-enum-cast %s
// good-no-diagnostics

enum E1 {
  E1_Zero,
  E1_One
};

enum E2 {
  E2_Zero
};

struct S {
  enum E1 e;
} s = { 12 }; // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
                 cxx-error {{cannot initialize a member subobject of type 'enum E1' with an rvalue of type 'int'}}

enum E1 foo(void) {
  int x;
  enum E1 e = 12; // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
                     cxx-error {{cannot initialize a variable of type 'enum E1' with an rvalue of type 'int'}}

  // Enum to integer is fine.
  x = e;

  // Integer to enum is not fine.
  e = x;    // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
               cxx-error {{assigning to 'enum E1' from incompatible type 'int'}}
  return x; // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
               cxx-error {{cannot initialize return object of type 'enum E1' with an lvalue of type 'int'}}
}

// Returning with the correct types is fine.
enum E1 bar(void) {
  return E1_Zero;
}

// Enum to different-enum conversion is also a C++ incompatibility, but is
// handled via a more general diagnostic, -Wimplicit-enum-enum-cast, which is
// on by default.
enum E1 quux(void) {
  enum E1 e1 = E2_Zero; // expected-warning {{implicit conversion from enumeration type 'enum E2' to different enumeration type 'enum E1'}} \
                           cxx-error {{cannot initialize a variable of type 'enum E1' with an rvalue of type 'E2'}}
  e1 = E2_Zero;         // expected-warning {{implicit conversion from enumeration type 'enum E2' to different enumeration type 'enum E1'}}   \
                           cxx-error {{assigning to 'enum E1' from incompatible type 'E2'}}
  return E2_Zero;       // expected-warning {{implicit conversion from enumeration type 'enum E2' to different enumeration type 'enum E1'}} \
                           cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'E2'}}
}

enum E1 comma1(void) {
  return ((void)0, E1_One);
}

enum E1 comma2(void) {
  enum E1 x;
  return
    (x = 12,  // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
                 cxx-error {{assigning to 'enum E1' from incompatible type 'int'}}
    E1_One);
}

enum E1 comma3(void) {
  enum E1 x;
  return ((void)0, foo()); // Okay, no conversion in C++
}

enum E1 comma4(void) {
  return ((void)1, 2); // expected-warning {{implicit conversion from 'int' to enumeration type 'enum E1' is invalid in C++}} \
                          cxx-error {{cannot initialize return object of type 'enum E1' with an rvalue of type 'int'}}
}