Skip to content

Commit eb41cc6

Browse files
committed
[clang-tidy] Add module for llvm-libc and restrict-system-libc-header-check.
Summary: This adds a new module to enforce standards specific to the llvm-libc project. This change also adds the first check which restricts user from including system libc headers accidentally which can lead to subtle bugs that would be a challenge to detect. Reviewers: alexfh, hokein, aaron.ballman Reviewed By: aaron.ballman Subscribers: juliehockett, arphaman, jfb, abrachet, sivachandra, Eugene.Zelenko, njames93, mgorny, xazax.hun, MaskRay, cfe-commits Tags: #clang-tools-extra, #libc-project, #clang Differential Revision: https://reviews.llvm.org/D75332
1 parent 360aff0 commit eb41cc6

19 files changed

+223
-0
lines changed

clang-tools-extra/clang-tidy/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ add_subdirectory(google)
5151
add_subdirectory(hicpp)
5252
add_subdirectory(linuxkernel)
5353
add_subdirectory(llvm)
54+
add_subdirectory(llvmlibc)
5455
add_subdirectory(misc)
5556
add_subdirectory(modernize)
5657
if(CLANG_ENABLE_STATIC_ANALYZER)
@@ -75,6 +76,7 @@ set(ALL_CLANG_TIDY_CHECKS
7576
clangTidyHICPPModule
7677
clangTidyLinuxKernelModule
7778
clangTidyLLVMModule
79+
clangTidyLLVMLibcModule
7880
clangTidyMiscModule
7981
clangTidyModernizeModule
8082
clangTidyObjCModule

clang-tools-extra/clang-tidy/ClangTidyForceLinker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ extern volatile int LLVMModuleAnchorSource;
4545
static int LLVM_ATTRIBUTE_UNUSED LLVMModuleAnchorDestination =
4646
LLVMModuleAnchorSource;
4747

48+
// This anchor is used to force the linker to link the LLVMLibcModule.
49+
extern volatile int LLVMLibcModuleAnchorSource;
50+
static int LLVM_ATTRIBUTE_UNUSED LLVMLibcModuleAnchorDestination =
51+
LLVMLibcModuleAnchorSource;
52+
4853
// This anchor is used to force the linker to link the CppCoreGuidelinesModule.
4954
extern volatile int CppCoreGuidelinesModuleAnchorSource;
5055
static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(LLVM_LINK_COMPONENTS support)
2+
3+
add_clang_library(clangTidyLLVMLibcModule
4+
LLVMLibcTidyModule.cpp
5+
RestrictSystemLibcHeadersCheck.cpp
6+
7+
LINK_LIBS
8+
clangAST
9+
clangASTMatchers
10+
clangBasic
11+
clangLex
12+
clangTidy
13+
clangTidyUtils
14+
clangTooling
15+
)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===--- LLVMLibcTidyModule.cpp - clang-tidy ------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "../ClangTidy.h"
10+
#include "../ClangTidyModule.h"
11+
#include "../ClangTidyModuleRegistry.h"
12+
#include "RestrictSystemLibcHeadersCheck.h"
13+
14+
namespace clang {
15+
namespace tidy {
16+
namespace llvm_libc {
17+
18+
class LLVMLibcModule : public ClangTidyModule {
19+
public:
20+
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
21+
CheckFactories.registerCheck<RestrictSystemLibcHeadersCheck>(
22+
"llvmlibc-restrict-system-libc-headers");
23+
}
24+
};
25+
26+
// Register the LLVMLibcTidyModule using this statically initialized variable.
27+
static ClangTidyModuleRegistry::Add<LLVMLibcModule>
28+
X("llvmlibc-module", "Adds LLVM libc standards checks.");
29+
30+
} // namespace llvm_libc
31+
32+
// This anchor is used to force the linker to link in the generated object file
33+
// and thus register the LLVMLibcModule.
34+
volatile int LLVMLibcModuleAnchorSource = 0;
35+
36+
} // namespace tidy
37+
} // namespace clang
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//===--- RestrictSystemLibcHeadersCheck.cpp - clang-tidy ------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "RestrictSystemLibcHeadersCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/ASTMatchers/ASTMatchFinder.h"
12+
#include "clang/Lex/HeaderSearch.h"
13+
#include "clang/Lex/HeaderSearchOptions.h"
14+
15+
namespace clang {
16+
namespace tidy {
17+
namespace llvm_libc {
18+
19+
namespace {
20+
21+
class RestrictedIncludesPPCallbacks : public PPCallbacks {
22+
public:
23+
explicit RestrictedIncludesPPCallbacks(
24+
RestrictSystemLibcHeadersCheck &Check, const SourceManager &SM,
25+
const SmallString<128> CompilerIncudeDir)
26+
: Check(Check), SM(SM), CompilerIncudeDir(CompilerIncudeDir) {}
27+
28+
void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
29+
StringRef FileName, bool IsAngled,
30+
CharSourceRange FilenameRange, const FileEntry *File,
31+
StringRef SearchPath, StringRef RelativePath,
32+
const Module *Imported,
33+
SrcMgr::CharacteristicKind FileType) override;
34+
35+
private:
36+
RestrictSystemLibcHeadersCheck &Check;
37+
const SourceManager &SM;
38+
const SmallString<128> CompilerIncudeDir;
39+
};
40+
41+
} // namespace
42+
43+
void RestrictedIncludesPPCallbacks::InclusionDirective(
44+
SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
45+
bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
46+
StringRef SearchPath, StringRef RelativePath, const Module *Imported,
47+
SrcMgr::CharacteristicKind FileType) {
48+
if (SrcMgr::isSystem(FileType)) {
49+
// Compiler provided headers are allowed (e.g stddef.h).
50+
if (SearchPath == CompilerIncudeDir) return;
51+
if (!SM.isInMainFile(HashLoc)) {
52+
Check.diag(
53+
HashLoc,
54+
"system libc header %0 not allowed, transitively included from %1")
55+
<< FileName << SM.getFilename(HashLoc);
56+
} else {
57+
Check.diag(HashLoc, "system libc header %0 not allowed") << FileName;
58+
}
59+
}
60+
}
61+
62+
void RestrictSystemLibcHeadersCheck::registerPPCallbacks(
63+
const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
64+
SmallString<128> CompilerIncudeDir =
65+
StringRef(PP->getHeaderSearchInfo().getHeaderSearchOpts().ResourceDir);
66+
llvm::sys::path::append(CompilerIncudeDir, "include");
67+
PP->addPPCallbacks(std::make_unique<RestrictedIncludesPPCallbacks>(
68+
*this, SM, CompilerIncudeDir));
69+
}
70+
71+
} // namespace llvm_libc
72+
} // namespace tidy
73+
} // namespace clang
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- RestrictSystemLibcHeadersCheck.h - clang-tidy ----------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_RESTRICTSYSTEMLIBCHEADERSCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_RESTRICTSYSTEMLIBCHEADERSCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang {
15+
namespace tidy {
16+
namespace llvm_libc {
17+
18+
/// Warns of accidental inclusions of system libc headers that aren't
19+
/// compiler provided.
20+
///
21+
/// For the user-facing documentation see:
22+
/// http://clang.llvm.org/extra/clang-tidy/checks/llvmlibc-restrict-system-libc-headers.html
23+
class RestrictSystemLibcHeadersCheck : public ClangTidyCheck {
24+
public:
25+
RestrictSystemLibcHeadersCheck(StringRef Name, ClangTidyContext *Context)
26+
: ClangTidyCheck(Name, Context) {}
27+
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
28+
Preprocessor *ModuleExpanderPP) override;
29+
};
30+
31+
} // namespace llvm_libc
32+
} // namespace tidy
33+
} // namespace clang
34+
35+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVMLIBC_RESTRICTSYSTEMLIBCHEADERSCHECK_H

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ The improvements are...
6767
Improvements to clang-tidy
6868
--------------------------
6969

