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

    <tr>
        <th>Summary</th>
        <td>
            `noderef` attribute does not work in `[[]]` spelling
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:frontend
      </td>
    </tr>

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

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

<pre>
    While working on https://reviews.llvm.org/D126061, I noticed that the `noderef` attribute does not work in the `[[]]` spelling.

Here is an example ([godbolt link](https://godbolt.org/z/f19Yszoxn)), with comments describing the actual behavior as well as what I think the desired behavior should be:

```
void f() {
    // Actual: warning: 'noderef' can only be used on an array or pointer type
    // Desired: Either keep current diagnostic or forbid `noderef` on declarations
    [[clang::noderef]] int i;

    // Actual: No diagnostic
    // Desired: Either diagnose the faulty dereference or forbid `noderef` on declarations
    [[clang::noderef]] int *p1;
    *p1;

    // Actual: No diagnostic
    // Desired: Either diagnose the faulty dereference or forbid `noderef` on declarations
    int *p2 [[clang::noderef]];
    *p2;

    // Actual: error: 'noderef' attribute cannot be applied to types
    // Desired: Allow attribute in this position, but warn that it can only be used on array or pointer types
    int [[clang::noderef]] *p3;
    *p3;

    // Actual: warning: 'noderef' can only be used on an array or pointer type
    // Desired: Allow attribute in this position, diagnose the faulty dereference
    int * [[clang::noderef]] p4;
    *p4;

    // Actual: warning: 'noderef' can only be used on an array or pointer type [-Wignored-attributes]
    // Desired: Either
    // - diagnose the faulty dereference
    // - forbid `noderef` on typedefs, or
    // - forbid `noderef` on declarations
    typedef int *IntPtr;
    [[clang::noderef]] IntPtr p5;
    *p5;

    // Actual: error: 'noderef' attribute cannot be applied to types
    // Desired: Either diagnose the faulty dereference or forbid `noderef` on typedefs
    typedef int *IntPtr;
    IntPtr [[clang::noderef]] p6;
    *p6;
}
```

It’s not exactly clear to me why the attribute doesn’t work in the `[[]]` spelling. From my understanding of the code, my expectation would be that the declaration `[[clang::noderef]] int *p1;` should cause a warning on the subsequent dereference (even though it’s not really correct to place a `[[]]` type attribute on a declaration). In debugging this, I have verified that a `NoDerefAttr` does get placed on the `int` type, just like it does with the `__attribute__` spelling. From there on out, the different spelling should not really have an influence on the behavior, but apparently they do; I have not been able to determine the reason for this.

Certainly, one thing that makes `noderef` special is that there is special logic in SemaType.cpp to associate `noderef` with the pointer operand to the _right_ of the attribute, rather than the pointer operand to the _left_ of the attribute (see `TypeProcessingState::parsedNoDeref` and `ExpectNoDerefChunk` in `GetFullTypeForDeclarator()`). Correspondingly, the `NoDerefAttr` is placed on the pointee type, rather than the pointer type, as would be more usual for pointer attributes. This doesn’t explain why the `[[]]` spelling doesn’t work though.

This special behavior will however make it more difficult to get the `[[]]` spelling to work correctly. The C++ standard has clear rules on the entity that an attribute appertains to in a particular position, and attributes that appertain to a pointer must be placed to the right of the `*`. A `noderef` pointer should therefore be declared as `int * [[clang::noderef]] p4;`. This implies that the `NoDerefAttr` would be placed on the pointer type, rather than the pointee type as it is done today.

Probably the best way to fix this would be to retain the special processing for the GNU spelling of the attribute, but modify it so that the the `NoDerefAttr` is placed on the pointer type; I believe the existing `ExpectNoDerefChunk` logic, which is currently only used for diagnostics, could be used to do this. The code that diagnoses dereferences of `noderef` pointers would then be changed correspondingly to expect the attribute on the pointer, not the pointee.

As https://reviews.llvm.org/D126061 will make changes to the way `[[]]` attributes are handled, I would request that any fix should wait until that patch has landed.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzNWE1v2zgQ_TXyhYhhK3EcH3zIR9PNpSjQLhZ7CmiJstlQopak4ri_ft8MJdmO3cTFortbqEksUcOZN2_eDL2w-Wb-x0obJdbWPelqKWwlViHUPjm_TtJ7XE49a7X2Q2Oey6F1S9y6G6eXo8txkt6KB1HZoDOVi7CSAT-USC5Hlc2VUwX-EjIEpxdNUCK3ytNq3kroqlucTG74uqMLb_haGQNXhsnoLhldx5-_wZ7QXshKqBdZ1vA4Sa_w3tLmC2uCwBtPZCC92ne_fd56_h3_i_HsT__dvlRJOuPrVqx1WInMlqWqghe58hl8JjTIRZmFRhqxUCv5rK0T0os1POTfFPMDVmFzXotXtQMY_WK_so2hz-TQTjwUd7z447PVuSgoonQmkulNvCvwL0YhrtkJGBFr6Sq4Rn8m6bRDOp2KDNjYymywmWg8nEAqcUs6JzcCrtRWV0E5ETa1OrB_Fx0nqx8ABpY9KVWLrHEOmIhcy2VlPTJNlgrrFvB3P9HYLVeZkU4GbSu_swPnF0_YaVzdS5xxECEInZzf7KJzNPBPdseNEwJoFytOTCEbEzaCN8b_KlO_JJAkva7HfTDRvd07_-fwOv_TdwI9CC89JTzlnHWHpN3KA-hL4gDyyro2mhTFMlf9W2BcG2PXO1ZYVqATtfWa4qPqxgOumihROhyvlGNl8hqdtwlAWJwfoHN-Cjq_vKhPwekdRh0w5T086osDMC7-NTDIubM_NAICAmd94J58e7e4DlacnQ5O_8aPqo-8y1XhCXJ7bKufK9vWXJeUhyp8Dm4f-LfTFN8Q9eQgW5P_sLD_ucr1OP8EVC0W7xH78gCq7Z1kene0xcefDyH5kCZXo2Q2i8MQppksgNKZUdIRMiVmsdUmTh57s1PVv3n6CCXunS1FuRFNhQB8kFXOQ17Bb2aIiliI5-qlVllgbsF4HFm2I90O87bbndYIyZs4A2USNStkV96cItj2zcKrvxqeMnYSi1lIPStaYpvlCqr9CjenpCHYLAaULBBwtZEZ2T-CBwvCFk2Sjd2YMHQNkXrcWjTLZZz7tI_jLeY4JZ6V04Xuhlze4pO9I2-vYZR24OF2qUL0Iu-CwyOg0blAFr81nobVJ0WNiN_i4bNd_PjYe_n4eCSTVBPsv20CWePk6IJBC_3iDvEdnDgMaKWuCtPEyokedpNq1yhRo5KMGaYgis0iix0OsY6RFbnAAA7McwW9LXUV6xN7eZhFQTKAewP8rXJBaog3yx6_EIEGoKV8Ag77BYxYMo2xGz2qo2E8AXQPjF1iGkUNfFGl_Ap0h1ldk0_Se4sV4fVJpMe5axO2Vg4FwXKE249OL1fhsSuOPhHkMHhCagRPqjdNGFUcsUBk9or9IUc_O5sp7xH-F1SciiUE1NHRWlbxwaliTfvAhdnev101OOXgoeY6_KjCfWMM2by37q4lNOWSzhFUB0TsWyoRX1su_Yh_y7ZXHKZxYI-9MUrVc_dHKHTP6UTUaUeJvosmTSenYqc1bxvxUHylAeS1skGIDHjSa-Ab6nZcFaNg7HGPN-p40x_N1hqHuJVdQ2YcU5Aqkt2mitIZeg3llYr6PUewjPdu1chsKDglbpP0Bpdg3ZUuRxH5VuhdY0D5FmeUmw6bVlyqHd6gGGPZeNpCk2yBJ4F8k25vdiO2bLFtTXVvc1X0KShJgZChNtctdZn8HXOZOtTAhuL6VRV1VlqJ4bIsCLRF1yZgU_pW-U4fE2kvzpMuaUjYVv0RovYkO0ZX9w5dVdsNPKWbCUhiZHO52eMMinQBldu0IunpCLEhsAr9EkfnbZu0UL6IM_Wzlmd1X-WtICrx8dPvW84ckxkS4NKCfhtyztstCD9VsS0ErNsLBTSfowH1onG4xN4_1BUWVf5GZKWzFdlvvwEAEDx589hN8WzPqtwosw4MXkCdwcYewIVAg0aMpZvn_G6z9wTGUZp1KMP7iqxnyOUSG2T7mkYbxgnmlfDuw0KOUgvbIcNezq_9yd99RfVg1Yg--a6QiCZHtGKnOFEiUIIqN5h0ecaIMTqagnzoZGDDTGvLbC3BhwYyYeLjWgakh-QEVZWrvA1jkM_P89n5TA4gKEbNT_4q7g1xGzTOzF99p4ZO2iyGmS3xgbBpf52B89-QBHzU3iMY_DGZTGejwWo-mqYX-biQciGvAODk_HIyyhYqH08up2M5LgZGgqp-Tj6kaScWhbPIUgWcUrg10PN0lKajyfl4NB1PR9PhDJbyq_HVZT66gq2L5GKEaUCbPmMDN2fPMNh5PDQogG06BxgVcEJUah4jH8gG3cPNS9LYamHVqlQDjmTOYfwN-rzZKQ">