[clang] [clang] Expose CrossTU context in CheckerContext.h (PR #181713)

via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 16 13:27:10 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Davide Cunial (capitan-davide)

<details>
<summary>Changes</summary>

Sometimes I find it useful to write an AST visitor that can cross TU boundaries. This patch allows to do this in a CSA checker.

An example use-case is the following:

> do not call 'baz' from a thread created using 'pthread_create'

My solution:

1. matche the `check::PreCall` to `pthread_create`
2. extract its 3rd argument (the thread entry point) as `FunctionDecl`
3. use a `RecursiveASTVisitor` to traverse all `CallExpr`s, looking for a call to `baz`
4. if the visitor cannot dig into a `CallExpr`, because the function body is in a separate TU, try to load the declaration using the CTU context

```c++
// In VisitCallExpr

const FunctionDecl *Callee = CE->getDirectCallee();
if (!Callee->hasBody()) {
  auto Result = CTUCtx->getCrossTranslationUnitDefinition(Callee, ...);

  if (!Result) {
    // Handle error
    return true;
  }

  CalleeDefinition = *Result;
}

// Now traverse CalleeDefinition->getBody()
```

Example output:

```sh
../build/Debug/bin/clang++ --analyze \
        -Xclang -analyzer-checker=example.MyChecker \
        -Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true \
        -Xclang -analyzer-config -Xclang ctu-dir=. \
        -Xclang -analyzer-config -Xclang ctu-invocation-list=invocations.yaml \
        -Xclang -analyzer-output=plist-multi-file \
        main.cpp
main.cpp:14:5: warning: function 'baz' called from a thread created using 'pthread_create' [example.MyChecker]
   14 |     pthread_create(&t, nullptr, thread_function, nullptr);
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:1: note: entering 'thread_function' here
    5 | void *thread_function(void *arg)
      | ^
main.cpp:7:5: note: 'thread_function' calls 'foo' here
    7 |     foo();
      |     ^
foo.cpp:5:12: note: 'foo' calls 'bar' here
    5 |     return bar();
      |            ^
bar.cpp:10:5: note: 'bar' calls 'baz' here
   10 |     baz();
      |     ^~~~~
4 warnings generated.
```

---
Full diff: https://github.com/llvm/llvm-project/pull/181713.diff


1 Files Affected:

- (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (+9) 


``````````diff
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index cf035a999af8a..dab36cae32109 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
 
+#include "clang/CrossTU/CrossTranslationUnit.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include <optional>
@@ -69,6 +70,14 @@ class CheckerContext {
     return Eng.getConstraintManager();
   }
 
+  cross_tu::CrossTranslationUnitContext *getCrossTranslationUnitContext() {
+    return Eng.getCrossTranslationUnitContext();
+  }
+  const cross_tu::CrossTranslationUnitContext *
+  getCrossTranslationUnitContext() const {
+    return Eng.getCrossTranslationUnitContext();
+  }
+
   StoreManager &getStoreManager() {
     return Eng.getStoreManager();
   }

``````````

</details>


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


More information about the cfe-commits mailing list