We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
Analyze & explore related research in Conceptio
Connect this record directly into your research workflow or AI agent. Explore citations across open repositories, query full text, and export structured proof bundles.
arXiv:2608.03734v1 [cs.SE] 4 Aug 2026
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments Kexin Sun
Yunbo Lyu∗
Xutong Ma
kexinsun@smail.nju.edu.cn State Key Lab for Novel Software Technology, Nanjing University Nanjing, China
yunbolyu@smu.edu.sg Singapore Management University Singapore
xutong.ma@inria.fr Inria Paris, France
Hongyu Kuang∗
Ratnadira Widyasari
He Zhang
khy@nju.edu.cn State Key Lab for Novel Software Technology, Nanjing University Nanjing, China
ratnadiraw@smu.edu.sg Singapore Management University Singapore
hezhang@nju.edu.cn State Key Lab for Novel Software Technology, Nanjing University Nanjing, China
Xiaoxing Ma
Julia Lawall
David Lo
xxm@nju.edu.cn State Key Lab for Novel Software Technology, Nanjing University Nanjing, China
julia.lawall@inria.fr Inria Paris, France
davidlo@smu.edu.sg Singapore Management University Singapore
Abstract
Keywords
As the Linux kernel evolves, code comments may become outdated, as the functions they reference can be refactored or removed independently without corresponding updates to the comments. Such stale function references can mislead maintainers and thus hinder code comprehension. Prior work on detecting code-comment inconsistency mainly focused on addressing semantic misalignment between Javadoc comments and their directly annotated functions, making them inapplicable to this type of externally induced staleness in the Linux kernel. Therefore, we propose ReCite, a threestage approach to identify and repair such stale references: (1) detecting unresolved function-form symbols—symbols in comments that appear to reference functions but for which no matching function can be found in the current codebase, (2) tracing the evolution history of each unresolved symbol through the Git history, and (3) generating LLM-based repair suggestions grounded in the evolution history and current code context. On Linux kernel v6.18-rc1, ReCite detects 869 stale references with generated repair suggestions. A manual evaluation on 200 sampled repairs shows that 178 (89.0%) provide useful repair guidance, with 85 (42.5%) directly applicable. Of our 75 submitted patches, 50 have been accepted. We also empirically study all unresolved function-form symbols.
code comments, stale references, software maintenance, Linux kernel, code evolution, large language models
CCS Concepts • Software and its engineering → Software evolution; Software maintenance tools; Maintaining software. ∗ Hongyu Kuang and Yunbo Lyu are the corresponding authors.
This work is licensed under a Creative Commons Attribution 4.0 International License. ASE ’26, Munich, Germany © 2026 Copyright held by the owner/author(s). ACM ISBN 979-8-4007-2882-2/2026/10 https://doi.org/10.1145/3832783.3837474
ACM Reference Format: Kexin Sun, Yunbo Lyu, Xutong Ma, Hongyu Kuang, Ratnadira Widyasari, He Zhang, Xiaoxing Ma, Julia Lawall, and David Lo. 2026. We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments. In Proceedings of the 41st IEEE/ACM International Conference on Automated Software Engineering (ASE ’26), October 12–16, 2026, Munich, Germany. ACM, New York, NY, USA, 13 pages. https://doi.org/10. 1145/3832783.3837474
1
Introduction & Motivation
In modern iterative development, code undergoes frequent refactoring as part of routine maintenance [5, 9, 34]. The Linux kernel, which is one of the world’s most actively maintained codebases, typically ships every two to three months with each cycle absorbing about 13,000 changesets [42]. Such changes, however, do not always extend to the comments: existing automated refactoring approaches are primarily proposed for syntactic code elements, instead of unstructured comment texts, making comments easily outdated during code evolution [31]. The lack of update to relevant comments has also been substantiated by a large-scale empirical study [44]. Within these outdated comments, a particularly harmful case is the stale function reference, where the comment of a given function typically mentions another function that has been refactored or removed and thus no longer exists in the current codebase. Such references matter because they capture repository-level knowledge from the original developers that links code entities across the codebase. Once stale, they reduce comment usefulness and increase the maintenance burden as the codebase evolves [8, 36]. Prior studies [7, 32] have recognized the code comment inconsistency (CCI) issue, but they generally focus on local inconsistencies between a function and its directly associated comment, typically
ASE ’26, October 12–16, 2026, Munich, Germany
Figure 1: Prior CCI work vs. our focus. Prior work detects broad local semantic misalignment (left). We target stale function references caused by external evolution (right).
Figure 2: A motivating example of a stale function reference to hw_perf_group_sched_in() and its repair. Javadoc-style function-comment pairs in Java [26] (Figure 1, left). In contrast, we target a different type of inconsistency that we observe in Linux kernel comments: externally induced stale function references, where a comment becomes outdated because the function it mentions has been refactored or removed independently elsewhere (Figure 1, right). Such inconsistencies are overlooked by approaches that focus only on local inconsistencies. These stale references can affect more than comment readability. Figure 2 shows a case where a comment describing a conditional exit refers to hw_perf_group_sched_in(), a function that no longer exists in the current codebase. To repair this unresolved reference, we traced back to commit e7bef6b (January 2010), where the comment was originally written, and found that hw_perf_group_sched_in() was defined at line 992 of the same file. We then tracked the function’s subsequent evolution and found that it was completely removed in commit a13c3af (April 2010). This removal not only rendered the comment stale, but also left the conditional branch “if (!n_ev) return 0;” as unreachable dead code. Such dead code unnecessarily inflates the codebase that maintainers and security auditors must reason about—a well-recognized concern in software debloating and kernel attack-surface reduction [10, 28]. We have submitted a patch that removes both the outdated comment and the dead code. This case illustrates that stale function references are not merely a documentation problem—they can signal latent logical defects that may otherwise go unnoticed. Linux kernel developers have also noticed such stale references in practice. For example, commit b7dd80f removed two references to the deleted scan_swap_map_slots() from comments. Nevertheless, such fixes remain isolated and manual, and the kernel still lacks a systematic approach to (i) scan the codebase for stale function references, (ii) trace when and why a reference became unresolved (i.e., no matching function can be found for the symbol in the codebase), and (iii) generate history-grounded repairs at scale.
Sun et al.
To bridge this gap, we propose ReCite, a three-stage approach for automatically identifying and repairing stale function references in Linux kernel comments: (1) Given a kernel snapshot, ReCite first extracts function-form symbols (i.e., symbols written as “foo()” that appear to reference a function or a function-like macro) from all comment blocks. It then checks whether they are resolvable (i.e. the matching function can be found) in the current codebase, using grep combined with Coccinelle [25], a semantic patching framework for C code. (2) For each unresolved symbol, ReCite traces back to the commit where the reference was introduced and identifies the function actually intended by the comment via large language model (LLM)-based entity selection, since static analysis alone cannot disambiguate among same-name candidates. It then tracks the function’s evolution forward—through renames, splits, and removals—to construct an evolution tree. (3) Finally, ReCite prompts an LLM with the evolution tree and relevant context to generate a history-grounded repair suggestion. We evaluate ReCite on Linux kernel v6.18-rc1, where it detects 869 stale references and automatically generates corresponding repair suggestions. A manual evaluation on 200 sampled generated repairs shows that 178 (89.0%) provide useful repair guidance, including 85 (42.5%) directly applicable repairs and 93 (46.5%) partially acceptable ones that need minor manual refinement before direct application. We therefore position ReCite as a decision-support tool that provides helpful repair candidates for maintainers, rather than a fully automatic repair system, at present. We have submitted 75 patches to the Linux kernel; 50 have been accepted. Specifically, a maintainer who received our patch remarked: “We must have missed this comment ... a few years ago.” We further did an empirical study on all detected unresolved function-form symbols (5,442 in total) from 8,258 mentions, i.e., occurrences in comments, and established a five-category taxonomy of their underlying causes.
2
Related Work
Code Comment Inconsistency. Early work relies on rule-based approaches to detect code-comment inconsistency [31, 36–38], while subsequent work shifts towards learning-based methods [17, 29, 46] For example, Panthaplackel et al. [26] use a GNN-based encoder with attention to jointly represent code edits and comments, predicting whether a change invalidates the associated comment at commit time. Other learning-based approaches include CoCC [7], which uses skip-gram embeddings and random-forest classifiers for binary judgments, and CARL-CCI [23], which applies label-aware contrastive learning on structured code diffs. More recently, the task has expanded from detection to automated repair [14, 18, 27], as demonstrated by Rong et al. [32], who fine-tune CodeLLaMA (C4RLLaMA) to both detect and repair inconsistencies. Compared to prior CCI work, we target a long-overlooked problem: a comment may reference a function in a distant file that evolves independently, leaving the comment stale. Existing CCI approaches, developed mostly for Java documentation comments, target local function-summary inconsistencies and thus miss cross-file references (60.5% of our cases; Section 5.2.1). Our C4RLLaMA evaluation further indicates poor transfer to this setting (Section 5.4). Code–Documentation Inconsistency Across Software Artifacts. Beyond source-code comments, inconsistencies between
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
ASE ’26, October 12–16, 2026, Munich, Germany
Figure 3: Overview of ReCite for identifying and repairing stale function references in Linux kernel comments. evolving code and its accompanying documentation are pervasive across software artifacts. Prior work has studied outdated code names or samples in API documentation [12, 13, 47], stale code references in README files [39, 40] and outdated code snippets on Q&A posts [30]. With the growing capability of large language models, recent work has also begun applying LLMs to detect and repair such inconsistencies. For example, METAMON [11], DocPrism [45], and Gao et al. [6] use LLM-based reasoning to detect broader forms of code–documentation inconsistency across code behavior, documentation text, and README updates. These efforts share our concern for code–documentation inconsistency, but they target different scenarios. Tang et al. [41] target outdated screenshots, while Lee et al. [12, 13] and Tan et al. [39, 40] target outdated API references in project documentation rather than in-code comments, with documentation-specific designs. Beyond this artifact gap, most of these works (e.g. [11, 47]) reason over a single code snapshot or a single commit diff, and can thus only establish whether an inconsistency exists. Our approach traces full evolution histories to determine not only whether a reference is stale, but also why it became stale and how to repair it. FreshDoc is closest in using revision history for API documentation, but its Java-AST-based change analysis [4] cannot handle C constructs such as Linux kernel #ifdef directives. We therefore adopt RefDiff [33] as a baseline for evaluating ReCite’s LLM-based evolution reasoning.
3
Proposed Approach
Inspired by the manual repair process, we propose ReCite, a threestage approach (Figure 3) for automatically identifying and repairing stale function references in Linux kernel comments. First, we scan the codebase to extract all function-form symbols from comments, and determine which of them are unresolved in the current codebase (Section 3.1). We then trace the evolutionary history of each unresolved symbol to understand why it became invalid (Section 3.2). Finally, we leverage an LLM to generate repair suggestions based on the function’s evolutionary history (Section 3.3).
3.1
Identifying Unresolved Function-Form Symbols
We analyzed Linux kernel v6.18-rc1 (HEAD=3a86608). From around 62,000 source files (.c and .h), we extracted 2.27 million code comments, and identified function-form symbols as tokens matching the regular expression “[A-Za-z_][A-Za-z0-9_]*()”. This yields 49,302
unique symbols across 61,866 comments, totaling 83,241 mentions. Here, a symbol refers to a unique function-form string, while a mention refers to one occurrence of such a symbol in a comment, as one symbol can appear in multiple comments. We then design a two-step validation pipeline to determine whether a given symbol has at least one matching function-level code entity (i.e., can be “resolved”) at a specific snapshot. Step 1: Coarse-Grained Search. For each symbol, we use grep to obtain candidate source files that mention it. We then filter out matches that occur exclusively within comment regions or string literals, ensuring the matched identifier appears in code proper. Step 2: Fine-Grained Static Analysis. For symbols with candidate files, we further apply static analysis to check whether a matching function definition, declaration, or function-like macro definition exists. We include function declarations as valid evidence of existence, because some functions are implemented in assembly and only declared in C header files. Ignoring declarations would over-approximate the unresolved symbols. We adopt Coccinelle [25] for this check. Coccinelle is a code matching and patching engine based on the Semantic Patch Language (SmPL), which was originally developed to support collateral evolution in the Linux kernel. We write an SmPL rule that matches function definitions of the form “name(...){...}”, “type name(...);” and “#define name(...) ...”. We denote this two-step pipeline as Resolve(sym, commit), which returns the set of files that contain the matching function-level code entity for sym in version commit. When restricted to a single file, we write Exists(sym, file, commit) to denote whether sym can be resolved within a specific file. If no matching entity is found in any candidate file, the symbol is considered unresolved at the queried version. We treat the unresolved symbols in snapshot v6.18-rc1 as the starting point for the subsequent repair pipeline.
3.2
Tracing Function Evolution History
To understand why a function-form symbol is unresolvable in the current snapshot, we trace its evolutionary history. We model the historical state of a code entity as a tuple ⟨sym, file, commit⟩, where sym is the function-form symbol, file is the source file path, and commit is the Git commit hash. The goal of this stage is to first construct the initial state ⟨sym0, file0, commit0 ⟩ by locating the code entity that the comment originally referred to (Section 3.2.1), and then trace its evolution forward along the Git history (Section 3.2.2).
ASE ’26, October 12–16, 2026, Munich, Germany
3.2.1 Locating the Referenced Code Entity. We first return to the commit where the symbol was originally introduced into the comment (i.e., the symbol-introducing commit), and verify whether it was resolved at that point. For the symbols that are already unresolvable at that time, we manually categorize the underlying reasons in Section 6.1. For the resolvable symbols, we further identify which specific code entity the comment refers to. 1) Identify the symbol-introducing commit: Since files may be renamed over time, we first trace the rename history of the commented file. We then collect commits whose patches involve the referenced symbol under each historical file path. Starting from the earliest such commit, we check whether any comment-region line in the file at that version has a Jaccard similarity ≥ 0.7 with the symbol-bearing line in the current comment. We use Jaccard similarity rather than exact matching because comments are frequently extended or lightly edited. The 0.7 threshold tolerates minor wording changes while reliably identifying the original introduction. The earliest commit satisfying this criterion is taken as the symbol-introducing commit commit0 . 2) Collecting Candidate Code Entities: We collect all candidate files containing a matching function entity at the symbolintroducing commit by invoking Resolve(sym, commit0 ). 3) Selecting the Comment-Referenced Code Entity with the LLM: The static analysis alone cannot determine which candidate code entity the comment actually refers to [22]. The Linux kernel supports multiple architectures, and the same function name may have several architecture-specific implementations simultaneously (e.g., under x86 and ARM). Moreover, some function-form symbols do not refer to any function at all—for instance, “decrypt()” in the comment “an optional alternate error code that is acceptable for decrypt() to return” refers generically to a decryption operation rather than a specific implementation. Therefore, we leverage the LLM to identify which candidate the comment refers to. We supply the LLM with the target symbol, the comment text at the symbol-introducing commit, the comment-related code context, and the set of candidate entities. The code context is extracted via Tree-sitter [2] from the enclosing or nearest function. Candidates are ordered by path edit distance to the comment’s file. Each candidate is represented by its identifier line together with the three preceding lines, as function signatures may span multiple lines and visibility qualifiers such as “static” may appear on a preceding line. The LLM is instructed to return any one of: • the file containing the comment-referenced code entity, • NO_MATCHED_DEFINITION if no suitable candidate is found, • NOT_A_FUNCTION if the symbol does not refer to a function. For functions whose implementations fall outside our *.c/*.h scope (e.g., assembly implementations), the LLM is instructed to select the declaration file closest in path to the comment’s file. To guard against hallucination, we verify whether the returned file path appears in the original candidate list. If not, we retry up to two times, each time providing the LLM with its previous erroneous output as feedback, as prior work [16] has shown that LLM performance improves in early feedback rounds and quickly stabilizes thereafter. If the response remains invalid after all retries, the case is marked as “Tracing Inconclusive” and excluded from further tracing. The complete prompt is available in our replication package.
Sun et al.
Algorithm 1 Tracking the Evolution of a Referenced Entity Input: sym: target symbol; file0 : definition file at commit0 ; commit0 : symbol-introducing commit; depth: current depth Output: Evolution tree with leaf status (“Permanently Removed”, “Aligned with HEAD”, or “Depth Limit Reached”) 1: function trace(sym, file, commit, depth) 2: if depth ≥ 5 then 3: mark Depth Limit Reached; return 4: commit𝑟𝑚 ← findRemovalCommit ( sym, file, commit ) 5: rdiff ← filterDiff ( gitShow ( commit𝑟𝑚 ), sym ) 6: result ← validateWithRetry ( llmAnalyze ( sym, rdiff ), commit𝑟𝑚 ) 7: recordHistory ( commit𝑟𝑚 , result ) 8: if result.type = removed then 9: mark Permanently Removed; return 10: else if result.type = refactored then 11: for 𝑠 ∈ result.successors do 12: if Exists (𝑠.sym, 𝑠.file, HEAD ) then 13: mark Aligned with HEAD; return 14: else 15: trace(𝑠.sym, 𝑠.file, commit𝑟𝑚 , depth + 1) 16: trace(sym, file0 , commit0 , 0)
After entity selection, a symbol that is confirmed to refer to a specific code entity that existed in the past—but no longer exists in the current snapshot—is regarded as a stale function reference. This yields the initial state ⟨sym0, file0, commit0 ⟩, from which we trace the code entity’s subsequent evolution. 3.2.2 Tracking the Evolution of the Referenced Entity. Starting from the initial state ⟨sym0, file0, commit0 ⟩, we iteratively trace the code entity’s evolution forward along the Git history (outlined in Algorithm 1). At each step, we locate the commit that causes the entity to disappear from its file, and pass the commit message and diff to an LLM to determine whether the entity was refactored (i.e., its functionality was taken over by one or more successor entities) or removed (i.e., its functionality was eliminated entirely). If removed, the trace terminates. Otherwise, we check whether the successor entity still exists in the current snapshot (i.e., at HEAD); if so, the evolution has reached the present and the trace terminates (marked “Aligned with HEAD” in Algorithm 1). If not, we apply the same procedure recursively to the successor, up to a maximum depth of five iterations to guard against overly long or drifting traces. We detail the core steps of the iteration below. 1) Locating the Function-Removing Commit. commit𝑟𝑚 𝑖 is used to represent the function-removing commit for state ⟨sym𝑖 , file𝑖 , commit𝑖 ⟩, i.e. the first commit after commit𝑖 at which sym𝑖 is no longer present in file𝑖 , regardless of whether it was deleted, renamed, or moved elsewhere. To locate commit𝑟𝑚 𝑖 , we chronologically traverse the modification history of sym𝑖 on file𝑖 , i.e., all commits from commit𝑖 to HEAD that modified file𝑖 involving sym𝑖 . The earliest commit c at which ¬Exists(sym𝑖 , file𝑖 , 𝑐) is designated as commit𝑟𝑚 𝑖 . If no such commit is found (e.g., Coccinelle misidentifies the symbol as unresolved while the function still exists, leaving no removal to locate), the case also ends in “Tracing Inconclusive”. 2) LLM-Based Change Analysis. We provide commit𝑟𝑚 𝑖 —its title, message, and code diff—to the LLM to determine whether sym𝑖 was removed or refactored. In the refactored case, the LLM additionally reports the successor symbols and the corresponding containing files. The LLM can also return None, indicating that sym𝑖 was not actually removed at this commit (e.g., Coccinelle incorrectly identified the removing commit). In this case, we distrust the Coccinelle-based localization and fall back to an LLM-based
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
Figure 4: Evolution trees of two code entities. Green marks surviving successors; shaded marks those absent at HEAD. change analysis: we sequentially feed each commit in the modification history to the LLM, adopting the first non-None response as the true removing commit and its change-analysis result. If no valid removing commit can be identified, the case ends in “Tracing Inconclusive”. When interacting with the LLM, we first provide the complete diff; if the full prompt exceeds the token limit, we retain only hunks from files whose token sets shared at least one subtoken of sym𝑖 (split on “_”), as renames in the Linux kernel typically preserve one or more sub-tokens of the original name. 3) Validation and Retry. We validate each reported successor in two steps: (1) file existence check: we verify via git that the reported file exists at commit𝑟𝑚 𝑖 ; (2) entity membership check: we verify Exists(𝑠.sym, 𝑠.file, commit𝑟𝑚 𝑖 ). Accumulated error messages are fed back to the LLM, which is allowed up to two retries. If validation still fails, this case ends in “Tracing Inconclusive”. If the change is classified as removed, the branch terminates—the function was permanently deleted at this commit. If classified as refactored, we check each validated successor s against the current snapshot via Exists. If s exists, this branch has reached the present, and tracing stops. Otherwise, s itself was removed in a later commit, so we update the state to ⟨sym𝑖+1, file𝑖+1, commit𝑖+1 ⟩ = ⟨𝑠.sym, 𝑠.file, commit𝑖rm ⟩ and continue tracing. When a function is split into multiple successors, each successor is traced independently. We organize the evolutionary history of a code entity into a tree structure. Figure 4 illustrates two examples. The function ttm_tt_unbind was first renamed to ttm_bo_tt_unbind and later removed entirely, leaving no surviving successor. In contrast, ieee80211 _start_scan was split into two functions: __ieee80211_start_scan, which inherited the core scanning logic and still exists today, and ieee80211_request_internal_scan, which was further renamed to ieee80211_request_ibss_scan.
3.3
Generating Repair Suggestions with LLM
To repair stale references in comments, we generate suggestions based on the evolution history of the referenced code entities. Each stale reference is treated individually. The prompt is organized into four input sections followed by a chain-of-thought analysis request. (The full prompt details are included in our release package.) The structured input consists of: 1) Target Comment Context, which includes the current comment, its file location, the specific stale reference, and the surrounding code context in the current version, i.e., the environment into which the repaired comment needs to fit; 2) Origin Context, which includes the description of
ASE ’26, October 12–16, 2026, Munich, Germany
the symbol-introducing commit, together with the comment’s code context and the original function’s source at that time, allowing the LLM to contrast the original and current versions and judge whether the comment’s intent still holds; 3) Evolutionary History, which includes the full evolution tree of the referenced function (in a format similar to Figure 4), followed by detailed change logs, including each function-removing commit’s title and message and a pruned diff restricted to the disappeared entity or its successors; 4) Evolution Outcomes, where we present the current code of surviving successors in the evolution tree, so the LLM can assess whether they are suitable replacements for the stale reference. We then instruct the LLM to reason as follows before answering: 1) Evolution Analysis: trace the evolution path of the missing function—whether it was simply renamed, had its logic split, or was entirely removed—and identify which surviving function, if any, carries the semantic equivalent of the original reference. 2) Comment Context & Semantic Analysis: examine the current code context surrounding the comment and assess whether the comment’s original intent remains valid given the code changes. 3) Repair Strategy: propose a concrete fix by updating the function name, rephrasing the comment when needed, or entirely removing it if it has become obsolete, ensuring the repaired comment fits the current code context. Finally, the LLM produces the repaired comment based on the above analysis. For example, for the comment “See the link below and ieee80211_start_scan() for more.”, ReCite recommends replacing the stale reference with its core-logic successor __ieee80211_start _scan (Figure 4). This repair has been accepted into the Linux kernel.
4
Experimental Setup
We evaluated ReCite on Linux kernel v6.18-rc1 for automatically identifying and repairing stale function references in kernel comments. From this snapshot, we extracted 49,302 unique functionform symbols across 61,866 comments, totaling 83,241 mentions. Using grep with Coccinelle, ReCite flags 8,258 function-form mentions (5,442 unique symbols across 7,111 comments) as unresolved in the current snapshot. Among them, we found 7,177/8,258 (86.9%) mentions were already unresolvable when the symbol was first introduced into the comment; we provide a manual categorization of their underlying reasons in Section 6.1 (only 17.3% of these are genuinely missing functions). For the remaining 1,081/8,258 (13.1%) resolvable mentions, for which at least one same-name candidate can serve as a traceable starting point, ReCite proceeds to construct the evolution history: it first locates a valid referenced code entity for 999 of them (the other 82 lack a valid entity), then successfully traces and repairs 869 of these (the remaining 130 end in Tracing Inconclusive). These 869 cases therefore constitute ReCite’s positive predictions for repair-worthy stale function references. Our manual analysis shows that the majority of these 130 cases are upstream Coccinelle false positives that in fact need no repair (see Section 5.2); accordingly, ReCite does not treat them as repair-worthy stale references and does not present repair suggestions to the user. The 82 cases without a valid comment-referenced code entity are effectively unresolvable at introduction (the staticanalysis candidates are only same-name objects); their underlying
ASE ’26, October 12–16, 2026, Munich, Germany
Sun et al.
4.2
Figure 5: Attrition flow of ReCite’s stale-function-reference detection and repair pipeline.
reasons can also be understood through the taxonomy established in Section 6.1. We summarize the above attrition flow in Figure 5. Throughout all LLM-based steps, we used DeepSeek-V3.2 [15] as a cost-efficient model with temperature set to 0 to reduce output randomness. To assess both ReCite’s component-level performance (RQ1–RQ3) and its end-to-end performance (RQ4), we posed following research questions: • RQ1: How accurately can ReCite detect unresolved functionform symbols? • RQ2: How accurately does ReCite trace the function-evolution history? • RQ3: How effectively can ReCite repair the identified stale function references? • RQ4: How accurately does ReCite identify repair-worthy stale function references end to end?
4.1
RQ1: Detection of Unresolved Symbols
As described in Section 3.1, ReCite uses a two-step process to determine whether a symbol is resolved at a given version: a coarsegrained search with grep followed by fine-grained static analysis with Coccinelle. To evaluate the accuracy of this pipeline, we replaced Coccinelle with three other widely used static analysis tools: Tree-sitter [2] (a concrete syntax tree parser), Universal Ctags [43] (a syntax-based symbol indexer), and GNU Global [35] (a project-wide cross-reference tool). Each was configured to check whether a matching function definition, declaration, or functionlike macro definition exists. We also evaluated using grep alone without any fine-grained analysis. We denote the five resulting configurations as Resolve-Coccinelle (grep + Coccinelle, our default), Resolve-TreeSitter (grep + Tree-sitter), Resolve-Ctags (grep + Universal Ctags), Resolve-GNUGlobal (grep + GNU Global), and Resolve-OnlyGrep (grep only, without any fine-grained static analysis). We ran all five configurations on the 49,302 unique functionform symbols extracted from HEAD. Among the 49,302 symbols, 3,796 received conflicting resolution results across the five configurations. To establish ground truth, we randomly sampled 200 of these disagreement cases for manual annotation, forming the Symbol Resolution 200 dataset. Two annotators—both senior undergraduate students majoring in software engineering—independently labeled each symbol as resolved or unresolved at HEAD, by inspecting the source code at the target commit. They first annotated a pilot batch of 20 symbols to calibrate their criteria, achieving a Cohen’s 𝜅 of 0.89. After resolving disagreements through discussion with the first author, the remaining symbols were split evenly between the two annotators. In the final ground truth, 110 symbols were labeled as resolved and 90 as unresolved. We evaluated all five Resolve variants on this dataset and report precision (𝑃), recall (𝑅), F1-score (𝐹 1), and accuracy (𝐴𝑐𝑐).
RQ2: Accuracy of Evolution Tracing
For the 1,081 mentions resolvable at their symbol-introducing commit, ReCite constructs the evolution history for repair. We evaluate this stage through two sub-tasks: (1) comment-reference entity selection—whether ReCite correctly identifies the referenced code entity; and (2) refactoring analysis—whether ReCite correctly determines how the entity was changed at function-removing commits. Comment-Reference Entity Selection. We randomly sampled 200 cases from the 1,081 resolvable mentions to form the Entity Selection 200 dataset. Two annotators independently labeled each case, determining: (a) whether the symbol refers to a concrete function entity, and if so, (b) which file contains the referenced entity at commit0 . The annotator selected one of: a file path (the entity is found), NOT_A_FUNCTION (the symbol does not refer to a function), or NO_MATCHED_DEFINITION (no suitable candidate is found). The annotators first labeled a pilot batch of 20 cases. At the binary level (entity exists vs. not), they achieved a Cohen’s 𝜅 of 0.62 (substantial agreement). Among the 16 cases where both identified a valid entity, they agreed on the exact file path in all cases (100%). After resolving disagreements through discussion with the first author, the remaining cases were split evenly between the two annotators. In the final ground truth, 173 symbols were labeled as having a valid code entity, while 27 were not (14 NO_MATCHED_DEFINITION, 13 NOT_A_FUNCTION). We also evaluated ReCite on two levels. First, we assessed entity detection: whether ReCite correctly determines that a symbol has a valid code entity. We mapped the output to a binary label: 𝑦=1 if ReCite returns a file path; 𝑦=0 if it returns NOT_A_FUNCTION or NO_MATCHED_DEFINITION. We then report 𝑃, 𝑅, and 𝐹 1. Second, we assessed entity localization: among the cases where both ReCite and the ground truth agree that a valid entity exists (𝑦=1), we computed the accuracy of the returned file path, i.e., the proportion of cases where ReCite’s file path matches the annotator’s file path. Refactoring Analysis. Applying entity selection to 1,081 resolvable mentions, ReCite located a valid referenced code entity for 999 of them. To evaluate how accurately ReCite traces their evolution, we use RefDiff [33], a static-analysis-based refactoring detection tool, as a baseline. Using ReCite, we successfully constructed evolution trees for 869 of 999 candidate mentions, containing a total of 916 unique function-removing commits. The remaining 130 cases ended in Tracing Inconclusive, analyzed in Section 5.2. Using RefDiff, we constructed evolution trees for 903 cases, containing 837 function-removing commits. The two approaches shared 785 removing commits where they analyzed the same code entity ⟨sym, file⟩ at the same commit, of which 282 yielded different results. We randomly sampled 200 cases from these divergent cases to form the Refactoring Analysis 200 dataset. For each case—a code entity ⟨sym, file⟩ at a specific function-removing commit—the annotator determined whether the entity was removed (deleted without a successor) or refactored. If refactored, the annotator identified each successor as a refactoring route: ⟨sym𝐴 , file𝐴 ⟩ → ⟨sym𝐵 , file𝐵 ⟩, where ⟨sym𝐴 , file𝐴 ⟩ is the entity before the commit and ⟨sym𝐵 , file𝐵 ⟩ is its successor after the commit. A single entity may yield multiple refactoring routes when the function is split into several successors.
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
Two annotators independently labeled a pilot batch of 20 cases. They agreed on 19 (95%) cases for the binary judgment, with nearly all labeled as refactored. We computed pairwise agreement by treating one annotator’s routes as predictions against the other’s, yielding 𝐹 1=0.80. After resolving disagreements through discussion with the first author, they independently labeled the remaining cases. In the final ground truth, 191 cases are labeled as refactored, 7 as removed, and 2 as Coccinelle false positive—the function still exists at the supposed removing commit and was not actually changed. We evaluated both ReCite and RefDiff on this dataset at two levels: (1) binary classification—whether a function-removing commit is correctly classified as refactored or removed, with refactored as the positive class, measured by 𝑃, 𝑅, and 𝐹 1 (the Coccinelle false positive is excluded, leaving 198 valid cases); and (2) successor identification—among commits where both the tool and the ground truth agree on refactored, whether the tool identifies the correct successor(s), measured by 𝑃, 𝑅, and 𝐹 1 at the refactoring-route level.
4.3
RQ3: Effectiveness of Repair
We manually evaluated the quality of LLM-generated comment repairs. The first author reviewed an initial set of 30 cases to establish the following four-category rubric: • Acceptable: the repair appropriately identifies the successor or handles the removal, and can be directly applied. • Partial: the repair makes partially correct changes but is not directly applicable, e.g., leaving residual outdated descriptions. • Incorrect: the suggested repair is entirely wrong and offers no reference value. • Off-Target: the case falls outside the scope of our repair task, e.g., the symbol does not refer to a function. We then randomly sampled an additional 200 cases to form the Repair Quality 200 dataset. Two annotators (the same for the Symbol Resolution 200 dataset) independently labeled a pilot batch of 20 cases, achieving a Cohen’s 𝜅 of 0.72. After resolving disagreements through discussion with the first author, the remaining cases were divided between two annotators. Ablation Study. Additionally, we include two ablation studies to assess the necessity of LLM-based repair and evolution history. For the LLM-based repair ablation, we construct a rule-based repair baseline that, instead of an LLM, applies simple rules over the evolution tree: if the evolution tree contains a surviving successor, the baseline replaces the stale function mention with the successor whose name has the smallest edit distance to the original; otherwise, it removes the enclosing sentence. For the evolution-history ablation, we implement a no-history ReCite variant by removing the evolution-history input from the repair stage, leaving the LLM only with the original and current comment context. Comparing ReCite against these two variants isolates the contribution of LLM-based repair and evolution-history context.
4.4
ASE ’26, October 12–16, 2026, Munich, Germany
Table 1: (RQ1) Performance of five Resolve variants on the Symbol Resolution 200 dataset. Resolved is the positive class. Variant
𝑃
𝑅
𝐹1
𝐴𝑐𝑐
Resolve-Coccinelle Resolve-TreeSitter Resolve-Ctags Resolve-GNUGlobal Resolve-OnlyGrep
96.7% 95.4% 50.0% 75.4% 55.0%
79.1% 56.4% 53.6% 41.8% 100.0%
0.870 0.709 0.518 0.538 0.710
87.0% 74.5% 45.0% 60.5% 55.0%
Table 2: (RQ2) Performance on Entity Selection 200 dataset. Task
Metric
Entity detection
TP = 173, FP = 13, FN = 0, TN = 14 𝑃 = 93.0% 𝑅 = 100.0% 𝐹 1 = 0.964
File path match
On 173 TP cases, 𝐴𝑐𝑐 = 98.3%
via disproportionate stratified sampling: 200 predicted-positive cases reused from the Repair Quality 200, and 200 predicted-negative cases randomly sampled from the remaining 82,372 unflagged mentions. Manual annotation of the predicted-positive sample, as reported in RQ3, confirms 178 true positives and 22 false positives. We further annotate the 200 predicted-negative cases (the two annotators agreed on all 20 pilot cases), and find only 2 genuinely stale function references that require repair. As the closest applicable baseline, we include C4RLLaMA [32], a learning-based comment– code inconsistency detector. We reproduce it under its original setting and adapt it to our task by taking its inconsistent verdict as a positive flag. We report the performance of ReCite and C4RLLaMA on the predicted-positive (𝑛=200), the predicted-negative (𝑛=200), and the full balanced (𝑛=400) samples, using 𝑃, 𝑅, 𝐹 1, and 𝐴𝑐𝑐.
5 Results 5.1 RQ1: Detection of Unresolved Symbols Table 1 reports the performance of five Resolve variants on the Symbol Resolution 200 dataset. Resolve-Coccinelle achieves the highest 𝐹 1 (0.870) and accuracy (87.0%) among all variants. We find that Coccinelle can recognize common Linux-kernel macro forms that match its predefined patterns (e.g., BPF_CALL). For example, for BPF_CALL_2(bpf_redirect, ...), only Resolve-Coccinelle and Resolve-OnlyGrep (by string matching) classify bpf_redirect as resolved, while the other three tools all classify it as unresolved. However, it remains limited in handling macro-generated function definitions, whose definitions are syntactically hidden inside C preprocessor macros, which accounts for its comparatively lower recall (𝑅=79.1%). For instance, PAGE_TYPE_OPS(Buddy, ...) constructs the function named PageBuddy through token pasting (##), making it unrecognizable as a function definition at the source level (grep survives as the name appears elsewhere). Because our SmPL rules operate on unexpanded source text, such patterns cannot be matched by the current analysis. This is a deliberate trade-off in our tool configuration, which we discuss further in Section 7.
RQ4: End-to-End Detection.
Of the 83,241 function-form mentions in v6.18-rc1, ReCite flags 869 (1.0%) as repair-worthy stale function references and leaves the remaining 82,372 (99.0%) unflagged. To assess this end-to-end detection, we construct the Repair-Worthy Detection 400 dataset
5.2
RQ2: Accuracy of Evolution Tracing
5.2.1 Comment-Reference Entity Selection. As shown in Table 2, ReCite achieves an 𝐹 1 of 0.964 on entity detection. The 13 false positives indicate that some symbols without a valid code entity may
ASE ’26, October 12–16, 2026, Munich, Germany
Sun et al.
Table 3: (RQ2) Performance on the Refactoring Analysis 200 dataset. Binary classification: refactored is the positive class (𝑛=198, 2 Coccinelle false positives excluded). Successor identification: 𝑛 = cases where tool and human agree on refactored. Task
Tool
𝑛
𝑃
𝑅
𝐹1
Binary classification
ReCite RefDiff
198 198
0.974 0.951
0.974 0.304
0.974 0.460
Successor identification
ReCite RefDiff
186 58
0.736 0.672
0.905 0.506
0.812 0.577
enter the subsequent tracing and repair steps, but this conservative strategy ensures perfect recall (𝑅=100%, FN =0), so no symbol that genuinely requires repair is missed. Among the 173 true-positive cases, ReCite returns the correct file path in 170 (98.3%). These results indicate that our comment-reference entity selection provides a reliable starting point for evolution tracing and repair. We additionally analyze the relative positions between the referenced entities and the comments that mention them. Among the 173 annotated true-positive cases, 55.5% involve a cross-file reference, i.e., the entity definition resides in a different file from the comment. A similar proportion can be observed at larger scale: of the 999 valid entities ReCite identifies from all 1,081 resolvable mentions, 60.5% are cross-file references. These findings indicate that cross-file entity references are prevalent in Linux kernel comments, and the simple local-context analysis is insufficient to address them, validating ReCite’s LLM-based cross-file entity resolution. 5.2.2 Refactoring Analysis. As shown in Table 3, ReCite substantially outperforms RefDiff in both distinguishing whether a function was refactored or removed (𝐹 1: 0.974 vs. 0.460) and identifying correct successors (𝐹 1: 0.812 vs. 0.577). ReCite can benefit from the semantic information in commit messages [20]. For example, commit 5e7a5c8 is titled “fold dentry_kill() into dput()”. ReCite correctly identifies dput() as the successor—an Inline Function refactoring where dentry_kill()’s logic is absorbed into an existing, larger function—while RefDiff only classifies this case as removed. We find that ReCite shows a relatively lower precision on successor identification (𝑃=0.736), as it sometimes reports semantically paired functions as successors, e.g., for the renamed set_settings(), it returns the getter get_link_ksettings() alongside the true successor set_link_ksettings(). Regarding false negatives, it occasionally misses semantically distant successors: for vmtruncate(), it identifies the core successor truncate_pagecache() but misses inode_newsize_ok(), an auxiliary validation helper extracted from it. Nevertheless, ReCite’s high recall (𝑅=0.905) is valuable for downstream repair, ensuring potential successors are not missed. Across all 869 successfully constructed evolution trees, ReCite identifies a total of 1,136 function-removing commits, averaging 1.31 per tree. The deepest trees reach depth 6. For example, the function ctl_clear_bit() undergoes 5 rounds of refactoring, but one of its leaf nodes system_ctl_set_clear_bit() is absent from the current codebase after reaching the iteration limit, so this case is marked as Tracing Inconclusive. However, its other leaf node system_ctl_clear_bit() is present in the current codebase and can serve as a valid repair target. Another case, estimation_timer(), illustrates the breadth of a single evolution: in commit 705dd344, it
is refactored into 6 successors—1 for top-level execution loop, 2 for core estimation logic, and 3 for lifecycle management. These cases highlight the complexity of kernel code evolution, motivating the need for automated tracing support. Of the 869 trees, 335 (38.6%) end with no surviving successor. The remaining 534 (61.4%) retain at least one successor in the current codebase, providing concrete targets for repairing the stale comment. We also analyze the 130 out of 999 cases (13.0%) marked as Tracing Inconclusive, where the evolution tree construction does not reach a definitive conclusion. One of them is the ctl_clear_bit() case described above. 87 of these (67%) arise because no removing commit is found during the traversal of the modification history. We sample ten such cases and confirm that the function still exists at HEAD, meaning the upstream Coccinelle check incorrectly flagged it as unresolved at the current version, so no repair is actually needed. The remaining 42 cases (32%) fail during successor validation after all retries. We manually inspect ten of these and find that seven are caused by an incorrectly located removing commit leading the LLM to analyze the wrong diff. The other three cases represent corner cases not yet covered, such as a non-function successor (e.g., a function replaced by a struct that cannot pass the functionlevel existence check). Overall, “Tracing Inconclusive” filters cases requiring no repair or affected by localization errors, leaving 869 reliable evolution trees for repair.
5.3
RQ3: Effectiveness of Repair
Among 200 annotated ReCite’s repair suggestions, 85 (42.5%) are labeled Acceptable (directly applicable), 93 (46.5%) Partial (providing useful reference for manual repair), 0 (0.0%) Incorrect, and 22 (11.0%) Off-Target (outside our repair scope). We further analyze the sub-patterns within each category. Acceptable (85). 1) Proper Name Substitution (71/85): ReCite locates a suitable successor, and directly substituting the function name suffices to fix the stale reference. 2) Proper Wording Revision (11/85): ReCite goes beyond simple name replacement and also updates other outdated descriptions in the comment. For example, the comment “it will be used as xxx_of_node on soc_bind_dai_link()” references a function, whose successor is snd_soc_add_pcm_runtime(). Since snd_soc_add _pcm_runtime() no longer directly holds the xxx_of_node structure but uses it for component matching, ReCite revises the comment to “xxx_of_node for component matching in snd_soc_add_pcm _runtime()” to better reflect this change. 3) Proper Sentence Deletion (3/85): ReCite correctly suggests deleting the clause that mentions a removed function, such as irda_connect() in “Copied and modified irda_connect()”. We also find that ReCite exhibits a degree of tolerance for intermediate errors. For example, the evolution tree for swiotlb_unmap _page() traces an incorrect path, yet the LLM bypasses it and identifies the correct replacement xen_swiotlb_unmap_page() from the current code context, still producing an Acceptable repair. Partial (93). Complex code evolution can also cause ReCite’s repair to be incomplete, in two ways. First, ReCite may correctly identify a successor but leave residual outdated wording in the repaired comment (34 cases). Second, when no single successor can fully
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
assume the original function’s role, ReCite instead replaces the stale name with a natural-language description (59 cases). We find that the repairs proposing a concrete successor are more readily accepted and easier to verify; natural-language replacements, while less likely to become outdated, lose the direct code-navigation value that a concrete function name offers—we thus tend to label such repairs as Partial. Among the 59 natural-language-description cases, 39 are labeled as having a more precise alternative available, while the remaining 20 need a more focused description. 1) More Wording Revision Needed (34/93): ReCite correctly identifies the successor, but the repair still contains residual outdated or inaccurate descriptions. For instance, amdgpu_fence_driver _init_ring has the comment “Helper function for amdgpu_fence _driver_init()”, ReCite correctly traces the rename to amdgpu_fence _driver_sw_init() and substitutes the name. However, the body of amdgpu_fence_driver_sw_init() now consists solely of return 0—the helper relationship no longer holds, and the comment should be removed rather than merely updated. 2) More Precise Alternative Available (39/93): Annotators identify a more precise alternative for these cases—33 have a suitable function name available in the codebase, and 6 warrant deletion. For example, pump_transfers() was split into three sub-functions during an SPI core migration, none of which alone preserves the original semantics. ReCite substitutes “Concurrent handling of the same transfer completion leads to problems”, but annotators find that spi_finalize_current_transfer()—the function that now handles transfer completion in the new architecture and already appears in the collected repair context—is a more precise replacement. 3) Too Broad Description (20/93): No suitable function name exists, so using the natural-language description is an appropriate choice, but the resulting description is too broad or verbose, requiring manual adjustment. Off-Target (22): 1) Changelog Comment (9/22): Nine cases appear in changelogstyle comments (e.g., “1999/11. . . Made nbd_end_request() use the io_request_lock”), which record historical changes rather than describe current code and thus do not require repair. 2) Detection False Positive (7/22): Seven are detection-stage false positives where the function still exists. ReCite correctly recommends no change in five of these. 3) Non-Function Entity (6/22): These cases reference non-function entities (e.g., driver callbacks), which are also noted by ReCite. In our 200-case RQ3 evaluation, ReCite generally produces useful repair suggestions. Off-Target cases (22/200, 11.0%) are often identifiable through explicit signals such as change-log formatting or ReCite’s own diagnostics. Among the 178 actionable cases, nearly half (85, 47.8%) are directly acceptable, while the remaining (93, 52.2%) are partially acceptable; they still provide helpful guidance for manual repair. We find that whether the repair proposes a concrete successor is generally a useful indicator of its readiness for direct application. Across the 200 annotated cases, ReCite proposes a concrete successor in 121 repairs. Of these, 82 (67.8%) are directly acceptable (the first two Acceptable subcategories), 34 (28.1%) are Partial (the first Partial subcategory), and 5 (4.1%) are Off-Target. Regardless of the final label, a concrete successor gives maintainers a clear starting point for evaluating and refining the
ASE ’26, October 12–16, 2026, Munich, Germany
Table 4: Outcomes of the 75 submitted Linux kernel patches. Patch Source
Accepted
Responded
Pending
Rejected
Total
Verbatim ReCite patches Human-refined ReCite patches Manual patches
15 16 19
1 2 0
7 10 5
0 0 0
23 28 24
Total
50
3
22
0
75
Table 5: (RQ4) Performance on the Repair-Worthy Detection 400 dataset. ReCite
C4RLLaMA
Sample
𝑃
𝑅
𝐹1
𝐴𝑐𝑐
𝑃
𝑅
𝐹1
𝐴𝑐𝑐
ReCite-Positive (𝑛=200) 89.0% 100.0% 0.942 89.0% 90.4% 84.3% 0.872 78.0% ReCite-Negative (𝑛=200) – 0.0% – 99.0% 1.2% 100.0% 0.023 16.5% Balanced Full (𝑛=400) 89.0% 98.9% 0.937 94.0% 45.4% 84.4% 0.590 47.2%
repair. Combined with 24 manual patches, we have submitted 75 repair patches to the Linux community in total. Their current status is summarized in Table 4. Of these, 50 have been accepted (i.e., queued in maintainer trees or merged into mainline), 3 have received maintainer responses, including 2 with Acked/Reviewed-by but are not yet in any tree, 1 case (_decode_session6(), discussed later) is superseded by an alternative refactoring chosen by the developer, and the remainder are still under review. No patch was rejected for reporting a false issue. To avoid burdening the community, we manually refine ReCite-based patches before submission when needed, typically by simplifying wording or correcting outdated descriptions that ReCite missed. Among the 31 accepted ReCite-based patches, 15 (48.4%) are verbatim ReCite patches that required no manual revision. Together with the 42.5% Acceptable rate in our manual evaluation, we frame ReCite as a maintainer decision-support tool that produces useful repair candidates, rather than a fully automatic repair system at present. We also received strong positive feedback from a senior Linux kernel maintainer: “Impressive use of AI and impeccably correctly tagged, this is exactly how I want AI-assisted submissions to look.” Ablation Results. Finally, we compare ReCite with the rulebased repair baseline and its no-history variant. The rule-based baseline reproduces ReCite’s repair in only 260 of 869 cases (29.9%), and even on the simplest pure-name-substitution cases, it identifies the correct successor in just 44 of 71 cases (62.0%). The no-history variant is similarly limited: it matches our original repairs in only 110 of 869 cases (12.6%), and 9 of 71 (12.7%) on the same pure-namesubstitution subset. These results show that, in our setting, both LLM-based reasoning and explicit evolution history substantially improve repair over simple rule-based and no-history variants.
5.4
RQ4: End-to-End Detection.
Table 5 reports the end-to-end results. Although ReCite misses two genuinely repair-worthy stale references, it still achieves good end-to-end performance on the balanced full sample (𝐹 1=0.937, 𝐴𝑐𝑐=94.0%). Both missed cases were already unresolvable at introduction and thus never entered the tracing and repair steps, i.e., the True Missing Function category analyzed in Section 6.1. By contrast, C4RLLaMA marks 335/400 (83.8%) cases as inconsistent and performs poorly on the balanced sample (𝐹 1=0.590, 𝐴𝑐𝑐=47.2%),
ASE ’26, October 12–16, 2026, Munich, Germany
suggesting that general CCI methods does not transfer reliably to our setting and may over-flag Linux kernel comments.
6 Discussion 6.1 Categorization of Unresolvable Mentions For the 7,177 (86.9%) mentions that were already unresolvable when the symbol was first written into the comment, we conducted a manual categorization to understand their underlying reasons. The first author first performed open coding on 30 randomly sampled cases, establishing the five categories listed below. We then sampled an additional 400 cases to form the Exist Reason 400 dataset. Three other annotators (also undergraduate students majoring in software engineering) began with a 20-case pilot, achieving a Fleiss’ 𝜅 of 0.72. After resolving disagreements with the first author, they completed the remaining 380 annotations. All 400 annotated cases fell within the five categories, with no additional category emerging. (1) Non-kernel Entity (43/400, 10.8%): the symbol refers to an entity not defined in the kernel source, such as a compiler builtin, a C library function, or a function from an external project. For example, the comment “CONFIG_UBSAN_TRAP inserts a UD2 when it sees __builtin_unreachable()” refers to a GCC compiler built-in, not a kernel function. (2) Kernel Concept, Not a Function (153/400, 38.3%): the symbol refers to a kernel entity but does not refer to a function. For example, in comments, “invalid_vma()” may denote a functionpointer field rather than a standalone function, and “kexec()” can be used as a verb meaning “perform a kexec operation”. (3) Abbreviation/Wildcard (113/400, 28.3%): the symbol refers to one or more real kernel functions, but the comment uses an abbreviation or suffix pattern that does not exactly match any function name. For example, the comment “completion is now handled in the regular_isr()” refers to the function wmt_mci_regular_isr() in the same file, but resolving the abbreviated name regular_isr alone yields no match. (4) True Missing Function (69/400, 17.3%): the symbol refers to a specific kernel function that genuinely does not exist at the queried version. We further sub-categorize these cases: (a) Typo (33/69): the symbol is a misspelling of an existing function, e.g., “cmpxcgh()” for the actual function cmpxchg(). (b) Already Obsolete at Introduction (32/68): the referenced function had already been removed or renamed before the comment was written. For example, the function plug_ctx_cmp() was refactored into plug_rq_cmp() in 2018, but a comment created in 2021 still referenced the obsolete name—likely due to copy-paste from an earlier source. (c) Explicitly Declared Absence (4/69): the comment itself makes clear that the referenced function does not exist, e.g., in a TODO note. (5) Tool False Positive (22/400, 5.5%): the function exists at the queried version but was missed by our tool.
6.2
Challenges and Insights
As discussed above, both identifying and repairing stale function references are considerably more complex than initially anticipated. We summarize the key challenges and insights below.
Sun et al.
Challenges in identification. The difficulty of identifying repair-worthy stale references stems from two sources: the diversity of natural language in comments, and the complexity of the code itself. On the language side, developers frequently use functionform symbols to refer to entities that are not kernel-managed functions—compiler built-ins, C library routines (Cat. 1), struct fields, or verbs (Cat. 2). These do not require function-level repair. Beyond non-targets, natural language may also complicate what a symbol actually refers to. Developers may use abbreviations or wildcard-style names (Cat. 3), which turn a one-to-one symbolto-entity mapping into a one-to-many relationship. And the abbreviation could also become stale. For instance, pci_dma_sync() is a shorthand for a family of PCI DMA synchronization functions (e.g. pci_dma_sync_{single_for_cpu, sg_for_device}(), etc.), all of which were removed in commit 7968778 and replaced by the unified dma_sync_* API. Moreover, typos and omitted parentheses (e.g., writing foo instead of foo()) could further increase ambiguity and cause references to escape our extraction. On the code side, even when a matching function definition exists, the specific reference may still be stale. For instance, if a comment in an ARM source file mentions platform_cpu_die() but the only matching definition is found under a different architecture (i.e., arch/blackfin/), the reference is still outdated since it clearly does not intend to point there. Such cases (NO_MATCHED_DEFINITION in our entity selection) are effectively a form of Already Obsolete at Introduction, requiring architecture-aware reasoning to disambiguate. Given these complexities, we do not claim to have mapped all stale function references in the Linux kernel. Our approach— anchoring on “symbol()”-form tokens—provides a practical starting point, and we focus repair efforts on the subset where a source entity can be located at the symbol-introducing commit. Challenges in repair. Tracing a stale reference back to its source entity is a prerequisite for history-grounded repair, yet this cannot always be achieved. The Linux kernel has been under development since 1991, but it only adopted Git in 2005, leaving pre-Git history difficult to access [19]. Moreover, comment authors do not always reference valid entities at the time of writing (e.g., through copy-paste from older code). Combined with non-kernel and non-function references (Cat. 1–3), 7,177 of 8,258 mentions (86.9%) are already unresolvable at introduction. In this work, we focus on the 1,081 resolvable mentions, where a source entity can be located—this also naturally filters out non-kernel entities and other noise, letting us concentrate on cases with clear repair value. Even for these traceable cases, repairing a stale reference is far from simple name substitution. A function’s removal or refactoring often reflects deeper changes in code logic. For example, in the comment “It must be done after xfrm6_policy_check(), because _decode_session6() uses IP6CB()”, _decode_session6() was first renamed to decode_session6() and later refactored to no longer use IP6CB() (commit 7a02070). As a result, the ordering constraint itself no longer holds, and the entire sentence—not just the function name—should be removed. We submitted this repair as a kernel patch, but the maintainer’s response went even further, questioning whether the removal of this constraint makes the repeated fill_cb/restore_cb call pattern it necessitated redundant as well. This suggests that stale comments can signal deeper code-level technical debt. Such cases call for repair strategies that go beyond
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
lexical replacement. In future work, we plan to explore more flexible, agent-based approaches [21] to address them, including handling typos and wildcard-style references.
7
Threats to Validity
Internal validity. Our Resolve-Coccinelle pipeline operates on unexpanded source text, so it cannot recognize function definitions generated through C preprocessor macros. Coccinelle can resolve this by performing full preprocessing with the kernel build configuration, but this drastically increases analysis time and limits results to the single hardware architecture selected in the config file. Operating on unexpanded source text allows our pipeline to find definitions for all architectures. This trade-off favors precision over recall (𝑃=96.7%): Resolve-Coccinelle may over-report unresolved symbols, but rarely misses a genuinely resolved one. For our task, this is the safer direction—over-reported cases are easily filtered during evolution tracing, whereas a missed stale reference would silently forgo repair. Another threat is that we track the function changes commit-by-commit, so a refactoring spread across commits (e.g., delete then re-add) may be misclassified as Removed. To assess this, we sampled 50 cases flagged as removed and compared each deleted body against later-added functions, treating ≥ 50% identifiertoken overlap (Jaccard ≥ 0.5) as a possible multi-step refactoring; none was detected. Further threats stem from our hyperparameters and choice of LLM. For identifying the symbol-introducing commit, we use Jaccard ≥ 0.7 to match the symbol-bearing comment; rerunning this step at 0.6 and 0.8 changed only 0.86% / 0.85% of commits, suggesting low sensitivity to this threshold. For the LLM, we use DeepSeek-V3.2 as a cost-effective choice with temperature 0 for output stability, following prior SE studies [3, 24]. A stronger model shows better performance, e.g. on the RQ2 Entity Selection 200 dataset, Claude Opus 4.7 [1] improves entity-detection 𝐹 1 from 0.964 to 0.975 and file-path match accuracy from 98.3% to 99.4%. This suggests that our results are not tied to the strongest available model and may improve with stronger LLMs. Our prompts use only structured inputs (no Linux-specific few-shot examples), though their effectiveness on other projects requires further evaluation. External validity. We evaluate ReCite solely on the Linux kernel. Given its scale and complexity, we expect the approach to generalize to other C projects with a Git history. While ReCite’s core idea of static-analysis-assisted LLM reasoning is language-agnostic, its effectiveness on other languages remains to be validated. Construct validity. All our annotated datasets meet or exceed the minimum sample size for a 95% confidence level with a ±10% margin of error. Two of them—Symbol Resolution 200 and Refactoring Analysis 200—are sampled from cases where tools disagree, which may introduce sampling bias. To verify that tool performance generalizes, we additionally sampled 100 agreement cases for each dataset. On Symbol Resolution, all five Resolve variants achieve 100% accuracy. On Refactoring Analysis, ReCite achieves 𝐹 1=0.891 on binary classification and 𝐹 1=1.00 on successor identification. The lower binary 𝐹 1 compared to the disagreement set (0.974) is attributable to 9 borderline cases where the function was deleted but its functionality was merged by another one, leading both tools to label them as removed while annotators favor refactored. The perfect successor identification (𝐹 1=1.00) further demonstrates that
ASE ’26, October 12–16, 2026, Munich, Germany
ReCite reliably traces function evolution on both agreement and disagreement cases. Similarly, given the rarity of stale references, RQ4 uses balanced rather than purely random sampling, which may limit our view of their true prevalence across all 83,241 mentions. Nevertheless, on the annotated sample, ReCite achieves high precision with only two false negatives. Additionally, to ensure annotation reliability of our ground truth, all datasets follow a pilot-then-split protocol, and the inter-annotator agreement across pilot batches reaches at least substantial agreement (minimum 𝜅 = 0.62). Finally, Section 6.1 shows that an unresolved symbol (i.e., one without a matching function) is not necessarily a stale reference requiring repair. And we focus on staleness in the narrow sense of function references, specifically cases where the referenced function has disappeared through code evolution. Cases involving other code entities (e.g. variables), or semantic drift while the referenced function will be our future work. Lastly, given the 42.5% Acceptable rate in RQ3, we position ReCite as a decision-support tool rather than a fully automatic repair system, at present.
8
Conclusion and Future Work
We presented ReCite, a three-stage approach for automatically identifying and repairing stale function references in Linux kernel comments. On kernel v6.18-rc1, ReCite extracted 83,241 functionform mentions and detected 869 stale references with generated repair suggestions. A manual evaluation on 200 sampled repairs shows that 85 (42.5%) generated suggestions are directly applicable. To date, 50 of 75 our submitted patches have been accepted. In future work, we plan to broaden coverage by handling abbreviations, wildcard-style references, and omitted parentheses. We also aim to explore agent-based approaches that can reason about deeper semantic changes, and to investigate the generalizability of our approach to other large, long-lived C codebases.
Acknowledgments Yucong Guan, Jiaqi Sun, Yifeng Pan, Zhenyan Song, and Yuxuan Li also contribute to this work. This work was supported in part by the Fundamental and Interdisciplinary Disciplines Breakthrough Plan of the Ministry of Education of China under Grant JYB2025XDXM118; in part by the National Natural Science Foundation of China under Grant 62572237, Grant 62302210, and Grant 72371125; in part by the 2024 Development and Testing Tools Project under Grant CEIEC2024-ZM02-0066; in part by the Frontier Technologies R&D Program of Jiangsu under Grant BF2024059; in part by the Natural Science Foundation of Jiangsu Province under Grant BK20241195; and in part by the PTCC project SWHSec under Grant ANR-22-PTCC0001. This research / project is supported by the National Research Foundation, under its Investigatorship Grant (NRF-NRFI08-20220002). Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not reflect the views of National Research Foundation, Singapore.
Data Availability Statement Our replication package, including all datasets, scripts, and prompts, is available at https://doi.org/10.5281/zenodo.19232503.
ASE ’26, October 12–16, 2026, Munich, Germany
References [1] 2026. Claude. https://claude.ai. [2] Max Brunsfeld et al. 2026. Tree-sitter: A Parser Generator Tool and an Incremental Parsing Library. https://tree-sitter.github.io/tree-sitter/. Accessed: 2026-03. [3] Hongbo Chen, Yifan Zhang, Xing Han, Tianhao Mao, Huanyao Rong, Yuheng Zhang, XiaoFeng Wang, Luyi Xing, Xun Chen, and Hang Zhang. 2025. LineBreaker: Finding Token-Inconsistency Bugs with Large Language Models. In 2025 40th IEEE/ACM International Conference on Automated Software Engineering (ASE). 893–905. doi:10.1109/ASE63991.2025.00079 [4] Beat Fluri, Michael Wursch, Martin PInzger, and Harald Gall. 2007. Change distilling: Tree differencing for fine-grained source code change extraction. IEEE Transactions on software engineering 33, 11 (2007), 725–743. [5] Martin Fowler. 2018. Refactoring: improving the design of existing code. AddisonWesley Professional. [6] Haoyu Gao, Hong Yi Lin, Christoph Treude, Gregory Gay, and Mansooreh Zahedi. 2026. Does My README File Need To Be Updated? Exploring LLM-Based README Maintenance. arXiv:2603.00489 [cs.SE] https://arxiv.org/abs/2603. 00489 [7] Yuan Huang, Yinan Chen, Xiangping Chen, and Xiaocong Zhou. 2025. Are your comments outdated? Toward automatically detecting code-comment consistency. Journal of Software: Evolution and Process 37, 1 (2025), e2718. doi:10.1002/smr.2718 [8] Walid M Ibrahim, Nicolas Bettenburg, Bram Adams, and Ahmed E Hassan. 2012. On the relationship between comment update practices and software bugs. Journal of Systems and Software 85, 10 (2012), 2293–2304. [9] James Ivers, Robert L Nord, Ipek Ozkaya, Chris Seifried, Christopher S Timperley, and Marouane Kessentini. 2022. Industry experiences with large-scale refactoring. In Proceedings of the 30th ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering. 1544–1554. [10] Anil Kurmus, Reinhard Tartler, Daniela Dorneanu, Bernhard Heinloth, Valentin Rothberg, Andreas Ruprecht, Wolfgang Schröder-Preikschat, Daniel Lohmann, and Rüdiger Kapitza. 2013. Attack Surface Metrics and Automated Compile-Time OS Kernel Tailoring. In NDSS. [11] Hyeonseok Lee, Gabin An, and Shin Yoo. 2025. METAMON: Finding Inconsistencies between Program Documentation and Behavior using Metamorphic LLM Queries. arXiv:2502.02794 [cs.SE] https://arxiv.org/abs/2502.02794 [12] Seonah Lee, Jueun Heo, and Katherine R Dearstyne. 2025. Can LLMs Update API Documentation?. In 2025 IEEE International Conference on Software Maintenance and Evolution (ICSME). IEEE, 1–12. [13] Seonah Lee, Rongxin Wu, Shing-Chi Cheung, and Sungwon Kang. 2019. Automatic detection and update suggestion for outdated API names in documentation. IEEE Transactions on Software Engineering 47, 4 (2019), 653–675. [14] Bo Lin, Shangwen Wang, Zhongxin Liu, Yepang Liu, Xin Xia, and Xiaoguang Mao. 2023. Cct5: A code-change-oriented pre-trained model. In Proceedings of the 31st ACM Joint European Software Engineering Conference and Symposium on the Foundations of Software Engineering. 1509–1521. [15] Aixin Liu, Aoxue Mei, Bangcai Lin, Bing Xue, Bingxuan Wang, Bingzheng Xu, Bochao Wu, Bowei Zhang, Chaofan Lin, Chen Dong, et al. 2025. Deepseekv3. 2: Pushing the frontier of open large language models. arXiv preprint arXiv:2512.02556 (2025). [16] Yue Liu, Thanh Le-Cong, Ratnadira Widyasari, Chakkrit Tantithamthavorn, Li Li, Xuan-Bach D Le, and David Lo. 2024. Refining ChatGPT-generated code: Characterizing and mitigating code quality issues. ACM Transactions on Software Engineering and Methodology 33, 5 (2024), 1–26. [17] Zhiyong Liu, Huanchao Chen, Xiangping Chen, Xiaonan Luo, and Fan Zhou. 2018. Automatic detection of outdated comments during code changes. In 2018 IEEE 42nd Annual Computer Software and Applications Conference (COMPSAC), Vol. 1. IEEE, 154–163. [18] Zhongxin Liu, Xin Xia, Meng Yan, and Shanping Li. 2021. Automating justin-time comment updating. In Proceedings of the 35th IEEE/ACM International Conference on Automated Software Engineering (Virtual Event, Australia) (ASE ’20). Association for Computing Machinery, New York, NY, USA, 585–597. doi:10. 1145/3324884.3416581 [19] Yunbo Lyu, Hong Jin Kang, Ratnadira Widyasari, Julia Lawall, and David Lo. 2024. Evaluating SZZ Implementations: An Empirical Study on the Linux Kernel. IEEE Trans. Softw. Eng. 50, 9 (Sept. 2024), 2219–2239. doi:10.1109/TSE.2024.3406718 [20] Yunbo Lyu, Jieke Shi, Hong Jin Kang, Ratnadira Widyasari, Junda He, Yuqing Niu, Chengran Yang, Junkai Chen, Zhou Yang, Julia Lawall, et al. 2026. AgentSZZ: Teaching the LLM Agent to Play Detective with Bug-Inducing Commits. arXiv preprint arXiv:2604.02665 (2026). [21] Yunbo Lyu, David Williams, Jieke Shi, Zhensu Sun, Chao Peng, Zhou Yang, Federica Sarro, and David Lo. 2026. How Do Practitioners Build SE Agents? Insights from a Mixed-Methods Study. arXiv preprint arXiv:2607.10856 (2026). [22] Yunbo Lyu, Zhou Yang, Jieke Shi, Jianming Chang, Yue Liu, and David Lo. 2025. "My productivity is boosted, but . . . " Demystifying Users’ Perception on AI Coding Assistants. In 2025 40th IEEE/ACM International Conference on Automated Software Engineering (ASE). 191–203. doi:10.1109/ASE63991.2025.00024
Sun et al.
[23] Phong Nguyen, Anh M. T. Bui, and Phuong T. Nguyen. 2026. Larger Is Not Always Better: Leveraging Structured Code Diffs for Comment Inconsistency Detection. In 2026 IEEE International Conference on Software Analysis, Evolution and Reengineering (SANER). [24] Shuyin Ouyang, Jie M Zhang, Mark Harman, and Meng Wang. 2025. An empirical study of the non-determinism of ChatGPT in code generation. ACM Transactions on Software Engineering and Methodology 34, 2 (2025), 1–28. [25] Yoann Padioleau, Julia Lawall, René Rydhof Hansen, and Gilles Muller. 2008. Documenting and automating collateral evolutions in linux device drivers. In Proceedings of the 3rd ACM SIGOPS/EuroSys European Conference on Computer Systems 2008 (Glasgow, Scotland UK) (Eurosys ’08). Association for Computing Machinery, New York, NY, USA, 247–260. doi:10.1145/1352592.1352618 [26] Sheena Panthaplackel, Junyi Jessy Li, Milos Gligoric, and Raymond J Mooney. 2021. Deep just-in-time inconsistency detection between comments and source code. In Proceedings of the AAAI conference on artificial intelligence, Vol. 35. 427– 435. [27] Sheena Panthaplackel, Pengyu Nie, Milos Gligoric, Junyi Jessy Li, and Raymond Mooney. 2020. Learning to update natural language comments based on code changes. In Proceedings of the 58th Annual Meeting of the Association for Computational Linguistics. 1853–1868. [28] Anh Quach, Aravind Prakash, and Lok Yan. 2018. Debloating software through { Piece-Wise } compilation and loading. In 27th USENIX security symposium (USENIX Security 18). 869–886. [29] Fazle Rabbi and Md Saeed Siddik. 2020. Detecting code comment inconsistency using siamese recurrent network. In Proceedings of the 28th international conference on program comprehension. 371–375. [30] Chaiyong Ragkhitwetsagul, Jens Krinke, Matheus Paixao, Giuseppe Bianco, and Rocco Oliveto. 2019. Toxic code snippets on stack overflow. IEEE Transactions on Software Engineering 47, 3 (2019), 560–581. [31] Inderjot Kaur Ratol and Martin P. Robillard. 2017. Detecting fragile comments. In 2017 32nd IEEE/ACM International Conference on Automated Software Engineering (ASE). 112–122. doi:10.1109/ASE.2017.8115624 [32] Guoping Rong, Yongda Yu, Song Liu, Xin Tan, Tianyi Zhang, Haifeng Shen, and Jidong Hu. 2025. Code Comment Inconsistency Detection and Rectification Using a Large Language Model. In Proceedings of the IEEE/ACM 47th International Conference on Software Engineering (Ottawa, Ontario, Canada) (ICSE ’25). IEEE Press, 1832–1843. doi:10.1109/ICSE55347.2025.00035 [33] Danilo Silva, João Paulo da Silva, Gustavo Santos, Ricardo Terra, and Marco Tulio Valente. 2020. RefDiff 2.0: A multi-language refactoring detection tool. IEEE Transactions on Software Engineering 47, 12 (2020), 2786–2802. [34] Danilo Silva, Nikolaos Tsantalis, and Marco Tulio Valente. 2016. Why we refactor? confessions of GitHub contributors. In Proceedings of the 2016 24th ACM SIGSOFT International Symposium on Foundations of Software Engineering (Seattle, WA, USA) (FSE 2016). Association for Computing Machinery, New York, NY, USA, 858–870. doi:10.1145/2950290.2950305 [35] Tama Communications Corporation. 2026. GNU GLOBAL Source Code Tagging System. https://www.gnu.org/software/global/. Accessed: 2026-03. [36] Lin Tan, Ding Yuan, Gopal Krishna, and Yuanyuan Zhou. 2007. /*icomment: bugs or bad comments?*/. In Proceedings of Twenty-First ACM SIGOPS Symposium on Operating Systems Principles (Stevenson, Washington, USA) (SOSP ’07). Association for Computing Machinery, New York, NY, USA, 145–158. doi:10.1145/1294261.1294276 [37] Lin Tan, Yuanyuan Zhou, and Yoann Padioleau. 2011. aComment: mining annotations from comments and code to detect interrupt related concurrency bugs. In Proceedings of the 33rd international conference on software engineering. 11–20. [38] Shin Hwei Tan, Darko Marinov, Lin Tan, and Gary T Leavens. 2012. @ tcomment: Testing javadoc comments to detect comment-code inconsistencies. In 2012 IEEE Fifth International Conference on Software Testing, Verification and Validation. IEEE, 260–269. [39] Wen Siang Tan, Markus Wagner, and Christoph Treude. 2023. Wait, wasn’t that code here before? Detecting Outdated Software Documentation. In 2023 IEEE International Conference on Software Maintenance and Evolution (ICSME). IEEE, 553–557. [40] Wen Siang Tan, Markus Wagner, and Christoph Treude. 2024. Detecting outdated code element references in software repository documentation. Empirical Software Engineering 29, 1 (2024), 5. [41] Ye Tang, Aoyang Yan, Hui Liu, Na Meng, and Hao Zhong. 2026. Detecting outdated screenshot from GUI document. ACM Transactions on Software Engineering and Methodology 35, 5 (2026), 1–26. [42] The Linux Kernel Community. 2024. How the Development Process Works. The Linux Kernel Documentation. Accessed: 2026. https://docs.kernel.org/process/2. Process.html [43] Universal Ctags Team. 2026. Universal Ctags: A Maintained Ctags Implementation. https://ctags.io/. Accessed: 2026-03. [44] Fengcai Wen, Csaba Nagy, Gabriele Bavota, and Michele Lanza. 2019. A largescale empirical study on code-comment inconsistencies. In Proceedings of the 27th International Conference on Program Comprehension (Montreal, Quebec, Canada) (ICPC ’19). IEEE Press, 53–64. doi:10.1109/ICPC.2019.00019
We Must Have Missed This Comment: Detecting and Repairing Stale Function References in Linux Kernel Comments
[45] Xiaomeng Xu, Zahin Wahab, Reid Holmes, and Caroline Lemieux. 2025. DocPrism: Local Categorization and External Filtering to Identify Relevant CodeDocumentation Inconsistencies. arXiv:2511.00215 [cs.SE] https://arxiv.org/abs/ 2511.00215 [46] Zhengkang Xu, Shikai Guo, Yumiao Wang, Rong Chen, Hui Li, Xiaochen Li, and He Jiang. 2024. Code Comment Inconsistency Detection Based on Confidence Learning. IEEE Transactions on Software Engineering 50, 3 (2024), 598–617. doi:10.
ASE ’26, October 12–16, 2026, Munich, Germany
1109/TSE.2024.3358489 [47] Hao Zhong and Zhendong Su. 2013. Detecting API documentation errors. In Proceedings of the 2013 ACM SIGPLAN International Conference on Object Oriented Programming Systems Languages & Applications (Indianapolis, Indiana, USA) (OOPSLA ’13). Association for Computing Machinery, New York, NY, USA, 803–816. doi:10.1145/2509136.2509523
Related documents
- CVE-2026-93233#1091762
- A cache-coherent attestation controller for runtime memory integrity verification#358998
- Assignment of the 'OAM Alert Label' for Multiprotocol Label Switching Architecture (MPLS) Operation and Maintenance (OAM) Functions#222701
- BullsEye: Directed Firmware Fuzzing#463146
- Benign on Label, Malicious by Design: Clean-Label Dormant-to-Activated Backdoor via Machine Unlearning with Removable Camouflage#414046
Retrieved via Conceptio: every document is proof-bundled with source, license, and retrieval metadata.
Read the Docs → · View CLI source on GitHub · Conceptio Open Knowledge Archive