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

    <tr>
        <th>Summary</th>
        <td>
            [clang-cl] Self instantiation does not work in a constant expression
        </td>
    </tr>

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

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

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

<pre>
    Consider the following example:
```
template <int I = 0>
struct S {
        static constexpr int A = I;
        static constexpr int B = S<>::A;
};
static_assert(S<1>::B == 0, "S<1>::B should be 0");
```

Latest MSVC (14.41) is able to compile this:
```
C:\test>cl.exe /c example.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.41.34120 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

example.cpp
```

However clang-cl fails to compile:
```
C:\test>clang-cl.exe example.cpp
C:\test\example.cpp(4,30): error: implicit instantiation of
          template 'S<>' within its own definition
        4 |     static constexpr int B = S<>::A;
          | ^
C:\test\example.cpp(4,26): error: constexpr variable 'B' must
         be initialized by a constant expression
        4 |     static constexpr int B = S<>::A;
          |                          ^
          | = 0
2 errors generated.
```

Here is a *draft* patch that I tried to make while working at #47033. It __does not__ work - it removes the errors, but the assert fails. Maybe it will help.
```
Parent: 520ddf22b2270dc092dbdbd391b1c02c403b475a ([TableGen] Remove duplicate code in applyMnemonicAliases when target uses DefaultAsmParserVariant. (#108494))

------------------------- clang/lib/Sema/SemaDecl.cpp -------------------------
index 3c6a0dff798f..6a12ed82894d 100644
@@ -352,7 +352,26 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
       return nullptr;
     }
 
-    if (!LookupCtx->isDependentContext() &&
+    CXXRecordDecl *DeclFromScope = nullptr, *DeclFromScopeSpec = nullptr;
+    if (S->getLookupEntity())
+ DeclFromScope = dyn_cast_or_null<CXXRecordDecl>(S->getLookupEntity());
+
+    if (SS->isValid()) {
+           auto ClassTemplateSpecDecl = 
+        dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+                SS->getScopeRep()->getAsRecordDecl());
+         if (ClassTemplateSpecDecl && 
+                 ClassTemplateSpecDecl->getSpecializedTemplate()) {
+ DeclFromScopeSpec = ClassTemplateSpecDecl->
+                getSpecializedTemplate()->getTemplatedDecl();
+         }
+ }
+       
+    if (getLangOpts().MSVCCompat && DeclFromScope && 
+                DeclFromScope == DeclFromScopeSpec) {
+      LookupCtx = nullptr;
+               SS = nullptr;
+    } else if (!LookupCtx->isDependentContext() &&
 RequireCompleteDeclContext(*SS, LookupCtx))
       return nullptr;
   }

------------------------ clang/lib/Sema/SemaLookup.cpp ------------------------
index d3d4bf27ae72..de7b7fbba9b3 100644
@@ -2695,6 +2695,25 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
 ObjectType->castAs<TagType>()->isBeingDefined()) &&
 "Caller should have completed object type");
   } else if (SS && SS->isNotEmpty()) {
+    CXXRecordDecl *DeclFromScope = nullptr, *DeclFromScopeSpec = nullptr;
+    if (S->getLookupEntity())
+ DeclFromScope = dyn_cast_or_null<CXXRecordDecl>(S->getLookupEntity());
+
+    if (SS->isValid()) {
+           auto ClassTemplateSpecDecl = 
+        dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+                SS->getScopeRep()->getAsRecordDecl());
+         if (ClassTemplateSpecDecl && 
+                 ClassTemplateSpecDecl->getSpecializedTemplate()) {
+ DeclFromScopeSpec = ClassTemplateSpecDecl->
+                getSpecializedTemplate()->getTemplatedDecl();
+         }
+ }
+       
+    if (getLangOpts().MSVCCompat && DeclFromScope && 
+                DeclFromScope == DeclFromScopeSpec)
+      return LookupName(R, S, AllowBuiltinCreation);
+        
     // This nested-name-specifier occurs after another nested-name-specifier,
     // so long into the context associated with the prior nested-name-specifier.
     if ((DC = computeDeclContext(*SS, EnteringContext))) {
```

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWMtu4zrSfhpmU4ghUbJlLbyw5eT_A3SfPogbjd4FlFS2OU2TGpLK5Tz9oEj5ktjuPpiZxSzaCGKZZN0-flVFSjgnNxpxxsYLNl7eiN5vjZ19U6KVO2lX22YrN0bh801t2rdZZbSTLVrwW4S1Ucq8SL0BfBW7TiHL5ixZsmTOJsnwF3563HVKeASWVVJ7eACWLSFh2V2cd972jYcVsGIxKEhK54WXDTRGO4-vnQWSnAfJB5b9Yt0irFuxrCIj2Zxl8_lRqFgenqP0k3AOrWd8SiLpQSaoib7yChjnH6fd1vSqhRppBWe8PBp5D0H8_0l4dB4-r76Rtmmaj_KU8RKkA1ErBG-gMbtO0uNWumt4VjQxrkgXy-4aNcJXBMbvm_1GjJqui0s_y8YaZ9ae7D2SrYrx-4rxBeML-NJ5uZN_0RZW0a6Fb2idNBrScpSnoyxPeQJrY-F1kg_WTfdm5WYbVFak8mikMrYzVnhp9AhgrhSElQ4sOrTP2I5O4Tjz9iJo_29e8BktNErozW2jYC2kcidY_V2YongA68zy6dpxdTrNpznjVZaEzZ0DWmssPchdp2QjPUjtvNBehqjBrA_MBDgSnxd7MvICXqTfSg3SOzAvGlpcSy1J-iCaAysqoM-_QW-yTOJsfPf3guOTj8EdzT0LKwM3GS8W5Pyud_5oqEYIvgsl_8IW6jcQUVhoD6QAnfuvB3b1c4j4iEFI3jDGY3gONqjRCn8k40XWocWQl8D4vLVi7RmfQyd8swW_FVTEvJXYEg934gfCy5bS9sXYH5ROgrIjy4sky0bw4OHpqTXoQBv_9BQWwS1IDxZ35hldKKfROyo0de_DSKxKke8j-CzeCG0PL1Ip2KLqLvv_p7CoPe3imCdtu-a85rxI2iYpeVu3dZuVaZ02CW_yJKvzYkwhTtl48ZX2-f9Qs_ESHoNj0PZEcmJwY1raahBdp94-a9wZLZu5ksKhg5ctavDCbtBDTwNLXIte-bnb_SmsQ_uNWKT9KFjiWZpM8zIn0vHyFPTba5-Y_IzfK1kzfr_CnRi-ltgoojJclY2qpW7xFbJmIpJ2vS7K6Xo0moiUYzvl0zJvIU2SST6UOJYnLE_gNhtzxqsCGF_ERz6BYS7E1X596xCCN4GrG_Q08ofYIePTQG14aFF7uZZoH_TaAOOThwfa5JXpbYOfTBPrBsl8Mg3jVXRhYLRF31sNuleq8_aQCpHtxXL4NaBHg3IdMU4_GfOj7yr_esuyO-mW2KEmVyqjPb76sKgkd-gvRs0XpKH6_v0RG2NbgpbYT9_31uxWjekwZNTendAU38-vOmzerTlkb9Qe_VuRUxv00ck77aV_ix4dGcEXcG65fdNPjXD-ydgnssCy6p2_ocL-Qv2JR5dcW0XAvgkl24PQydGELyCUFwDRewOVEs59HQo9RR9hy5bwfv0lzz-KhjIa-HCM5Z0WUrTaRxdQecQuOjkMzt0JGJdChuh9DPaK84EU8A6cwfjlcPcO7UPAdr_iCoCXKXNV9xkGPzM2OLMfPEXiHIZDDgXlJz-CoTNyEKeE3nzpvIsqR3SWo7NTKPgBtg-kPcNyCOGM24TAGS5nyIXPIbevZlo0slr9LBVZsQRUDv-TmgGP-M9eWiQIFHqkAE5Xz1crqhIHxacZ_ssSd9yPn3aH680hmv1pezjtDm3W5vWaFwILPhq1WNTFuq5FWWcXuwOflGPGqwm1h-GZj_f9oTZGnXSG6ElsGkN7iEOP6HoVuPMYusJAmnmArfr-_SRDBjAHeL7U_8AmtBvaLKosc8ey6qvY0NhQO2I2SLdAqTdLOmfiaU073UjGeSUU3QCGS81WPGM4YtO-tmCCPfCk_P1V55xKxLvI-301_cP4u113UoXPWP277fxuO7_bzv9O2_nQcoYqHak9VLBYsejfXCnzsuil8lJXFgOXziIf7mgnB1h-z_g9fN1KBxqdx_ZWix3eOsKYTsxgmqa3DsTaowWhjd-ivbz0_cF50OwMKKM3dLU04UbVxNZENyvTSNqmcBkPc52V5ory0YnqfbOcLuPtkipkf7Xx3WmPVurNYao84-X729tNO8vaMivFDc7Sgk_GRVqOxzfbGWI9XidllgnMmjoTaVkkNRdNWU-busj4jZzxhOdJmRZpmpbpeDTFNMlrMS1EMi3LOmN5gjsh1Uip593I2M2NdK7HWZpMywm_UaJG5cKLQM41vkCYpVo_Xt7YGQnd1v3GsTxR0nl3VOOlV-EN4v4dC90gV6jWH96N7K_A8QJMl8lL7wpueqtmW--78P4rbORG-m1fjxqzoy6vnvdft5011JUYvw_OOsbvh2ieZ_xfAQAA__-kwg_g">