summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2019-10-02 17:18:57 +0000
committerAaron Ballman <aaron@aaronballman.com>2019-10-02 17:18:57 +0000
commitb879fd05bd7628cfb27d8e127dc8751389dcd1d7 (patch)
tree7ee81f7e1c5ba7aaa03d83f3972a2f0b6974e792 /clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
parenteb6700b57e969e75014394a02e8130542f3f6457 (diff)
downloadbcm5719-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/InitVariablesCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp105
1 files changed, 105 insertions, 0 deletions
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
OpenPOWER on IntegriCloud