70+
New module
71+
^^^^^^^^^^
72+
- New module `llvmlibc`.
73+
74+
This module contains checks related to the LLVM-libc coding standards.
75+
7076
New checks
7177
^^^^^^^^^^
7278

@@ -95,6 +101,12 @@ New checks
95101
Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
96102
``memcmp`` and similar derivatives on non-trivial types.
97103

104+
- New :doc:`llvmlibc-restrict-system-libc-headers
105+
<clang-tidy/checks/llvmlibc-restrict-system-libc-headers>` check.
106+
107+
Finds includes of system libc headers not provided by the compiler within
108+
llvm-libc implementations.
109+
98110
- New :doc:`objc-dealloc-in-category
99111
<clang-tidy/checks/objc-dealloc-in-category>` check.
100112

clang-tools-extra/docs/clang-tidy/checks/list.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ Clang-Tidy Checks
187187
`llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm-prefer-isa-or-dyn-cast-in-conditionals.html>`_, "Yes"
188188
`llvm-prefer-register-over-unsigned <llvm-prefer-register-over-unsigned.html>`_, "Yes"
189189
`llvm-twine-local <llvm-twine-local.html>`_, "Yes"
190+
`llvmlibc-restrict-system-libc-headers <llvmlibc-restrict-system-libc-headers.html>`_,
190191
`misc-definitions-in-headers <misc-definitions-in-headers.html>`_, "Yes"
191192
`misc-misplaced-const <misc-misplaced-const.html>`_,
192193
`misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.. title:: clang-tidy - llvmlibc-restrict-system-libc-headers
2+
3+
llvmlibc-restrict-system-libc-headers
4+
=====================================
5+
6+
Finds includes of system libc headers not provided by the compiler within
7+
llvm-libc implementations.
8+
9+
.. code-block:: c++
10+
11+
#include <stdio.h> // Not allowed because it is part of system libc.
12+
#include <stddef.h> // Allowed because it is provided by the compiler.
13+
#include "internal/stdio.h" // Allowed because it is NOT part of system libc.
14+
15+
16+
This check is necessary because accidentally including system libc headers can
17+
lead to subtle and hard to detect bugs. For example consider a system libc
18+
whose ``dirent`` struct has slightly different field ordering than llvm-libc.
19+
While this will compile successfully, this can cause issues during runtime
20+
because they are ABI incompatible.

clang-tools-extra/docs/clang-tidy/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ Name prefix Description
6868
``google-`` Checks related to Google coding conventions.
6969
``hicpp-`` Checks related to High Integrity C++ Coding Standard.
7070
``llvm-`` Checks related to the LLVM coding conventions.
71+
``llvmlibc-`` Checks related to the LLVM-libc coding standards.
7172
``misc-`` Checks that we didn't have a better category for.
7273
``modernize-`` Checks that advocate usage of modern (currently "modern"
7374
means "C++11") language constructs.

0 commit comments

Comments
 (0)