LegalizeAdulthood updated this revision to Diff 398756.
LegalizeAdulthood added a comment.
clang-format
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D7982/new/
https://reviews.llvm.org/D7982
Files:
clang-tools-extra/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp
clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/docs/clang-tidy/checks/readability-duplicate-include.rst
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/iostream
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/readability-duplicate-include.h
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/string.h
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/sys/types.h
clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/types.h
clang-tools-extra/test/clang-tidy/checkers/readability-duplicate-include.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/readability-duplicate-include.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/readability-duplicate-include.cpp
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy -std=c++98-or-later %s readability-duplicate-include %t -- -- -I%S/Inputs/readability-duplicate-include
+
+int a;
+#include <string.h>
+int b;
+#include <string.h>
+int c;
+// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: duplicate include [readability-duplicate-include]
+// CHECK-FIXES: {{^int a;$}}
+// CHECK-FIXES-NEXT: {{^#include <string.h>$}}
+// CHECK-FIXES-NEXT: {{^int b;$}}
+// CHECK-FIXES-NEXT: {{^int c;$}}
+
+int d;
+#include <iostream>
+int e;
+#include <iostream> // extra stuff that will also be removed
+int f;
+// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: {{.*}}
+// CHECK-FIXES: {{^int d;$}}
+// CHECK-FIXES-NEXT: {{^#include <iostream>$}}
+// CHECK-FIXES-NEXT: {{^int e;$}}
+// CHECK-FIXES-NEXT: {{^int f;$}}
+
+int g;
+#include "readability-duplicate-include.h"
+int h;
+#include "readability-duplicate-include.h"
+int i;
+// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: {{.*}}
+// CHECK-FIXES: {{^int g;$}}
+// CHECK-FIXES-NEXT: {{^#include "readability-duplicate-include.h"$}}
+// CHECK-FIXES-NEXT: {{^int h;$}}
+// CHECK-FIXES-NEXT: {{^int i;$}}
+
+#include "types.h"
+
+int j;
+#include <sys/types.h>
+int k;
+#include <sys/types.h>
+int l;
+// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: {{.*}}
+// CHECK-FIXES: {{^int j;$}}
+// CHECK-FIXES-NEXT: {{^#include <sys/types.h>$}}
+// CHECK-FIXES-NEXT: {{^int k;$}}
+// CHECK-FIXES-NEXT: {{^int l;$}}
+
+int m;
+ # include <string.h> // lots of space
+int n;
+// CHECK-MESSAGES: :[[@LINE-2]]:9: warning: {{.*}}
+// CHECK-FIXES: {{^int m;$}}
+// CHECK-FIXES-NEXT: {{^int n;$}}
+
+// defining a macro in the main file resets the included file cache
+#define ARBITRARY_MACRO
+int o;
+#include <sys/types.h>
+int p;
+// CHECK-FIXES: {{^int o;$}}
+// CHECK-FIXES-NEXT: {{^#include <sys/types.h>$}}
+// CHECK-FIXES-NEXT: {{^int p;$}}
+
+// undefining a macro resets the cache
+#undef ARBITRARY_MACRO
+int q;
+#include <sys/types.h>
+int r;
+// CHECK-FIXES: {{^int q;$}}
+// CHECK-FIXES-NEXT: {{^#include <sys/types.h>$}}
+// CHECK-FIXES-NEXT: {{^int r;$}}
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/types.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/types.h
@@ -0,0 +1 @@
+// empty file used by readability-duplicate-include.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/sys/types.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/sys/types.h
@@ -0,0 +1 @@
+// empty file used by readability-duplicate-include.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/string.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/string.h
@@ -0,0 +1 @@
+// empty file used by readability-duplicate-include.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/readability-duplicate-include.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/readability-duplicate-include.h
@@ -0,0 +1 @@
+// empty file used by readability-duplicate-include.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/iostream
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/readability-duplicate-include/iostream
@@ -0,0 +1 @@
+// empty file used by readability-duplicate-include.cpp
Index: clang-tools-extra/docs/clang-tidy/checks/readability-duplicate-include.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/readability-duplicate-include.rst
@@ -0,0 +1,48 @@
+.. title:: clang-tidy - readability-duplicate-include
+
+readability-duplicate-include
+=============================
+
+Looks for duplicate includes and removes them. The check maintains a list of
+included files and looks for duplicates. If a macro is defined or undefined
+then the list of included files is cleared.
+
+A common LLVM preprocessor tactic is to define a macro that controls an
+included file and then include it multiple times in order to achieve different
+effects. Resetting the list of seen includes every time a macro is defined
+or undefined prevents a false positive from that use case.
+
+Examples:
+
+.. code-block:: c++
+
+ #include <memory>
+ #include <vector>
+ #include <memory>
+
+becomes
+
+.. code-block:: c++
+
+ #include <memory>
+ #include <vector>
+
+Because of the intervening macro definitions, this code remains unchanged:
+
+.. code-block:: c++
+
+ class LangOptionsBase {
+ public:
+ // Define simple language options (with no accessors).
+ #define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
+ #define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+ #include "clang/Basic/LangOptions.def"
+
+ protected:
+ // Define language options of enumeration type. These are private, and will
+ // have accessors (below).
+ #define LANGOPT(Name, Bits, Default, Description)
+ #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+ unsigned Name : Bits;
+ #include "clang/Basic/LangOptions.def"
+ };
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -293,6 +293,7 @@
`readability-container-size-empty <readability-container-size-empty.html>`_, "Yes"
`readability-convert-member-functions-to-static <readability-convert-member-functions-to-static.html>`_, "Yes"
`readability-delete-null-pointer <readability-delete-null-pointer.html>`_, "Yes"
+ `readability-duplicate-include <readability-duplicate-include.html>`_, "Yes"
`readability-else-after-return <readability-else-after-return.html>`_, "Yes"
`readability-function-cognitive-complexity <readability-function-cognitive-complexity.html>`_,
`readability-function-size <readability-function-size.html>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -117,6 +117,11 @@
Finds cases where code could use ``data()`` rather than the address of the
element at index 0 in a container.
+- New :doc:`readability-duplicate-include
+ <clang-tidy/checks/readability-duplicate-include>` check.
+
+ Finds duplicate includes, e.g. files included more than once.
+
- New :doc:`readability-identifier-length
<clang-tidy/checks/readability-identifier-length>` check.
Index: clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -16,6 +16,7 @@
#include "ContainerSizeEmptyCheck.h"
#include "ConvertMemberFunctionsToStatic.h"
#include "DeleteNullPointerCheck.h"
+#include "DuplicateIncludeCheck.h"
#include "ElseAfterReturnCheck.h"
#include "FunctionCognitiveComplexityCheck.h"
#include "FunctionSizeCheck.h"
@@ -71,6 +72,8 @@
"readability-convert-member-functions-to-static");
CheckFactories.registerCheck<DeleteNullPointerCheck>(
"readability-delete-null-pointer");
+ CheckFactories.registerCheck<DuplicateIncludeCheck>(
+ "readability-duplicate-include");
CheckFactories.registerCheck<ElseAfterReturnCheck>(
"readability-else-after-return");
CheckFactories.registerCheck<FunctionCognitiveComplexityCheck>(
Index: clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h
@@ -0,0 +1,35 @@
+//===--- DuplicateIncludeCheck.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_READABILITY_DUPLICATE_INCLUDE_CHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DUPLICATE_INCLUDE_CHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \brief Find and remove duplicate #include directives.
+///
+/// Only consecutive include directives without any other preprocessor
+/// directives between them are analyzed.
+class DuplicateIncludeCheck : public ClangTidyCheck {
+public:
+ DuplicateIncludeCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_DUPLICATE_INCLUDE_CHECK_H
Index: clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp
@@ -0,0 +1,103 @@
+//===--- DuplicateIncludeCheck.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 "DuplicateIncludeCheck.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+namespace {
+
+SourceLocation advanceBeyondCurrentLine(const SourceManager &SM,
+ SourceLocation Start, int Offset) {
+ const FileID Id = SM.getFileID(Start);
+ const unsigned LineNumber = SM.getSpellingLineNumber(Start);
+ while (SM.getFileID(Start) == Id &&
+ SM.getSpellingLineNumber(Start.getLocWithOffset(Offset)) ==
+ LineNumber) {
+ Start = Start.getLocWithOffset(Offset);
+ }
+ return Start;
+}
+
+class DuplicateIncludeCallbacks : public PPCallbacks {
+public:
+ DuplicateIncludeCallbacks(DuplicateIncludeCheck &Check,
+ const SourceManager &SM)
+ : Check(Check), SM(SM) {}
+
+ void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
+ StringRef FileName, bool IsAngled,
+ CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath,
+ const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) override;
+
+ void MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) override;
+
+ void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
+ const MacroDirective *Undef) override;
+
+private:
+ std::vector<StringRef> Files;
+ DuplicateIncludeCheck &Check;
+ const SourceManager &SM;
+};
+
+void DuplicateIncludeCallbacks::InclusionDirective(
+ SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName,
+ bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File,
+ StringRef SearchPath, StringRef RelativePath, const Module *Imported,
+ SrcMgr::CharacteristicKind FileType) {
+ if (!SM.isInMainFile(HashLoc)) {
+ return;
+ }
+
+ if (std::find(Files.cbegin(), Files.cend(), FileName) != Files.end()) {
+ const auto Start =
+ advanceBeyondCurrentLine(SM, HashLoc, -1).getLocWithOffset(-1);
+ const auto End = advanceBeyondCurrentLine(SM, FilenameRange.getEnd(), 1);
+ Check.diag(HashLoc, "duplicate include")
+ << FixItHint::CreateRemoval(SourceRange(Start, End));
+ } else {
+ Files.push_back(FileName);
+ }
+}
+
+void DuplicateIncludeCallbacks::MacroDefined(const Token &MacroNameTok,
+ const MacroDirective *MD) {
+ if (SM.isInMainFile(MacroNameTok.getLocation())) {
+ Files.clear();
+ }
+}
+
+void DuplicateIncludeCallbacks::MacroUndefined(const Token &MacroNameTok,
+ const MacroDefinition &MD,
+ const MacroDirective *Undef) {
+ if (SM.isInMainFile(MacroNameTok.getLocation())) {
+ Files.clear();
+ }
+}
+
+} // namespace
+
+void DuplicateIncludeCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ PP->addPPCallbacks(std::make_unique<DuplicateIncludeCallbacks>(*this, SM));
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -11,6 +11,7 @@
ContainerSizeEmptyCheck.cpp
ConvertMemberFunctionsToStatic.cpp
DeleteNullPointerCheck.cpp
+ DuplicateIncludeCheck.cpp
ElseAfterReturnCheck.cpp
FunctionCognitiveComplexityCheck.cpp
FunctionSizeCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits