[clang-tools-extra] r373489 - Add the misc-init-local-variables check.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 2 10:18:57 PDT 2019


Author: aaronballman
Date: Wed Oct  2 10:18:57 2019
New Revision: 373489

URL: http://llvm.org/viewvc/llvm-project?rev=373489&view=rev
Log:
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.

Added:
    clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
    clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.h
    clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst
    clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-init-variables.cpp
Modified:
    clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt
    clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
    clang-tools-extra/trunk/docs/ReleaseNotes.rst
    clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst

Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt?rev=373489&r1=373488&r2=373489&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CMakeLists.txt Wed Oct  2 10:18:57 2019
@@ -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

Modified: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp?rev=373489&r1=373488&r2=373489&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp Wed Oct  2 10:18:57 2019
@@ -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>(

Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp?rev=373489&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp Wed Oct  2 10:18:57 2019
@@ -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

Added: clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.h?rev=373489&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/cppcoreguidelines/InitVariablesCheck.h Wed Oct  2 10:18:57 2019
@@ -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

Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=373489&r1=373488&r2=373489&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Oct  2 10:18:57 2019
@@ -79,24 +79,27 @@ Improvements to clang-tidy
   Finds obvious infinite loops (loops where the condition variable is not
   changed at all).
 
+- New :doc:`cppcoreguidelines-init-variables
+  <clang-tidy/checks/cppcoreguidelines-init-variables>` check.
+
 - New :doc:`darwin-dispatch-once-nonstatic
   <clang-tidy/checks/darwin-dispatch-once-nonstatic>` check.
 
   Finds declarations of ``dispatch_once_t`` variables without static or global
   storage.
 
-- New :doc:`linuxkernel-must-use-errs
-  <clang-tidy/checks/linuxkernel-must-use-errs>` check.
-
-  Checks Linux kernel code to see if it uses the results from the functions in
-  ``linux/err.h``.
-
 - New :doc:`google-upgrade-googletest-case
   <clang-tidy/checks/google-upgrade-googletest-case>` check.
 
   Finds uses of deprecated Googletest APIs with names containing ``case`` and
   replaces them with equivalent APIs with ``suite``.
 
+- New :doc:`linuxkernel-must-use-errs
+  <clang-tidy/checks/linuxkernel-must-use-errs>` check.
+
+  Checks Linux kernel code to see if it uses the results from the functions in
+  ``linux/err.h``.
+
 - New :doc:`llvm-prefer-register-over-unsigned
   <clang-tidy/checks/llvm-prefer-register-over-unsigned>` check.
 

Added: clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst?rev=373489&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst Wed Oct  2 10:18:57 2019
@@ -0,0 +1,51 @@
+.. title:: clang-tidy - cppcoreguidelines-init-variables
+
+cppcoreguidelines-init-variables
+================================
+
+Checks whether there are local variables that are declared without an
+initial value. These may lead to unexpected behaviour if there is a
+code path that reads the variable before assigning to it.
+
+Only integers, booleans, floats, doubles and pointers are checked. The
+fix option initializes all detected values with the value of zero. An
+exception is float and double types, which are initialized to NaN.
+
+As an example a function that looks like this:
+
+.. code-block:: c++
+
+   void function() {
+     int x;
+     char *txt;
+     double d;
+
+     // Rest of the function.
+   }
+
+Would be rewritten to look like this:
+
+.. code-block:: c++
+
+   #include <math.h>
+
+   void function() {
+     int x = 0;
+     char *txt = nullptr;
+     double d = NAN;
+
+     // Rest of the function.
+   }
+
+Options
+-------
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or
+   `google`. Default is `llvm`.
+
+.. option:: MathHeader
+
+   A string specifying the header to include to get the definition of
+   `NAN`. Default is `math.h`.

Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=373489&r1=373488&r2=373489&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Oct  2 10:18:57 2019
@@ -194,6 +194,7 @@ Clang-Tidy Checks
    cppcoreguidelines-avoid-magic-numbers (redirects to readability-magic-numbers) <cppcoreguidelines-avoid-magic-numbers>
    cppcoreguidelines-c-copy-assignment-signature (redirects to misc-unconventional-assign-operator) <cppcoreguidelines-c-copy-assignment-signature>
    cppcoreguidelines-explicit-virtual-functions (redirects to modernize-use-override) <cppcoreguidelines-explicit-virtual-functions>
+   cppcoreguidelines-init-variables
    cppcoreguidelines-interfaces-global-init
    cppcoreguidelines-macro-usage
    cppcoreguidelines-narrowing-conversions

Added: clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-init-variables.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-init-variables.cpp?rev=373489&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-init-variables.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/cppcoreguidelines-init-variables.cpp Wed Oct  2 10:18:57 2019
@@ -0,0 +1,80 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-init-variables %t
+
+// Ensure that function declarations are not changed.
+void some_func(int x, double d, bool b, const char *p);
+
+// Ensure that function arguments are not changed
+int identity_function(int x) {
+  return x;
+}
+
+int do_not_modify_me;
+
+static int should_not_be_initialized;
+extern int should_not_be_initialized2;
+
+typedef struct {
+  int unaltered1;
+  int unaltered2;
+} UnusedStruct;
+
+typedef int my_int_type;
+#define MACRO_INT int
+#define FULL_DECLARATION() int macrodecl;
+
+template <typename T>
+void template_test_function() {
+  T t;
+  int uninitialized;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'uninitialized' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  int uninitialized = 0;{{$}}
+}
+
+void init_unit_tests() {
+  int x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'x' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  int x = 0;{{$}}
+  my_int_type myint;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: variable 'myint' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  my_int_type myint = 0;{{$}}
+
+  MACRO_INT macroint;
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: variable 'macroint' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  MACRO_INT macroint = 0;{{$}}
+  FULL_DECLARATION();
+
+  int x0 = 1, x1, x2 = 2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: variable 'x1' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  int x0 = 1, x1 = 0, x2 = 2;{{$}}
+  int y0, y1 = 1, y2;
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: variable 'y0' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-MESSAGES: :[[@LINE-2]]:19: warning: variable 'y2' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  int y0 = 0, y1 = 1, y2 = 0;{{$}}
+  int hasval = 42;
+
+  float f;
+  // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: variable 'f' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  float f = NAN;{{$}}
+  float fval = 85.0;
+  double d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: variable 'd' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  double d = NAN;{{$}}
+  double dval = 99.0;
+
+  bool b;
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: variable 'b' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  bool b = 0;{{$}}
+  bool bval = true;
+
+  const char *ptr;
+  // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: variable 'ptr' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  const char *ptr = nullptr;{{$}}
+  const char *ptrval = "a string";
+
+  UnusedStruct u;
+
+  static int does_not_need_an_initializer;
+  extern int does_not_need_an_initializer2;
+  int parens(42);
+  int braces{42};
+}




More information about the cfe-commits mailing list