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

    <tr>
        <th>Summary</th>
        <td>
            DISubprogram has declaration pointing to itself
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            openmp,
            debuginfo
      </td>
    </tr>

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

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

<pre>
    
repro source: 
```c
class Request final {
  public:
    Request(){}
};

class Response final {
  public:
    Response(){}
};

class LoggingAllowedFields {
  public:
    template <typename T>
    static const int loggingFieldsForType();

    template <>
    const int loggingFieldsForType<Request>();

    template <>
    const int loggingFieldsForType<Response>();
};


template <typename PAYLOAD>
int makeLogData(const PAYLOAD& payload) {
  return LoggingAllowedFields::loggingFieldsForType<PAYLOAD>();
}

Response *log(Request* request) {
  makeLogData(*request);
  Response *response = new Response{};
  makeLogData(*response);
  return response;
}
```
run the command:
```
clang-16 -o repro.o -fopenmp -c -g2 -O1 repro.cc
```
stack overflow inside `constructCallSiteEntryDIEs` from asm printer pass when constructing callsite
callee ``LoggingAllowedFields::loggingFieldsForType<Request>()``  
caller `makeLogData<Request>(Request const&)`.

with the follow debug info:
```
!54 = !DISubprogram(name: "loggingFieldsForType<Request>", linkageName: "_ZN20LoggingAllowedFields20loggingFieldsForTypeI7RequestEEKiv", scope: !55, file: ! 1, line: 17, type: !58, scopeLine: 17, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: DISPFlagOptimized, templateParams: !64)
!55 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "LoggingAllowedFields", file: !1, line: 11, size: 8, flags: DIFlagTypePassByValue, elements: ! 56, identifier: "_ZTS20LoggingAllowedFields")
!56 = !{!54, !57}
!57 = distinct !DISubprogram(name: "loggingFieldsForType<Response>", linkageName: "_ZN20LoggingAllowedFields20loggingFieldsForTypeI8ResponseEEKiv", scope: ! 55, file: !1, line: 20, type: !58, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, templateParams: !62, declaration: !57, retainedNodes: !61)
``` 
Notice that `DISubprogram` `loggingFieldsForType<Response>`'s `declaration` field points to itself, which leads to infinite call stack.

The self-reference `DISubprogram` exists in the unoptimized IRs straight from clang codegen, so it is reproducible with the following cmd as well,
```
clang-16 -o repro.ll -fopenmp -g2 -O1 repro.cc -Xclang -disable-llvm-passes -emit-llvm -S
```

In order to reproduce, I need all of `-fopenmp`, `-O1`( or use a `-O` level >= 1) and `-g2`:
  * `-fopenmp` affects which declarations go into `CodeGenModule::DeferredDeclsToEmit` and their orders. The source has nothing to do with openmp, but this flag is applied universally in our internal code repo. As explained below, I think certain order of the declarations causes the issue.
  * `-O` level seems to affect debug info verbosity. If I give `-O0`, less debug info is generated and the issue is gone.
  * `-g2` implies `-debug-info-kind=constructor`. If I give `-debug-info-kind=limited`, the issue is gone.


Below is what I've found so far after digging into clang codegen. 
When `-fopenmp` is given, the order of function codegen is
1. codegen function `log(Request*)`: create temporary `DICompositeType` for `Response` and store in `TypeCache`. It has `DIFlagFwdDecl` flag.
        
2. codegen function `int makeLogData<Request>(Request const&)`: the type definition of `loggingFieldsForType` is created. This in turn creates a `DISubprogram` for `loggingFieldsForType<Response>()`, and uses the type created in previous step for its `templateParams` field. The type is stored in the `DISubprograms` hashmap using the `templateParams` as part of key.

3. codegen function for the constructor `Response::Response()`: because of ctor homing, it creates the complete type for `Response` and replaces the previously created temporary node with a distinct `DICompositeType` node.

4. codegen function `int makeLogData<Response>(Response const&)`
        1. searching the `TypeCache` for type `Response` now returns the distinct node.
        2. searching the `DISubprograms` hashmap for `loggingFieldsForType<Response>()` does not return anything because the key value has been updated.
        3. A new `DISubprogram` for `loggingFieldsForType<Response>()` is created.

If `-fopenmp` is not given, the order of function codegen changes, now #3 `Response::Response()`, the constructor is generated before #2, so that in #4, the search will hit in the hashmap.


I am not sure if openmp is to blame here, it looks to me that it exposes an issue in debug info generation when ctor homing is used. 

