[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 16 15:59:37 PST 2025
https://github.com/matts1 updated https://github.com/llvm/llvm-project/pull/127161
>From 918e07fa9012c95e9e2f6cf5f49f74b46db9978f Mon Sep 17 00:00:00 2001
From: Matt Stark <msta at google.com>
Date: Fri, 14 Feb 2025 14:14:03 +1100
Subject: [PATCH] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules.
See https://issues.chromium.org/issues/351909443 for details and benchmarks.
This improves the performance of a file containing a single line, `#include <iostream>`, from ~1 second to ~100ms on my machine.
---
clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 ++++++++++++---
clang/test/Modules/safe_buffers_optout.cpp | 28 +++++++---------------
2 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 589869d018657..849c899bbbc8b 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2546,14 +2546,27 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) {
class CallableVisitor : public DynamicRecursiveASTVisitor {
private:
llvm::function_ref<void(const Decl *)> Callback;
+ const unsigned int TUModuleID;
public:
- CallableVisitor(llvm::function_ref<void(const Decl *)> Callback)
- : Callback(Callback) {
+ CallableVisitor(llvm::function_ref<void(const Decl *)> Callback,
+ unsigned int TUModuleID)
+ : Callback(Callback), TUModuleID(TUModuleID) {
ShouldVisitTemplateInstantiations = true;
ShouldVisitImplicitCode = false;
}
+ bool TraverseDecl(Decl *Node) override {
+ // For performance reasons, only validate the current translation unit's
+ // module, and not modules it depends on.
+ // See https://issues.chromium.org/issues/351909443 for details.
+ if (Node && Node->getOwningModuleID() == TUModuleID) {
+ return DynamicRecursiveASTVisitor::TraverseDecl(Node);
+ } else {
+ return true;
+ }
+ }
+
bool VisitFunctionDecl(FunctionDecl *Node) override {
if (cast<DeclContext>(Node)->isDependentContext())
return true; // Not to analyze dependent decl
@@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
SourceLocation()) ||
(!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) &&
S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) {
- CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU);
+ CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU);
}
}
diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp
index 2129db65da752..8c3d6a235d399 100644
--- a/clang/test/Modules/safe_buffers_optout.cpp
+++ b/clang/test/Modules/safe_buffers_optout.cpp
@@ -95,18 +95,10 @@ int textual(int *p) {
// `safe_buffers_test_optout`, which uses another top-level module
// `safe_buffers_test_base`. (So the module dependencies form a DAG.)
-// No expected warnings from base.h because base.h is a separate
-// module and in a separate TU that is not textually included. The
-// explicit command that builds base.h has no `-Wunsafe-buffer-usage`.
-
-// expected-warning at base.h:3{{unsafe buffer access}}
-// expected-note at base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub1.h:5{{unsafe buffer access}}
-// expected-note at test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub1.h:14{{unsafe buffer access}}
-// expected-note at test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub2.h:5{{unsafe buffer access}}
-// expected-note at test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
+// No expected warnings from base.h, test_sub1, or test_sub2 because they are
+// in seperate modules, and the explicit commands that builds them have no
+// `-Wunsafe-buffer-usage`.
+
int foo(int * p) {
int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
#pragma clang unsafe_buffer_usage begin
@@ -129,14 +121,10 @@ int foo(int * p) {
// `safe_buffers_test_optout`, which uses another top-level module
// `safe_buffers_test_base`. (So the module dependencies form a DAG.)
-// expected-warning at base.h:3{{unsafe buffer access}}
-// expected-note at base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub1.h:5{{unsafe buffer access}}
-// expected-note at test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub1.h:14{{unsafe buffer access}}
-// expected-note at test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
-// expected-warning at test_sub2.h:5{{unsafe buffer access}}
-// expected-note at test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
+// No expected warnings from base.h, test_sub1, or test_sub2 because they are
+// in seperate modules, and the explicit commands that builds them have no
+// `-Wunsafe-buffer-usage`.
+
int foo(int * p) {
int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}}
#pragma clang unsafe_buffer_usage begin
More information about the cfe-commits
mailing list