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

    <tr>
        <th>Summary</th>
        <td>
            Template parameter name resolution behavior difference from GCC
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    Can the name of a template parameter shadow the name of a member of that class?

## Example
Consider this example (https://godbolt.org/z/hrE3YEzPd):

```c++
#include <cstdint>

class Foo {
  template <typename Write>
  void WriteNestedMessage(uint32_t field_number, Write write_message);

 protected:
  void Write();
};

template <typename Write>
void Foo::WriteNestedMessage(uint32_t field_number, Write write_message) {}
```

In this example:
* We have an in-class template _declaration_ method named `WriteNestedMessage`. Its template argument `Write` shadows the name of the protected `Write` method.

* We have an out-of-class template _definition_ for `WriteNestedMessage` whose template argument is also named `Write`.

## Compilers
Clang accepts this code without complaint.

GCC complains:
```
<source>:12:53: error: 'Write' is not a type
   12 | void Foo::WriteNestedMessage(uint32_t field_number, Write write_message) {}
 |                                                     ^~~~~
<source>:12:6: error: no declaration matches 'void Foo::WriteNestedMessage(uint32_t, int)'
 12 | void Foo::WriteNestedMessage(uint32_t field_number, Write write_message) {}
      |      ^~~
<source>:5:8: note: candidate is: 'template<class Write> void Foo::WriteNestedMessage(uint32_t, Write)'
    5 |   void WriteNestedMessage(uint32_t field_number, Write write_message);
 |        ^~~~~~~~~~~~~~~~~~
<source>:3:7: note: 'class Foo' defined here
 3 | class Foo {
      |       ^~~
<source>:12:53: error: 'void Foo::Write()' is protected within this context
   12 | void Foo::WriteNestedMessage(uint32_t field_number, Write write_message) {}
 |                                                     ^~~~~
<source>:8:8: note: declared protected here
    8 |   void Write();
      | ^~~~~
Compiler returned: 1
```
It clearly believes -- in the template _definition_ -- that `Write` is referring to the protected method, not the template parameter of the same name.

## References

cppreference.com - [Template parameters](https://en.cppreference.com/w/cpp/language/template_parameters.html#Name_resolution_for_template_parameters) says a number of things, none of which directly apply, and are potentially contradictory:

> In the definition of a member of a class template that appears outside of the class template definition, the name of a member of the class template hides the name of a template parameter of any enclosing class templates, **but not a template parameter of the member if the member is a class or function template**.

This suggests that Clang is correct, and `Write` should refer to the template parameter, because we're defining an out-of-class function template.

> In the definition of a member of a class template that appears *outside of the namespace* containing the class template definition, the name of a template parameter hides the name of a member of this namespace.

This also suggests that Clang is correct, though it might not apply due to the "outside of the namespace" part.

> In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each non-dependent base class, if the name of the base class or the name of a member of the base class is the same as the name of a template parameter, the base class name or member name hides the template parameter name.

This suggest that GCC is correct, though it might not apply because it specifically refers to members of base classes (and not the enclosing class).





---

*(cross-posted at https://stackoverflow.com/questions/79706653)*
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWN-v6rgR_mvMywgEDiHwwAOXc6hupa6q1UqrPiFjD8RtYqe2c1j24f7t1TgJCb_29Fa3lYqieyE49jfffDPzHYT3-mQQ1yz9wtK3kahDbt36z9aIkFvzM2qTCxdGB6su660wEHIEI0oEewQBAcuqEAGhEk6UGNCBz4Wy57t1JZYHdPQ-5CKALIT3LNmx6YYunjCewPtvoqwKZNPN1hqvFToIufaAzX1gfJmHUHmWbBjfMb47WXWwRZhYd2J89zvju9y9J397__2vivEVLWu2X0ybSzL-ha54ojayqBUCS7bSB6VNYMl780BEBztrgWW0GvowWbINlwpjYL86HbB5CODDatXc-Ql9QPUX9F6ckPFlrU1I-D7AUWOh9qYmJhjfNqvhTP_uy275iiVfGhRQORtQBlRNJMMzGF_2S7O36zOf4Yw77KylHZPNj4AbKcrehjQ3UL6am-y12eAb-BUhFx8IwoA244brK-69QlkIJ4K2Zg8lhtyqKCMFbDF9AngxncDXMNhBuFNdognX9WwxbTXpb0RJ768U36xujp104ryBbOswtscnsI_a6Ab10bqXYOGcW49P0GoPovD2LlYK76ZGtrasdIHOU5UUwpxASIkVEUBkS6sQzjrktg4gLR2iTWi3-NN2e73n23wMc5Zsva2djFJJNjPOkk2asGQD6Jx19IbxrJVfRoCNDdQCLhVGecKMA8u28N8UWTzgP3mx9P3bt2_fXsS5uAnTWBjIEEoRZI6eov-O0Cgaaip8xXhGyP8X7DShdhTFmB8jTlmyWTZxUl_YgBRGaUVy1L5NcydQ6o5R6l0T-R78V8g9CQCQtgB_cMccKqNN9s3rkQfSdjbkgfHs2vpJ4rGoUUGOLio8iWc8Tocb0l-x_qKentDZNvemxvoORWWtTVfnJuBv4f-47Jb3ImwqDtUg4o53AFg-iGY4AvsU9Od1nRIchtqZOEVhdtfzvpIVQeGKCxyw0PiBHsZj0I3Ned7ex-PGwwwnhvbg8IjOaXOCYO9mSzNPiGfqmDc797apnUiephMNgdu-_zPtjkaiby1KVbnu1kTaEsbA0i-_PGzrWfr24JvQTO6fZ3x3Znwnq4rxHc2VOkpg1wHd9ztO8lAWjCc_iRL3Dr0t6kjM0br9k-WkIy8uHgQ0emsi1ebkG0ZMnMbnXMsclHYoQ3EBUVXFhb4XRoFwCJUNaIIWRXGJ6ndCaRmsu_Q2L3mHr03i-nTdu08Bd5M7plJUFQrnabiT7-xycbe035WAvfa3Dw_mWqH_3DjTfXMBNLKwnoR0u02ki3EyJIc6dMP3pZBaRPr2k78yYB0cayMjSdduH3dvlfcLNRpfn07oo70QARrHEfuPo0R1Cbq1WrYuVFMOXSk8oqQnDyhF7RHO5Cdcxy9Zmjub9YBz8sMyzvjmLumUIl8JSWREpYkG1HcK4klinslgqBtyVN3hwxxEX_h5Isj0nXLQAUp9yluBUBmBqrHLBOP8dbycwIbPyb2jwbquYb7Ogq9lPmTlj8ruBb9kq1HInFrGWGGFRpFxPgjfJiY6ruODx-8XENI_KtvBSu37biw-r90u_4MdmuWuOyJ-7BXwRB6Dpj8svYYq8u7_brq7utIBfIVSH7WMbTOWpCclNJg8RdMjjg53SeXcTam7TsT4qtPG4BqPx9c_lBhfSme9H1eWjAeIALeTxwch_2E_0B0Le27nzj9r9JRjz_guW2XTxSJNov_ZjNQ6UatkJUa4nmUpXy6yVZqO8vU0XfF5Mk2y2WI1zxJEeZwrLg5yJtVMpnyk13zK02k2W85W8zRNJ8lqOk3n8-UCs0OCiWTzKZZCF5Oi-Cgn1p1G2vsa17P5Ks3SUSEOWPj4mwjnBs8Qv2Wcs_Rt5Nb00PhQnzybTwvtg--3CToUuH4cxI0A-nEJB8zFh7YOlD62gxiOzpaU6lHtivXdbx065PWhpYxOa_8bV87-PUpiFzESi20QH2v-rwAAAP__0kraNw">