cc: @dwblaikie @ayermolo 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1WF1z4jgW_TXkRQUFJpDwwAMdkilqe7q7Jqmd3Xnpkm0ZtLEtryUny_z6PfdKNjYhM-mt2SoqwbJ0P88994rYpMf1aLodTTe1qmojrGnqRI3mG-FXR8up_yT-OcmlteIX9e9GWScyXcpcjG4--ZdCVE2c6wTH2wXR7h1Ft6NoRVtvtkE0vszDyaFwW5nSqg9K95s_Lv6z2e91ud_kuXlV6YNWeWr_RIlTRZVLp8RofueOlSplocTTaH5_2mKddDoRCWxxQpdO5F6Nl_9g6iecC0YOrTpXMBD7J_Lmd210cej_ITwE9630N8H1fy9G6tvmn5-_bradbtJYyGeFTGylkxDtLWn3RUtRyWNuZAqV_dTUyjV1eTGDlK_55h0_ega8daNnfYe8UUSisLkD7wbKw9eBSUM_sO-0rdNyQqngDe33-VaU6vUEYQ_e-R_JbsHeFx6i0r1861xbw6HQm1K4g0L6i0KWaYf0s22olnI_ni3F2AjmhokR48wgp0UlxokY7yMx_joL75LkohCURfIszIuqMyQLWLM6heegE8p43STuTub5o3bqvnT1cbu7t3gpstoUQtpCVDXAomrgAZX7elCl6A4izyLBYYvDwWI8KZaOzw-D5E0lsRgherJrkt3PytmplhbZRsDYS5n0Ifaq3YGjnxmyTKQqbvaIS2bey8Momi2uGSz4tt09NjHiva9lAYVUXszVUfQBr6JRdCdyXT7LvfpyOvn9ty_RxXBF00tCdzdB5v393_RLkGoTUwV5s8WCVjKdtwtiFhTzwuyGntzxtP-2k_B5sCfL5Z5yJra7B3z9xsSM4rtrF2rjDAlKe4uPTMQ_qyJWNcutHk5iHr_Rw9fK6UL_rlI2JDDWN4mQ2mDS8ppS14V_weFPtQXoEufzcGeKyhD2ArE7uWcdv35_2vz0nVvNd3YSOnppughLH8NexIYB4ycLg-np9kJkyIRvUPjp-HeZN6xS5apQpWsdEoslraL4SqczjdC0uX96vJx8NqoXg2ULQaIpgiTJoy83J56hpwuh-mHI9rrOX4TZ21boe6AVb1A7yEE0vQjac4R2gPzfkceWpQoAqgFkU7b6uCJA9RIWpV9MqroTs1OeWuYIpPXFoBQU6EY6Yq5BJmjT8mKwzlIAgdGNpc19q4ik6ZCoDBjaCmeEdlblGZn5etDJQeRKpv5FiUkOlcJ0LbglDDjxCXRIR8e1ylStykRdslb9B6CyEMb02ZSmjaXY_WIhtZZ6f3C-dXDvAg2naq9KzgWZJ7T13SptEh3nSpyRMXeUIkXjEa8qz3Hug40RXp0641lbFON_eGvGKAoJreM8fynG1NCUFWNVaMcrYvx4mf75764Upk7RgJzpXOA632GEQAgosCajsLWGcN7ueOXrjB9uIUI0GDykX6Wg5upFYcRGmlG1BCSBiYBf7yM6dJqCaQQaihcyy1TibEh3Dx1W7CnrsBXb7pCFn1T5M0zm2sJnS3muVbrFEftk7hEDlgfVyIauva92IhgZfCMRB2SlNO5ASYLg1PjsBWvgadw4nEaKqSgp1bKqco3YNKXG_GERoiOhB-IEDxV0uSCIUEDNRGwsIIaCpPoSsQIefHxJ5bNIVE2lF7KAUBNsBi4nsqGM0rq2tlGT88j1Am6VKrg0fAh7U4CAqTH1leNE7DKo38N4f3waUporzEK9E3AVKFewg4DgY-hN4FemfGsKJ1foggLEpT1meWOSN37WNBRuu0HL1DTEnFnzdn-OaoQFwcj3bOj__aR4JiQAgaB2oJkXKsUGLqBeM1kjPDT8pZpJyiNqUNqTQHS_0mR4hk7SC2vL1pouc1mDzoSUtUKw00uZTbqlbo_nyMFNIMyGYN-kVnTXISI3tayPnraGkwERpeHBsSPVAHWLyCpCJBZo651MDsqH2jHcWRq1jYdXLhWWhcculIH2o8t2n1-zPjSsklsULepiABkTN8nz5HKxXfhY-1ikVLPaszRdSvyq9ZRzzughLh--fHpkUei6SmMzg2pSWtXqRZuG-oGqWAG6Eik5a7Zt-_IUw1K09RlJ2xZzZjEfQloOhaxgAPOQ3_VWNpJXydpR1J7VcQD9-YVkkZ3-RtaV3AAwTJpnv3T4VMWKaYcU8amDKWAYj3quC3647FW5csHXdxAJIsxlEk60oQRrtgE-Ab0k3mQClr1h7yL6aesgAtcfh2sfAd0d-gywbS2geq2SdXLoZaZfVj7K5P2Z5yVIyN-hveOdPwPLV9EF-e_i48ehjY6muMO193lZHn23a3NMOoEm8UIzPhNErBDDpkq58DpDgbAN_7Dwl5Rcv7YHE8n5tEEbyfwPkm5yAI9jiKXrERIwiubzj2A-yO1XyqD_xSojVoW4KMx9PP0Sy0bz6_a4TyQAjLHpoF1b8SF7F1rVTsiCvbMNcXYW5g7SjZ4U5_Qz1wGza6i83JhnflOE6RtrGC4M0ZYs28ZY9rt4cIFC5H_nOJUzaQEA0rbbhTE04QvA9TR9hX79rBU9yKOqC5MbcaXWs-Vytbyd405xla7n6Wq-kldOu1yt-7BgJPUmGT_RhzHLz_RXTZ2vD85V_AtK9IDPHrXfxBPQCh5ofg3_xpD6L4w0eGQvkeCHxSq6nl0d1vNrGWcLdbuKV8lUXS9Xt8hWPE_UzVzGSRJf5RJzl12PFrhhRu1kF_mLZsSx4h9KsLTYXul1NI1wTYtW0-kiuo4m06lazWarRTyVs-WNWiEaqpA6n5BdE1Pvr-o1mwg5Fi9zuk-cXmIg13sM06we8mXjDqZey4rvBq9X7M6affkvyhJVhA">