github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/switch.c (about)

     1  // This file tests the various forms of switch statement.
     2  //
     3  // We must be extra sensitive to the fact that switch fallthrough is handled
     4  // differently in C and Go. Break statements are removed and fallthrough
     5  // statements are added when nessesary.
     6  //
     7  // It is worth mentioning that a SwitchStmt has a CompoundStmt item that
     8  // contains all of the cases. However, if the individual case are not enclosed
     9  // in a scope each of the case statements and their childen are part of the same
    10  // CompoundStmt. For example, the first switch statement below contains a
    11  // CompoundStmt with 12 children.
    12  
    13  #include "tests.h"
    14  #include <stdio.h>
    15  
    16  void match_a_single_case()
    17  {
    18      switch (1) {
    19      case 0:
    20          fail("code should not reach here");
    21          break;
    22      case 1:
    23          pass(__func__);
    24          break;
    25      case 2:
    26          fail("code should not reach here");
    27          break;
    28      default:
    29          fail("code should not reach here");
    30          break;
    31      }
    32  }
    33  
    34  void fallthrough_to_next_case()
    35  {
    36      switch (1) {
    37      case 0:
    38          fail("code should not reach here");
    39          break;
    40      case 1:
    41          pass(__func__);
    42      case 2:
    43          pass(__func__);
    44          break;
    45      default:
    46          fail("code should not reach here");
    47          break;
    48      }
    49  }
    50  
    51  void match_no_cases()
    52  {
    53      switch (1) {
    54      case 5:
    55          fail("code should not reach here");
    56          break;
    57      case 2:
    58          fail("code should not reach here");
    59          break;
    60      }
    61  }
    62  
    63  void match_default()
    64  {
    65      switch (1) {
    66      case 5:
    67          fail("code should not reach here");
    68          break;
    69      case 2:
    70          fail("code should not reach here");
    71          break;
    72      default:
    73          pass(__func__);
    74          break;
    75      }
    76  }
    77  
    78  void fallthrough_several_cases_including_default()
    79  {
    80      switch (1) {
    81      case 0:
    82          fail("code should not reach here");
    83      case 1:
    84          pass(__func__);
    85      case 2:
    86          pass(__func__);
    87      default:
    88          pass(__func__);
    89      }
    90  }
    91  
    92  void scoped_match_a_single_case()
    93  {
    94      switch (1) {
    95      case 0: {
    96          fail("code should not reach here");
    97          break;
    98      }
    99      case 1: {
   100          pass(__func__);
   101          break;
   102      }
   103      case 2: {
   104          fail("code should not reach here");
   105          break;
   106      }
   107      default: {
   108          fail("code should not reach here");
   109          break;
   110      }
   111      }
   112  }
   113  
   114  void scoped_fallthrough_to_next_case()
   115  {
   116      switch (1) {
   117      case 0: {
   118          fail("code should not reach here");
   119          break;
   120      }
   121      case 1: {
   122          pass(__func__);
   123      }
   124      case 2: {
   125          pass(__func__);
   126          break;
   127      }
   128      default: {
   129          fail("code should not reach here");
   130          break;
   131      }
   132      }
   133  }
   134  
   135  void scoped_match_no_cases()
   136  {
   137      switch (1) {
   138      case 5: {
   139          fail("code should not reach here");
   140          break;
   141      }
   142      case 2: {
   143          fail("code should not reach here");
   144          break;
   145      }
   146      }
   147  }
   148  
   149  void scoped_match_default()
   150  {
   151      switch (1) {
   152      case 5: {
   153          fail("code should not reach here");
   154          break;
   155      }
   156      case 2: {
   157          fail("code should not reach here");
   158          break;
   159      }
   160      default: {
   161          pass(__func__);
   162          break;
   163      }
   164      }
   165  }
   166  
   167  void scoped_fallthrough_several_cases_including_default()
   168  {
   169      switch (1) {
   170      case 0: {
   171          fail("code should not reach here");
   172      }
   173      case 1: {
   174          pass(__func__);
   175      }
   176      case 2: {
   177          pass(__func__);
   178      }
   179      default: {
   180          pass(__func__);
   181      }
   182      }
   183  }
   184  
   185  typedef struct I67 I67;
   186  struct I67 {
   187      int x, y;
   188  };
   189  
   190  void run(I67* i, int pos)
   191  {
   192      switch (pos) {
   193      case 0:
   194          (*i).x += 1;
   195          (*i).y += 1;
   196          break;
   197      case 1:
   198          (*i).x -= 1;
   199          (*i).y -= 1;
   200          break;
   201      }
   202  }
   203  
   204  void run_with_block(I67* i, int pos)
   205  {
   206      switch (pos) {
   207      case 0: {
   208          (*i).x += 1;
   209          (*i).y += 1;
   210          break;
   211      }
   212      case 1: {
   213          (*i).x -= 1;
   214          (*i).y -= 1;
   215      } break;
   216      case 2:
   217          (*i).x *= 1;
   218          (*i).y *= 1;
   219          break;
   220      default:
   221          (*i).x *= 10;
   222          (*i).y *= 10;
   223      }
   224  }
   225  
   226  void switch_issue67()
   227  {
   228      I67 i;
   229      i.x = 0;
   230      i.y = 0;
   231      run(&i, 0);
   232      is_eq(i.x, 1);
   233      is_eq(i.y, 1);
   234      run(&i, 1);
   235      is_eq(i.x, 0);
   236      is_eq(i.y, 0);
   237      run_with_block(&i, 0);
   238      is_eq(i.x, 1);
   239      is_eq(i.y, 1);
   240      run_with_block(&i, 1);
   241      is_eq(i.x, 0);
   242      is_eq(i.y, 0);
   243  }
   244  
   245  void empty_switch()
   246  {
   247      int pos = 0;
   248      switch (pos) {
   249      }
   250      is_eq(pos, 0);
   251  }
   252  
   253  void default_only_switch()
   254  {
   255      int pos = 0;
   256      switch (pos) {
   257      case -1: // empty case
   258      case -1 - 4: // empty case
   259      case (-1 - 4 - 4): // empty case
   260      case (-3): // empty case
   261      case -2: // empty case
   262      default:
   263          pos++;
   264      }
   265      is_eq(pos, 1);
   266  }
   267  
   268  void switch_without_input()
   269  {
   270      int pos = 0;
   271      switch (0) {
   272      default:
   273          pos++;
   274      }
   275      is_eq(pos, 1);
   276  }
   277  
   278  void test_switch()
   279  {
   280      int val = 1;
   281      switch (0) {
   282      case -1000:
   283      default:
   284          // ignored
   285          val += 3;
   286      case -1:
   287          val += 1;
   288      case 2: {
   289          val *= 2;
   290      }
   291      case 3: {
   292          val *= 4;
   293      }
   294      case 4:
   295      case 5:
   296          val += 5;
   297      case 6:
   298      case 7:
   299          val *= 6;
   300          break;
   301      case 8:;
   302      case 9:;
   303      case 10:;
   304      }
   305      is_eq(val, 270);
   306  }
   307  
   308  void switch_bool()
   309  {
   310      double x = 3.0;
   311      switch (x < 0.0) {
   312      case 0:
   313          pass("ok");
   314          break;
   315      case 1:
   316          fail("switch_bool 1");
   317          break;
   318      default:
   319          fail("switch_bool 3");
   320      }
   321      int y = 7;
   322      const int t = 0;
   323      switch (y) {
   324      case 0 == t:
   325          fail("switch_bool 4");
   326          break;
   327      case 1 == t:
   328          fail("switch_bool 5");
   329          break;
   330      default:
   331          pass("ok");
   332          break;
   333      }
   334  }
   335  
   336  void switch_char()
   337  {
   338      char form = '1';
   339      switch (form) {
   340      default:
   341      case '1':
   342          form = 'S';
   343          break;
   344      case 0:;
   345      };
   346      is_eq(form, 'S');
   347  }
   348  
   349  int value()
   350  {
   351      return 42;
   352  }
   353  
   354  void switch_stat()
   355  {
   356      int v = 15;
   357      switch (v = value()) {
   358      case 15:
   359          fail("wrong");
   360          break;
   361      case 42:
   362          is_true(v == 42);
   363          break;
   364      }
   365  }
   366  
   367  int case_inside_block(int a)
   368  {
   369      switch (a) {
   370      case 1:
   371          break;
   372      case 2: {
   373          a = 42;
   374      case 3:
   375          a += 45;
   376          break;
   377      }
   378      case 4:
   379          break;
   380      }
   381      return a;
   382  }
   383  
   384  int main()
   385  {
   386      plan(37);
   387  
   388      switch_char();
   389      switch_bool();
   390      match_a_single_case();
   391      fallthrough_to_next_case();
   392      match_no_cases();
   393      match_default();
   394      fallthrough_several_cases_including_default();
   395      test_switch();
   396  
   397      // For each of the tests above there will be identical cases that use scopes
   398      // for the case statements.
   399      scoped_match_a_single_case();
   400      scoped_fallthrough_to_next_case();
   401      scoped_match_no_cases();
   402      scoped_match_default();
   403      scoped_fallthrough_several_cases_including_default();
   404  
   405      switch_issue67();
   406      empty_switch();
   407      default_only_switch();
   408      switch_without_input();
   409      switch_stat();
   410  
   411      is_eq(case_inside_block(0), 0);
   412      is_eq(case_inside_block(1), 1);
   413      is_eq(case_inside_block(2), 45 + 42);
   414      is_eq(case_inside_block(3), 3 + 45);
   415      is_eq(case_inside_block(4), 4);
   416      is_eq(case_inside_block(5), 5);
   417  
   418      diag("without parens");
   419      {
   420          int x = 0;
   421          switch (x)
   422          case 0:
   423              pass("ok");
   424          (void)(x);
   425      }
   426  
   427      done_testing();
   428  }