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

    <tr>
        <th>Summary</th>
        <td>
            [clang][enh] Show template instantiation chain for "inline function is not defined" (-Wundefined-inline)
        </td>
    </tr>

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

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

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

<pre>
    When `-Wundefined-inline` is enabled (which is part of `-Wall`), and a function declared `inline` is called but not defined, a warning is issued, which includes the textual location of the call site.  But if that call site is in a template, the warning does not include the template instantiation chain, making it difficult to track down the cause.

In contrast, `-Wunused-variable` does print an instantiation chain if the type of the unused variable is dependent on template arguments.

Example:

```c++
// test.cc
// Demonstrate reporting issue with -Wundefined-inline.

struct HasMethod {
  // Method to call.  Declared 'inline' but has no definition.
  inline static void method();
};

template <typename T>
struct Base {
  void callMethod() {
    // With -Wundefined-inline, we get:
    //
    // warning: inline function 'HasMethod::method' is not defined
    //
 // but without any indication of the instantiation chain, making it
 // hard to track down the root cause.
    T::method();

    // In contrast, with -Wunsed-variable, here we get:
    //
    //   warning: unused variable 'x'
    //
    // and an instantiation chain going back to 'kickOff'.
    T x;
  }
};

template <typename T>
struct Derived : public Base<T> {
  ~Derived()
  {
    // Instantiation of Base::callMethod.
    this->callMethod();
  }
};

void kickOff()
{
  // Implicit call to Derived::~Derived.
 Derived<HasMethod> m;
}

// EOF
```

Output of Clang 16:

```
$ clang++ -c -o /dev/null -Wall test.cc
test.cc:25:7: warning: unused variable 'x' [-Wunused-variable]
    T x;
 ^
test.cc:34:11: note: in instantiation of member function 'Base<HasMethod>::callMethod' requested here
    this->callMethod();
 ^
test.cc:41:22: note: in instantiation of member function 'Derived<HasMethod>::~Derived' requested here
  Derived<HasMethod> m;
 ^
test.cc:6:22: warning: inline function 'HasMethod::method' is not defined [-Wundefined-inline]
  inline static void method();
                     ^
test.cc:18:8: note: used here
 T::method();
       ^
2 warnings generated.
```

Compiler Explorer: https://godbolt.org/z/9zcrETsff

The issue is that the second warning, "inline function not defined", lacks the template instantiation chain.

Motivation: I'm working on a transformation that automatically moves `inline` methods with heavy dependencies into a separate header file, while retaining the `inline` specifier.  With `-Wundefined-inline` (and `-Werror`) I can ensure that a translation unit that uses the method without including the additional header fails.  But lacking template instantiation information makes those errors very difficult to understand in heavily templated code.  (I just spent more than an hour using manual minimization to understand one.)

Workaround: As the example shows, a workaround is to deliberately insert an unused (dependent-typed) variable, since `-Wunused-variable` will then report the instantiation chain.

