This is the initial fix of https://github.com/llvm/llvm-project/issues/191442. Following the discussion here https://github.com/llvm/llvm-project/issues/115418#issuecomment-2467017012. - Fix #21040 - Fix #52659 - Fix #115418 - Fix #14230 - Fix #21133 ### Description This PR introduces a new AST node, `ExplicitInstantiationDecl`, to systematically fix the long-standing issue of missing or incorrect source location information for explicit template instantiations. #### Background & The Problem Historically, Clang's AST lacked a dedicated node to represent the lexical occurrence of an explicit instantiation statement. Instead, `Sema` tried to shoehorn this information into existing specialization nodes (e.g., `FunctionDecl`, `VarTemplateSpecializationDecl`) or simply returned `nullptr`. This resulted in fragmented behavior across the seven instantiable entity types: * Function & Member Function Templates: Returned `nullptr`, completely losing `SourceRange` and `NestedNameSpecifier` information. * Member Functions & Static Data Members: Mutated existing nodes in-place. Consequently, multiple `template` or `extern template` declarations in the same file would overwrite each other's source locations. * Variable Templates: Suffered from `dyn_cast` bugs and dropped NNS information. #### Design Trade-offs Evaluated Before settling on the current design, I evaluated a mixed redeclaration-chain approach (similar to how explicit *specializations* are handled, creating new `FunctionDecl` nodes and stitching them into the redecl chain). However, this approach had significant flaws: 1. Inconsistency: It couldn't be cleanly applied to member functions or static data members due to `DeclContext` constraints (e.g., a member function shouldn't lexically reside in a namespace `DeclContext`, but placing it in the class context would pollute member lookup). 2. Fragility: It required bypassing standard `FoldingSet` mechanisms (`setFunctionTemplateSpecialization`). 3. Lookup Pollution: Injecting new `NamedDecl` nodes purely for instantiations risked breaking downstream `ASTMatcher`s and altering name lookup behavior. To avoid these pitfalls, this PR introduces `ExplicitInstantiationDecl` as a **purely lexical annotation node**. **Key Design Characteristics:** 1. Inherits from `Decl`, not `NamedDecl`: This is the most crucial design choice. Much like `StaticAssertDecl` or `FriendDecl`, this node lives in a `DeclContext` (making it traversable by `RecursiveASTVisitor` and visible in AST dumps) but remains completely invisible to C++ name lookup. It does not interfere with overload resolution or lookup tables. 2. Unified Representation: A single node type now covers all seven entity types. It holds a pointer (`Specialization`) to the underlying instantiated declaration, unifying how functions, variables, classes, and members are handled. 3. Lexical Fidelity: The node resides in the enclosing namespace or Translation Unit where the explicit instantiation was actually written, perfectly preserving the `SourceRange`, `NestedNameSpecifierLoc`, and the exact locations of the `template` and `extern` keywords. Assisted-by: Claude Code (Anthropic) — used for test writing and checking test results
123 KiB
123 KiB