Skip to content

Commit c2c0b4f

Browse files
committed
Merge bitcoin/bitcoin#30146: Add clang-tidy check for thread_local vars
34c9cee clang-tidy: add check for non-trivial thread_local vars (Cory Fields) Pull request description: Forbid thread_local vars with non-trivial destructors. This is a follow-up from: bitcoin/bitcoin#30095 (comment) ACKs for top commit: maflcko: ACK 34c9cee TheCharlatan: Re-ACK 34c9cee Tree-SHA512: 3a798607fb189a5bbc714ed6e86dea462fe29d366b790e96d10a7b4ffcf1f194da9b8f4cd0b82154408709b8e3c58d3f613d6311903bd65a76d8b556ab230d21
2 parents a231cfe + 34c9cee commit c2c0b4f

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

contrib/devtools/bitcoin-tidy/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ find_program(CLANG_TIDY_EXE NAMES "clang-tidy-${LLVM_VERSION_MAJOR}" "clang-tidy
2525
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
2626
message(STATUS "Found clang-tidy: ${CLANG_TIDY_EXE}")
2727

28-
add_library(bitcoin-tidy MODULE bitcoin-tidy.cpp logprintf.cpp)
28+
add_library(bitcoin-tidy MODULE bitcoin-tidy.cpp logprintf.cpp nontrivial-threadlocal.cpp)
2929
target_include_directories(bitcoin-tidy SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS})
3030

3131
# Disable RTTI and exceptions as necessary
@@ -58,7 +58,7 @@ else()
5858
endif()
5959

6060
# Create a dummy library that runs clang-tidy tests as a side-effect of building
61-
add_library(bitcoin-tidy-tests OBJECT EXCLUDE_FROM_ALL example_logprintf.cpp)
61+
add_library(bitcoin-tidy-tests OBJECT EXCLUDE_FROM_ALL example_logprintf.cpp example_nontrivial-threadlocal.cpp)
6262
add_dependencies(bitcoin-tidy-tests bitcoin-tidy)
6363

6464
set_target_properties(bitcoin-tidy-tests PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")

contrib/devtools/bitcoin-tidy/bitcoin-tidy.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include "logprintf.h"
6+
#include "nontrivial-threadlocal.h"
67

78
#include <clang-tidy/ClangTidyModule.h>
89
#include <clang-tidy/ClangTidyModuleRegistry.h>
@@ -13,6 +14,7 @@ class BitcoinModule final : public clang::tidy::ClangTidyModule
1314
void addCheckFactories(clang::tidy::ClangTidyCheckFactories& CheckFactories) override
1415
{
1516
CheckFactories.registerCheck<bitcoin::LogPrintfCheck>("bitcoin-unterminated-logprintf");
17+
CheckFactories.registerCheck<bitcoin::NonTrivialThreadLocal>("bitcoin-nontrivial-threadlocal");
1618
}
1719
};
1820

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include <string>
2+
thread_local std::string foo;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) 2023 Bitcoin Developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include "nontrivial-threadlocal.h"
6+
7+
#include <clang/AST/ASTContext.h>
8+
#include <clang/ASTMatchers/ASTMatchFinder.h>
9+
10+
11+
// Copied from clang-tidy's UnusedRaiiCheck
12+
namespace {
13+
AST_MATCHER(clang::CXXRecordDecl, hasNonTrivialDestructor) {
14+
// TODO: If the dtor is there but empty we don't want to warn either.
15+
return Node.hasDefinition() && Node.hasNonTrivialDestructor();
16+
}
17+
} // namespace
18+
19+
namespace bitcoin {
20+
21+
void NonTrivialThreadLocal::registerMatchers(clang::ast_matchers::MatchFinder* finder)
22+
{
23+
using namespace clang::ast_matchers;
24+
25+
/*
26+
thread_local std::string foo;
27+
*/
28+
29+
finder->addMatcher(
30+
varDecl(
31+
hasThreadStorageDuration(),
32+
hasType(hasCanonicalType(recordType(hasDeclaration(cxxRecordDecl(hasNonTrivialDestructor())))))
33+
).bind("nontrivial_threadlocal"),
34+
this);
35+
}
36+
37+
void NonTrivialThreadLocal::check(const clang::ast_matchers::MatchFinder::MatchResult& Result)
38+
{
39+
if (const clang::VarDecl* var = Result.Nodes.getNodeAs<clang::VarDecl>("nontrivial_threadlocal")) {
40+
const auto user_diag = diag(var->getBeginLoc(), "Variable with non-trivial destructor cannot be thread_local.");
41+
}
42+
}
43+
44+
} // namespace bitcoin
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2023 Bitcoin Developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef NONTRIVIAL_THREADLOCAL_CHECK_H
6+
#define NONTRIVIAL_THREADLOCAL_CHECK_H
7+
8+
#include <clang-tidy/ClangTidyCheck.h>
9+
10+
namespace bitcoin {
11+
12+
// Warn about any thread_local variable with a non-trivial destructor.
13+
class NonTrivialThreadLocal final : public clang::tidy::ClangTidyCheck
14+
{
15+
public:
16+
NonTrivialThreadLocal(clang::StringRef Name, clang::tidy::ClangTidyContext* Context)
17+
: clang::tidy::ClangTidyCheck(Name, Context) {}
18+
19+
bool isLanguageVersionSupported(const clang::LangOptions& LangOpts) const override
20+
{
21+
return LangOpts.CPlusPlus;
22+
}
23+
void registerMatchers(clang::ast_matchers::MatchFinder* Finder) override;
24+
void check(const clang::ast_matchers::MatchFinder::MatchResult& Result) override;
25+
};
26+
27+
} // namespace bitcoin
28+
29+
#endif // NONTRIVIAL_THREADLOCAL_CHECK_H

0 commit comments

Comments
 (0)