(I understand that this enhancement may be non-trivial, as the warning is only issued at the end of compilation.)

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysWE9z4joS_zTi0gUFcsBw4EBCqM1hag47VTkLuY31IkteSYZkDvvZt1r-g03Iy3u7O0Uxgyx3__rX_0d4r04GccuWj2y5n4g6FNZtfSkrFG-To80-tq8FGmCr-fS1NhnmymA2VUYrg2w1B-UBjThqzIDx9aVQsqCzSrgANm_eE1qz1ZzxDeNPIEwGAvLayKCsgQylFo7eXs1HUqXQJPRYBzA2QKs5SoCLcEaZE11T3tfNcavbSF1n6CEUCAHfQy00aCtF1GbzeE6ywauAM4DHOoCiYxGu51GyAQEBy0qLgKSA3uw0ZxZ9xNXqa9U1l0EZH4QJqlEqC6EMCSjFW0QdIFN5rmStAwQLwQn5Bpm9mBZc7XHG5ns23zXfLwakNcEJH0hM64vaYzY9C6eIfSItYqqcMgGEuYehsRMhfFTYUdHIgU4OGZ5hhSZDE8Caq03CneoSTfAjaM_voqw0smQ3PCVvx49k_JE-zSk_MH6AgD7MpByd7bG0xgdHihxW1oXGvb5GuKhQwOfgG8HwwdUywD-E_4GhsBmwtFUK0KpoHwQbvTwD2PeRx9M28nga460Q5Nsm5BTRN-tkNffABxGUhLNVGZRRLuNriu-kMzXdX_8dv3seWfJE_BtRIvxiyfPIgEfhcYg9aiC8PwZahhd6817vsxQTA-GEoXfR9aVPQtroZsmus7TPU8bTnl0Slew6w1OKmWGK3tfSqiB-yaO2pij9AGUyNU7O75JnLK8QLruTRM7aMMokwvNrDHzssVsubpKuj8JR1vEnKNDh36AYhiTfJh_j6Tvj6bdCYg29n-InSywdiYxgSeCbkm8_85zxdMgEvPeWA1C0_k9hu0enzpRJyQ6q-qiVjJHMkie6OozXf7dXW_Z7AJ8D-mVknM1bieTAa0IMTAqF8lOWPN9my1-zMyZaT9UV2-c68lJWWknVNotgO-MbaJ19HbD-4dMge56hHFWKYeVslDz_PNxU0uGln3Wo6then7QwJ1isvqq_ndAHkHSzqcYwlTCl2DhkeGb8YGqtIXbpcW3ufiQ7vmTJLiXvfh-8wJaPn9vTcv9F8LHl86225IElu8WCdBgbsKlGN8FucyixPKIbVag26IZU30YMIXT4rxp9wCwm798JoTtoHwgo5_8F2vuxMY6jr-F-G1n3wK56rP-XUt_5-qbnXJ39V_sl3PtzB_9izZLdesh1jMEBL39W42_l8o4FDyc0SNNHl7h38-7JlpXS6OD5vdLWoSMARQiVJ6Uxc082O1odZtadGD_8Zvyw-S3d8y-f50NJv6jPxelG-Wb0pKblUVqT9a6hUY_zW--MhmFOl7SQb_7bAXQ0L_2wQZ3jQzLhhfG0hIt1scPaOPc6YXxuXdlIiBBFHSz9pvT4gNKe0Y-n9oZ03_TKAsX5o58lpUKaqIMFAR4rESe9AkVGOaGaTnoplKbxLwgVZ2yyaCTfVyhVrtDNoJl3vtxKGF9Tj4zP0Tnrmv0DXkAKA2h87bA1qjFVN3bWRoXmvPbtDtEY1c8szbzfwRNZFgdEoXtjhNK-XSvIMfHmfbcocyW4FG9Rn_UIEbCHM7qP8aJAljqSkFGJIYKV_uilZyBtRhsN4-sX-KP2gQgzAUrbGGtoZihs7aD2BKsUhpajUhlVqt-to0daLI3ZfSuM36_WvQlna0OlAXYNR9hsAeALe_HtitbfiyFO07RWx5hjmqY-jy6uKW0XYXzdrx1TGjQyctdwzvLKSPxy97ko6l60qTbrw1eT5GzcbNcvQ3PbRIwrbSGMxDLSJz7giGCsmQanzkroaKEf7YPKgzVkWFxHoU1oJA5zkLFuiGaT6OicZNsk2yQbMcHtYrVZzTerZLWYFNvNKp3L5Xy9SR8WIp9vBC4x36znqRRzeRT5RG35nCfzTTJfpEv-sJhteI7ZMTsmPM0WPJHsYY6lUHqm9bmkUjSJsLardL1eT7Q4ovZx4-e8HQs4Lf9uS_enx_rk2cNcKx_8VUJQQcf_JmjeWO7Z8hFNwZZ7-GdhL39aeiC37l4pu9kbOKcwuLfDbCa109ubSqtCUR9n0paMHwhm-9e0cvYPlIHxQ7TaM36Ihv8nAAD__-N1UwI">