[clang-tools-extra] [clang-tidy] Add avoid-pragma-once. (PR #140388)
Tommy Chen via cfe-commits
cfe-commits at lists.llvm.org
Sat May 17 21:42:10 PDT 2025
https://github.com/dl8sd11 updated https://github.com/llvm/llvm-project/pull/140388
>From 5bc074dadddb094bf954388a95ecb818abe17b56 Mon Sep 17 00:00:00 2001
From: dl8sd11 <gcchen at google.com>
Date: Sat, 17 May 2025 17:23:26 +0000
Subject: [PATCH 1/3] [clang-tidy] Add avoid-pragma-once.
---
.../portability/AvoidPragmaOnceCheck.cpp | 49 +++++++++++++++++++
.../portability/AvoidPragmaOnceCheck.h | 34 +++++++++++++
.../clang-tidy/portability/CMakeLists.txt | 1 +
.../portability/PortabilityTidyModule.cpp | 3 ++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../checks/portability/avoid-pragma-once.rst | 12 +++++
.../Inputs/avoid-pragma-once/lib.h | 1 +
.../portability/avoid-pragma-once.cpp | 5 ++
9 files changed, 111 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/portability/avoid-pragma-once.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/portability/Inputs/avoid-pragma-once/lib.h
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
diff --git a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
new file mode 100644
index 0000000000000..e13b2039ac366
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
@@ -0,0 +1,49 @@
+//===--- AvoidPragmaOnceCheck.cpp - clang-tidy ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AvoidPragmaOnceCheck.h"
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang::tidy::portability {
+
+class PragmaOnceCallbacks : public PPCallbacks {
+ public:
+ PragmaOnceCallbacks(AvoidPragmaOnceCheck *Check, const SourceManager &SM)
+ : Check(Check), SM(SM) {}
+ void PragmaDirective(SourceLocation Loc,
+ PragmaIntroducerKind Introducer) override {
+ auto Str = llvm::StringRef(SM.getCharacterData(Loc));
+ if (!Str.consume_front("#")) {
+ return;
+ }
+ Str = Str.trim();
+ if (!Str.consume_front("pragma")) {
+ return;
+ }
+ Str = Str.trim();
+ if (Str.starts_with("once")) {
+ Check->diag(Loc, "Avoid pragma once.");
+ }
+ }
+
+ private:
+ AvoidPragmaOnceCheck *Check;
+ const SourceManager &SM;
+};
+
+void AvoidPragmaOnceCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(std::make_unique<PragmaOnceCallbacks>(this, SM));
+}
+
+} // namespace clang::tidy::portability
diff --git a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
new file mode 100644
index 0000000000000..f5a9246f8af58
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
@@ -0,0 +1,34 @@
+//===--- AvoidPragmaOnceCheck.h - clang-tidy --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPRAGMAONCECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPRAGMAONCECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::portability {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/portability/avoid-pragma-once.html
+class AvoidPragmaOnceCheck : public ClangTidyCheck {
+ public:
+ AvoidPragmaOnceCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+};
+
+} // namespace clang::tidy::portability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPRAGMAONCECHECK_H
diff --git a/clang-tools-extra/clang-tidy/portability/CMakeLists.txt b/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
index 5a38722a61481..73d74a550afc0 100644
--- a/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/portability/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_library(clangTidyPortabilityModule STATIC
+ AvoidPragmaOnceCheck.cpp
PortabilityTidyModule.cpp
RestrictSystemIncludesCheck.cpp
SIMDIntrinsicsCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
index 316b98b46cf3f..a15cb36dfdaff 100644
--- a/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/portability/PortabilityTidyModule.cpp
@@ -9,6 +9,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "AvoidPragmaOnceCheck.h"
#include "RestrictSystemIncludesCheck.h"
#include "SIMDIntrinsicsCheck.h"
#include "StdAllocatorConstCheck.h"
@@ -20,6 +21,8 @@ namespace portability {
class PortabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<AvoidPragmaOnceCheck>(
+ "portability-avoid-pragma-once");
CheckFactories.registerCheck<RestrictSystemIncludesCheck>(
"portability-restrict-system-includes");
CheckFactories.registerCheck<SIMDIntrinsicsCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 9b29ab12e1bfa..2b8d37054716b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -142,6 +142,11 @@ New checks
Finds potentially erroneous calls to ``reset`` method on smart pointers when
the pointee type also has a ``reset`` method.
+- New :doc:`portability-avoid-pragma-once
+ <clang-tidy/checks/portability/avoid-pragma-once>` check.
+
+ A check that catches pragma once.
+
New check aliases
^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 1ec476eef3420..607c526621cdf 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -351,6 +351,7 @@ Clang-Tidy Checks
:doc:`performance-type-promotion-in-math-fn <performance/type-promotion-in-math-fn>`, "Yes"
:doc:`performance-unnecessary-copy-initialization <performance/unnecessary-copy-initialization>`, "Yes"
:doc:`performance-unnecessary-value-param <performance/unnecessary-value-param>`, "Yes"
+ :doc:`portability-avoid-pragma-once <portability/avoid-pragma-once>`, "Yes"
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/avoid-pragma-once.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/avoid-pragma-once.rst
new file mode 100644
index 0000000000000..721511bf395c1
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/portability/avoid-pragma-once.rst
@@ -0,0 +1,12 @@
+.. title:: clang-tidy - portability-avoid-pragma-once
+
+portability-avoid-pragma-once
+=============================
+
+This check catches pragma once usage.
+
+For example:
+
+```
+#pragma once // Bad: Avoid pragma once.
+```
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/Inputs/avoid-pragma-once/lib.h b/clang-tools-extra/test/clang-tidy/checkers/portability/Inputs/avoid-pragma-once/lib.h
new file mode 100644
index 0000000000000..6f70f09beec22
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/Inputs/avoid-pragma-once/lib.h
@@ -0,0 +1 @@
+#pragma once
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
new file mode 100644
index 0000000000000..46f452dfe1f77
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
@@ -0,0 +1,5 @@
+// RUN: %check_clang_tidy %s portability-avoid-pragma-once %t \
+// RUN: -- -- -isystem %S/Inputs/avoid-pragma-once
+
+#include <lib.h>
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: Avoid pragma once. [portability-avoid-pragma-once]
\ No newline at end of file
>From 63ae6d77254cf1e0d11ba6022cf4c6a8c3e7f78b Mon Sep 17 00:00:00 2001
From: dl8sd11 <gcchen at google.com>
Date: Sat, 17 May 2025 17:53:43 +0000
Subject: [PATCH 2/3] Apply clang-format.
---
.../clang-tidy/portability/AvoidPragmaOnceCheck.cpp | 6 +++---
.../clang-tidy/portability/AvoidPragmaOnceCheck.h | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
index e13b2039ac366..9a835efd4b9e7 100644
--- a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.cpp
@@ -16,7 +16,7 @@
namespace clang::tidy::portability {
class PragmaOnceCallbacks : public PPCallbacks {
- public:
+public:
PragmaOnceCallbacks(AvoidPragmaOnceCheck *Check, const SourceManager &SM)
: Check(Check), SM(SM) {}
void PragmaDirective(SourceLocation Loc,
@@ -35,7 +35,7 @@ class PragmaOnceCallbacks : public PPCallbacks {
}
}
- private:
+private:
AvoidPragmaOnceCheck *Check;
const SourceManager &SM;
};
@@ -46,4 +46,4 @@ void AvoidPragmaOnceCheck::registerPPCallbacks(const SourceManager &SM,
PP->addPPCallbacks(std::make_unique<PragmaOnceCallbacks>(this, SM));
}
-} // namespace clang::tidy::portability
+} // namespace clang::tidy::portability
diff --git a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
index f5a9246f8af58..7208872d416b4 100644
--- a/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
+++ b/clang-tools-extra/clang-tidy/portability/AvoidPragmaOnceCheck.h
@@ -18,7 +18,7 @@ namespace clang::tidy::portability {
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/portability/avoid-pragma-once.html
class AvoidPragmaOnceCheck : public ClangTidyCheck {
- public:
+public:
AvoidPragmaOnceCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
@@ -29,6 +29,6 @@ class AvoidPragmaOnceCheck : public ClangTidyCheck {
Preprocessor *ModuleExpanderPP) override;
};
-} // namespace clang::tidy::portability
+} // namespace clang::tidy::portability
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPRAGMAONCECHECK_H
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPRAGMAONCECHECK_H
>From 80899c5631e1c422ba8b59796c47e62ab3ee1b16 Mon Sep 17 00:00:00 2001
From: dl8sd11 <gcchen at google.com>
Date: Sun, 18 May 2025 04:41:51 +0000
Subject: [PATCH 3/3] Fix test by adding header-filter.
---
.../clang-tidy/checkers/portability/avoid-pragma-once.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp b/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
index 46f452dfe1f77..b6695997d1945 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/portability/avoid-pragma-once.cpp
@@ -1,5 +1,5 @@
// RUN: %check_clang_tidy %s portability-avoid-pragma-once %t \
-// RUN: -- -- -isystem %S/Inputs/avoid-pragma-once
+// RUN: -header-filter=.* -- -- -I%S/Inputs/avoid-pragma-once
-#include <lib.h>
+#include "lib.h"
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: Avoid pragma once. [portability-avoid-pragma-once]
\ No newline at end of file
More information about the cfe-commits
mailing list