diff options
| author | Aaron Ballman <aaron@aaronballman.com> | 2019-10-02 17:18:57 +0000 |
|---|---|---|
| committer | Aaron Ballman <aaron@aaronballman.com> | 2019-10-02 17:18:57 +0000 |
| commit | b879fd05bd7628cfb27d8e127dc8751389dcd1d7 (patch) | |
| tree | 7ee81f7e1c5ba7aaa03d83f3972a2f0b6974e792 /clang-tools-extra/clang-tidy/cppcoreguidelines | |
| parent | eb6700b57e969e75014394a02e8130542f3f6457 (diff) | |
| download | bcm5719-llvm-b879fd05bd7628cfb27d8e127dc8751389dcd1d7.tar.gz bcm5719-llvm-b879fd05bd7628cfb27d8e127dc8751389dcd1d7.zip | |
Add the misc-init-local-variables check.
This checks finds all primitive type local variables (integers, doubles, pointers) that are declared without an initial value. Includes fixit functionality to initialize said variables with a default value. This is zero for most types and NaN for floating point types. The use of NaNs is copied from the D programming language.
Patch by Jussi Pakkanen.
llvm-svn: 373489
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines')
4 files changed, 151 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index be852859325..13c15bc9d22 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support) add_clang_library(clangTidyCppCoreGuidelinesModule AvoidGotoCheck.cpp CppCoreGuidelinesTidyModule.cpp + InitVariablesCheck.cpp InterfacesGlobalInitCheck.cpp MacroUsageCheck.cpp NarrowingConversionsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index 7c7fd1b72cb..8886eb83379 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -15,6 +15,7 @@ #include "../modernize/UseOverrideCheck.h" #include "../readability/MagicNumbersCheck.h" #include "AvoidGotoCheck.h" +#include "InitVariablesCheck.h" #include "InterfacesGlobalInitCheck.h" #include "MacroUsageCheck.h" #include "NarrowingConversionsCheck.h" @@ -49,6 +50,8 @@ public: "cppcoreguidelines-avoid-magic-numbers"); CheckFactories.registerCheck<modernize::UseOverrideCheck>( "cppcoreguidelines-explicit-virtual-functions"); + CheckFactories.registerCheck<InitVariablesCheck>( + "cppcoreguidelines-init-variables"); CheckFactories.registerCheck<InterfacesGlobalInitCheck>( "cppcoreguidelines-interfaces-global-init"); CheckFactories.registerCheck<MacroUsageCheck>( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp new file mode 100644 index 00000000000..8a628317a30 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp @@ -0,0 +1,105 @@ +//===--- InitVariablesCheck.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 "InitVariablesCheck.h" + +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +namespace { +AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); } +} // namespace + +InitVariablesCheck::InitVariablesCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IncludeStyle(utils::IncludeSorter::parseIncludeStyle( + Options.getLocalOrGlobal("IncludeStyle", "llvm"))), + MathHeader(Options.get("MathHeader", "math.h")) {} + +void InitVariablesCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(unless(hasInitializer(anything())), + unless(isInstantiated()), isLocalVarDecl(), + unless(isStaticLocal()), isDefinition()) + .bind("vardecl"), + this); +} + +void InitVariablesCheck::registerPPCallbacks(const SourceManager &SM, + Preprocessor *PP, + Preprocessor *ModuleExpanderPP) { + IncludeInserter = + std::make_unique<utils::IncludeInserter>(SM, getLangOpts(), IncludeStyle); + PP->addPPCallbacks(IncludeInserter->CreatePPCallbacks()); +} + +void InitVariablesCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("vardecl"); + const ASTContext &Context = *Result.Context; + const SourceManager &Source = Context.getSourceManager(); + + // We want to warn about cases where the type name + // comes from a macro like this: + // + // TYPENAME_FROM_MACRO var; + // + // but not if the entire declaration comes from + // one: + // + // DEFINE_SOME_VARIABLE(); + // + // or if the definition comes from a macro like SWAP + // that uses an internal temporary variable. + // + // Thus check that the variable name does + // not come from a macro expansion. + if (MatchedDecl->getEndLoc().isMacroID()) + return; + + QualType TypePtr = MatchedDecl->getType(); + const char *InitializationString = nullptr; + bool AddMathInclude = false; + + if (TypePtr->isIntegerType()) + InitializationString = " = 0"; + else if (TypePtr->isFloatingType()) { + InitializationString = " = NAN"; + AddMathInclude = true; + } else if (TypePtr->isAnyPointerType()) { + if (getLangOpts().CPlusPlus11) + InitializationString = " = nullptr"; + else + InitializationString = " = NULL"; + } + + if (InitializationString) { + auto Diagnostic = + diag(MatchedDecl->getLocation(), "variable %0 is not initialized") + << MatchedDecl + << FixItHint::CreateInsertion( + MatchedDecl->getLocation().getLocWithOffset( + MatchedDecl->getName().size()), + InitializationString); + if (AddMathInclude) { + auto IncludeHint = IncludeInserter->CreateIncludeInsertion( + Source.getFileID(MatchedDecl->getBeginLoc()), MathHeader, false); + if (IncludeHint) + Diagnostic << *IncludeHint; + } + } +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.h new file mode 100644 index 00000000000..0cacf9e533c --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.h @@ -0,0 +1,42 @@ +//===--- InitVariablesCheck.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_CPPCOREGUIDELINES_INITVARIABLESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_INITVARIABLESCHECK_H + +#include "../ClangTidyCheck.h" +#include "../utils/IncludeInserter.h" +#include "../utils/OptionsUtils.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// Find uninitialized local variables. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-init-variables.html +class InitVariablesCheck : public ClangTidyCheck { +public: + InitVariablesCheck(StringRef Name, ClangTidyContext *Context); + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::unique_ptr<clang::tidy::utils::IncludeInserter> IncludeInserter; + const utils::IncludeSorter::IncludeStyle IncludeStyle; + const std::string MathHeader; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_INITVARIABLESCHECK_H |

