[clang] [clang-tools-extra] [Clang][AST] Introduce `ExplicitInstantiationDecl` to preserve source info and fix diagnostic locations (PR #191658)

via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 13 07:17:29 PDT 2026


================
@@ -9314,10 +9314,36 @@ static void StripImplicitInstantiation(NamedDecl *D, bool MinGW) {
     FD->setInlineSpecified(false);
 }
 
+/// Create an ExplicitInstantiationDecl to record source-location info for an
+/// explicit template instantiation statement, and add it to \p CurContext.
+static void addExplicitInstantiationDecl(
+    ASTContext &Context, DeclContext *CurContext, const CXXScopeSpec &SS,
+    NamedDecl *Spec, SourceLocation ExternLoc, SourceLocation TemplateLoc,
+    SourceLocation TagKWLoc, const ASTTemplateArgumentListInfo *ArgsAsWritten,
+    SourceLocation NameLoc, TypeSourceInfo *TypeAsWritten,
+    TemplateSpecializationKind TSK) {
+  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
+  auto *EID = ExplicitInstantiationDecl::Create(
+      Context, CurContext, Spec, ExternLoc, TemplateLoc, TagKWLoc, QualifierLoc,
+      ArgsAsWritten, NameLoc, TypeAsWritten, TSK);
+  CurContext->addDecl(EID);
+}
+
 /// Compute the diagnostic location for an explicit instantiation
 //  declaration or definition.
 static SourceLocation DiagLocForExplicitInstantiation(
     NamedDecl* D, SourceLocation PointOfInstantiation) {
+  // Search for an ExplicitInstantiationDecl that references D. Per
+  // [temp.explicit], explicit instantiations must appear in an enclosing
+  // namespace of the template, so the EID is in D's DeclContext or an ancestor.
+  for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent()) {
+    for (auto *Decl : DC->decls()) {
+      if (auto *EID = dyn_cast<ExplicitInstantiationDecl>(Decl))
+        if (EID->getSpecialization() == D)
+          return EID->getTemplateLoc();
+    }
+  }
----------------
16bit-ykiko wrote:

In my experience, it should be similar to `StaticAssert`. Not storing them in the PCM has no real impact, as it doesn't actually affect how the language server functions. There are two main use cases: the first is "find references," which queries the index. Since indexing is based on the AST, this is fine—as long as the declaration is traversed during indexing, it can be found. The second use case is highlighting for open files, which also involves building an AST. In other words, we don't need to traverse the declarations in a PCH/PCM to implement any specific functionality.

The only exception is `CodeAction`; there might be some `CodeAction` in the future that requires this kind of access, though there probably isn't one right now. So, adding the reference probably wouldn't hurt, and it's worth considering. But what about the other AST nodes in the GMF that are optimized away? Are there any potential issues with that?

https://github.com/llvm/llvm-project/pull/191658


More information about the cfe-commits mailing list