Skip to content

bug: case statements are nested if C++ attributes are used #344

@mrwsl

Description

@mrwsl

Did you check existing issues?

  • I have read all the tree-sitter docs if it relates to using the parser
  • I have searched the existing issues of tree-sitter-cpp

Tree-Sitter CLI Version, if relevant (output of tree-sitter --version)

No response

Describe the bug

Consider the following example:

switch (Mychar) {
  [[likely]]   case '1': { assert(OtherVar > 1); }
  [[unlikely]] case '2': { assert("2" && false); }
  [[unlikely]] case '3': { assert("3" && true); }
  [[unlikely]] case '4': { assert("" && true); }
}

switch (Mychar) {
  case '1': { assert(OtherVar > 1); }
  case '2': { assert("2" && false); }
  case '3': { assert("3" && true); }
  case '4': { assert("" && true); }
}

The resulting tree from the playground:

translation_unit [0, 0] - [14, 0]
  switch_statement [0, 0] - [5, 1]
    condition: condition_clause [0, 7] - [0, 15]
      value: identifier [0, 8] - [0, 14]
    body: compound_statement [0, 16] - [5, 1]
      attributed_statement [1, 2] - [4, 48]
        attribute_declaration [1, 2] - [1, 12]
          attribute [1, 4] - [1, 10]
            name: identifier [1, 4] - [1, 10]
        case_statement [1, 15] - [4, 48]
          value: char_literal [1, 20] - [1, 23]
            character [1, 21] - [1, 22]
          compound_statement [1, 25] - [1, 50]
            expression_statement [1, 27] - [1, 48]
              call_expression [1, 27] - [1, 47]
                function: identifier [1, 27] - [1, 33]
                arguments: argument_list [1, 33] - [1, 47]
                  binary_expression [1, 34] - [1, 46]
                    left: identifier [1, 34] - [1, 42]
                    right: number_literal [1, 45] - [1, 46]
          attributed_statement [2, 2] - [4, 48]
            attribute_declaration [2, 2] - [2, 14]
              attribute [2, 4] - [2, 12]
                name: identifier [2, 4] - [2, 12]
            case_statement [2, 15] - [4, 48]
              value: char_literal [2, 20] - [2, 23]
                character [2, 21] - [2, 22]
              compound_statement [2, 25] - [2, 50]
                expression_statement [2, 27] - [2, 48]
                  call_expression [2, 27] - [2, 47]
                    function: identifier [2, 27] - [2, 33]
                    arguments: argument_list [2, 33] - [2, 47]
                      binary_expression [2, 34] - [2, 46]
                        left: string_literal [2, 34] - [2, 37]
                          string_content [2, 35] - [2, 36]
                        right: false [2, 41] - [2, 46]
              attributed_statement [3, 2] - [4, 48]
                attribute_declaration [3, 2] - [3, 14]
                  attribute [3, 4] - [3, 12]
                    name: identifier [3, 4] - [3, 12]
                case_statement [3, 15] - [4, 48]
                  value: char_literal [3, 20] - [3, 23]
                    character [3, 21] - [3, 22]
                  compound_statement [3, 25] - [3, 49]
                    expression_statement [3, 27] - [3, 47]
                      call_expression [3, 27] - [3, 46]
                        function: identifier [3, 27] - [3, 33]
                        arguments: argument_list [3, 33] - [3, 46]
                          binary_expression [3, 34] - [3, 45]
                            left: string_literal [3, 34] - [3, 37]
                              string_content [3, 35] - [3, 36]
                            right: true [3, 41] - [3, 45]
                  attributed_statement [4, 2] - [4, 48]
                    attribute_declaration [4, 2] - [4, 14]
                      attribute [4, 4] - [4, 12]
                        name: identifier [4, 4] - [4, 12]
                    case_statement [4, 15] - [4, 48]
                      value: char_literal [4, 20] - [4, 23]
                        character [4, 21] - [4, 22]
                      compound_statement [4, 25] - [4, 48]
                        expression_statement [4, 27] - [4, 46]
                          call_expression [4, 27] - [4, 45]
                            function: identifier [4, 27] - [4, 33]
                            arguments: argument_list [4, 33] - [4, 45]
                              binary_expression [4, 34] - [4, 44]
                                left: string_literal [4, 34] - [4, 36]
                                right: true [4, 40] - [4, 44]
  switch_statement [7, 0] - [12, 1]
    condition: condition_clause [7, 7] - [7, 15]
      value: identifier [7, 8] - [7, 14]
    body: compound_statement [7, 16] - [12, 1]
      case_statement [8, 2] - [8, 37]
        value: char_literal [8, 7] - [8, 10]
          character [8, 8] - [8, 9]
        compound_statement [8, 12] - [8, 37]
          expression_statement [8, 14] - [8, 35]
            call_expression [8, 14] - [8, 34]
              function: identifier [8, 14] - [8, 20]
              arguments: argument_list [8, 20] - [8, 34]
                binary_expression [8, 21] - [8, 33]
                  left: identifier [8, 21] - [8, 29]
                  right: number_literal [8, 32] - [8, 33]
      case_statement [9, 2] - [9, 37]
        value: char_literal [9, 7] - [9, 10]
          character [9, 8] - [9, 9]
        compound_statement [9, 12] - [9, 37]
          expression_statement [9, 14] - [9, 35]
            call_expression [9, 14] - [9, 34]
              function: identifier [9, 14] - [9, 20]
              arguments: argument_list [9, 20] - [9, 34]
                binary_expression [9, 21] - [9, 33]
                  left: string_literal [9, 21] - [9, 24]
                    string_content [9, 22] - [9, 23]
                  right: false [9, 28] - [9, 33]
      case_statement [10, 2] - [10, 36]
        value: char_literal [10, 7] - [10, 10]
          character [10, 8] - [10, 9]
        compound_statement [10, 12] - [10, 36]
          expression_statement [10, 14] - [10, 34]
            call_expression [10, 14] - [10, 33]
              function: identifier [10, 14] - [10, 20]
              arguments: argument_list [10, 20] - [10, 33]
                binary_expression [10, 21] - [10, 32]
                  left: string_literal [10, 21] - [10, 24]
                    string_content [10, 22] - [10, 23]
                  right: true [10, 28] - [10, 32]
      case_statement [11, 2] - [11, 35]
        value: char_literal [11, 7] - [11, 10]
          character [11, 8] - [11, 9]
        compound_statement [11, 12] - [11, 35]
          expression_statement [11, 14] - [11, 33]
            call_expression [11, 14] - [11, 32]
              function: identifier [11, 14] - [11, 20]
              arguments: argument_list [11, 20] - [11, 32]
                binary_expression [11, 21] - [11, 31]
                  left: string_literal [11, 21] - [11, 23]
                  right: true [11, 27] - [11, 31]

In the first switch statement, the case_statement are nested into the first one. If the attributes are ommitted the result is as expected.

Steps To Reproduce/Bad Parse Tree

  1. Use C++ attributes in a switch statement

Expected Behavior/Parse Tree

see above

Repro

switch (Mychar) {
  [[likely]]   case '1': { assert(OtherVar > 1); }
  [[unlikely]] case '2': { assert("2" && false); }
  [[unlikely]] case '3': { assert("3" && true); }
  [[unlikely]] case '4': { assert("" && true); }
}

switch (Mychar) {
  case '1': { assert(OtherVar > 1); }
  case '2': { assert("2" && false); }
  case '3': { assert("3" && true); }
  case '4': { assert("" && true); }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions