<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/61204>61204</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Wrong formatting of the pretty-printed return value of clang_getTypeSpelling()
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          vedgy
      </td>
    </tr>
</table>

<pre>
    When `clang_getTypeSpelling()` returns a value that contains `operator>`, `operator<=` or `operator-` followed by a closing angle bracket or `operator<` followed by an opening angle bracket, it does not insert whitespace between these two tokens. This makes the returned value invalid C++ and prevents *libclang* users from parsing it correctly. For example:

```cpp
namespace FormattingBug {
class X{};
bool operator>(X, int) { return true; }
bool operator<=(X, int) { return true; }
bool operator-(X, int) { return true; }
template<typename T> bool operator<(T, int) { return true; }

template<decltype(operator>)> class C{};
C<&operator> > gt;      // pretty-printed as "C<&operator>>"
C<&operator<= > le;     // pretty-printed as "C<&operator<=>"
C<&operator- > minus;   // pretty-printed as "C<&operator->"
C<&operator< <X>> lt;   // pretty-printed as "C<&operator<<FormattingBug::X>>"
}
```

When the space between the tokens is removed in the source code, like in the pretty-printed string, it does not compile. In simple cases like these, the user of `clang_getTypeSpelling()` can count the number of angle brackets and distinguish parts of operators from angle brackets. But this becomes unfeasible for more complicated types.

--------------------

I believe `clang_getTypeSpelling()`, or more likely `QualType::print()` used by it, should insert a tab character between such tokens to pretty-print compilable code. The tab character is preferable to the space character here, because the users may rely on the fact that pretty-printed binary operators are surrounded by spaces to distinguish them from angle brackets.

------------------

I think workaround code for the closing-angle-bracket part of this bug can be added into [`TemplateArgs::printLeft()`](https://github.com/llvm/llvm-project/blob/2e999b7dd1934a44d38c3a753460f1e5a217e9a5/llvm/include/llvm/Demangle/ItaniumDemangle.h#L1393). If the last printed template parameter was `operator>`, `operator<=` or `operator-`, insert a tab: `OB += "\t";` before the `OB += ">";` line.

And workaround code for the opening-angle-bracket part of this bug can be added into [`NameWithTemplateArgs::printLeft()`](https://github.com/llvm/llvm-project/blob/2e999b7dd1934a44d38c3a753460f1e5a217e9a5/llvm/include/llvm/Demangle/ItaniumDemangle.h#L1490). If the printed `Name` was `operator<`, insert a tab: `OB += "\t";` before the `TemplateArgs->print(OB);` line.

The last-printed-template-parameter and printed-`Name` checks can be implemented in terms of a simple new helper member function of [`class OutputBuffer`](https://github.com/llvm/llvm-project/blob/2e999b7dd1934a44d38c3a753460f1e5a217e9a5/llvm/include/llvm/Demangle/Utility.h#L31): `bool OutputBuffer::endsWith(const char *S) const;`.

--------------------

This bug originally affected *clang-format* as well, was reported as #58602 and closed by a *clang-format*-specific fix. This issue reports only the remaining, not fixed *libclang* part of the bug.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzcV12P27oR_TX0y8CGTPlLD36wvddAgIsGxd0i-1ZQ1EhilyIFklrH_74YSlp_bdK7aR-Ku0iyCMUZzpxzODMU3qvKIG7Zcs-WTxPRhdq67RsW1XmS2-K8_VajAbZKpBam-meF4fnc4h8taq1MxfiG8YytEnAYOmc8CHgTukMItQggrQlCGU_2tkUngnUs_Y2tEsYPt4sHlj6RH-uu16e0VFqt7QkLyM8gQGrrlalAmEoj5E7IVwx3ZuTu3tCAbdE8WFIgKkBh0YOxAZTx6AKcahXQt0Ii5BhOiAZCjR4hnCwE-4rGz-C5Vh4a8YqePg4QYDEgoMyb0KqAA-N7xvcgTAGtwzc0wQPjO63yiCnjO-g8Og-lsw20wsX8FMHnHMqgzzM4Wgf4XTStRpbuWPLEkvHfVdL_kW3brxjRDKEfrWtECMpU-64Ctt73G6QW3sML_X_9xNJhNbdWwzVLfPMS0TGB8YyshwwhuA5Zugey_sg0cvmL1tNPGAZsWi0CsvQQzi1S3vDM0t_gIR6-ef6TPh88Fyg1eWd8cwNORgf1SB7ukDzEI1dX24H-VoFOij-MHxk_khxCOE9bp0zAAgTpgj9ax_P4D3wT2NG9xtH9p7xHsn58wDT6bpTpfO_-E86nPw8cWHp46dMDHT7tPYZ-uJE4XY1093IH2YXb8apcUx3rG13fh9s-3HNQHhw29g0LUMNW2zmJIG2BJCutXnH8dBe5Dy6WydsiI23TKo0z-GLAK7rUIIVH33uKhYZMyB9VBrDln6jAUhiQtjMh2pmuyXvLm3LnYxkqlCfEOuVrqjfB074R16EO3ZrNYN-RY-UhR2kb9NCZEoVXuUYorYPGOoyJaSUFpU6Xxs-uoZ5-8HP9_QvkqBW-4X_OluAZDyXQ9Jls_t4JTdt7HUQOLvh0vu8EKtZ8X9tOF2O5FxBEDrIWTsiA7l0FvpP1KINgb8gdSBSUPwmB2gHeuVGeTEp0cVewVzq7bKrRRbZzlKLz-M46tZYzOErN9toqhQx9Y71TWa6McOcrBoVD8J1ztjNFn3U8NSZxTX6osfmQ7p_TdktaqJV5hZN1ryIeGOGImqCgh349jQdMx35NqiPR9YrqqqjeHEEURbxmwQJNJKvkeajEO1f5K1p_x_JCLVtSu6lDaOOWWEIqFeoun0nbMH7U-m38NW2d_RfKwPgx1zZn_Mgxy7J8XRTzLF2IxaJINzIV62W6WCXlHJeCz9eYieXFjzJSd3T1x4UnbGJ6jB-_BGFU14wrs5rx9Pd5mqWMZzP4UkZMtPDEYU_e2GsIE9EgSeIk_ruRqe91F2WzdEdbvu6BZhHqF5yz5SHQr5RQhhxLukoU3MPGvpT2-7QyeCOOnSl-SP0wcP0q9X8TDX5Tof5rSGCRJdcSGNkf8iRsH1g__A-ovAaP-vFYFL_u4wjzManPg0bHAjMdNTq9aLQfZ_vPV0nIGuWrHzmNva3BmCk1SHRN7DVibHsGT1CjbtFBg7FjlZ2RQVkTm17UQT9kfe1C24V9V5bo_s8I_0dQWoVzT3Q6j8BGluIcehN4lC-awpOwGd9Ia3yIzYCeBH_QdBqXemY-1T2fx_tknaqUEVqfQZQlyigzvosNdVrGeYneHMLDCbUmgZHyHLbWvQ9b6XKzSngkmQr4-Ph6dDP1LUpVKgml-j48iZT3HQ4OPVijz8P7qBHKDOMQjUGl-t6Hdv0UupQHpGxmk2KbFlmaiQlu56v1JsnS1WIzqbeLtFhmmGRZniVlNhdzvirm8_W8XGNWFrycqC1PeJqkySrJkjXfzBZFmst5lvOszBarRckWCYWkZ0TpzLpqEiPfruY8WUy0yFH78WHstlFJeVd5tki08sFfzIIKGrffnDUVlO8D6ZjFXbMeXh79I9GW8JNBZ9I5vf20xmMSnvFjzOPfAQAA___6Cg5e">