jpakkane updated this revision to Diff 212664.
jpakkane added a comment.
Herald added subscribers: kbarton, nemanjai.

Renamed to cppcoreguidelines-init-variables.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64671/new/

https://reviews.llvm.org/D64671

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

Index: clang-tools-extra/test/clang-tidy/cppcoreguidelines-init-variables.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/cppcoreguidelines-init-variables.cpp
@@ -0,0 +1,104 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-init-variables %t
+
+#include <stdint.h>
+
+#define DO_NOTHING(x) ((void)x)
+
+// 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;
+
+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;{{$}}
+
+  DO_NOTHING(t);
+  DO_NOTHING(uninitialized);
+}
+
+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;{{$}}
+  int32_t sized_var;
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: variable 'sized_var' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  int32_t sized_var = 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 = (0.0/0.0);{{$}}
+  float fval = 85.0;
+  double d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: variable 'd' is not initialized [cppcoreguidelines-init-variables]
+  // CHECK-FIXES: {{^}}  double d = (0.0/0.0);{{$}}
+  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;
+
+  DO_NOTHING(x);
+  DO_NOTHING(sized_var);
+  DO_NOTHING(myint);
+  DO_NOTHING(macroint);
+  DO_NOTHING(macrodecl);
+  DO_NOTHING(x0);
+  DO_NOTHING(x1);
+  DO_NOTHING(x2);
+  DO_NOTHING(y0);
+  DO_NOTHING(y1);
+  DO_NOTHING(y2);
+  DO_NOTHING(hasval);
+  DO_NOTHING(f);
+  DO_NOTHING(fval);
+  DO_NOTHING(d);
+  DO_NOTHING(dval);
+  DO_NOTHING(b);
+  DO_NOTHING(bval);
+  DO_NOTHING(ptr);
+  DO_NOTHING(ptrval);
+  DO_NOTHING(u);
+}
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
@@ -107,6 +107,7 @@
    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
Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-init-variables.rst
@@ -0,0 +1,37 @@
+.. 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++
+
+   void function() {
+     int x = 0;
+     char *txt = nullptr;
+     double d = (0.0/0.0);
+
+     // Rest of the function.
+   }
+
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -67,6 +67,12 @@
 Improvements to clang-tidy
 --------------------------
 
+- New :doc:`cppcoreguidelines-init-variables
+  <clang-tidy/checks/cppcoreguidelines-init-variables>` check.
+
+  Checks whether there are local variables that are declared without
+  an initial value.
+
 - New :doc:`linuxkernel-must-use-errs
   <clang-tidy/checks/linuxkernel-must-use-errs>` check.
 
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.h
@@ -0,0 +1,34 @@
+//===--- 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"
+
+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)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_INITVARIABLESCHECK_H
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp
@@ -0,0 +1,81 @@
+//===--- 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 {
+
+void InitVariablesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      varDecl(unless(hasInitializer(anything())), unless(isInstantiated()))
+          .bind("vardecl"),
+      this);
+}
+
+void InitVariablesCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("vardecl");
+
+  const char *InitializationString = nullptr;
+
+  if (!MatchedDecl->isLocalVarDecl())
+    return;
+
+  // 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;
+  }
+
+  StringRef VarName = MatchedDecl->getName();
+  QualType TypePtr = MatchedDecl->getType();
+
+  if (TypePtr->isIntegerType()) {
+    InitializationString = " = 0";
+  } else if (TypePtr->isFloatingType()) {
+    InitializationString = " = (0.0/0.0)"; // NaN without needing #includes
+  } else if (TypePtr->isPointerType()) {
+    if (getLangOpts().CPlusPlus) {
+      InitializationString = " = nullptr";
+    } else {
+      InitializationString = " = NULL";
+    }
+  }
+
+  if (InitializationString) {
+    diag(MatchedDecl->getLocation(), "variable %0 is not initialized")
+        << MatchedDecl;
+    diag(MatchedDecl->getLocation(), "insert initial value",
+         DiagnosticIDs::Note)
+        << FixItHint::CreateInsertion(
+               MatchedDecl->getLocation().getLocWithOffset(VarName.size()),
+               InitializationString);
+  }
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ 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"
@@ -41,6 +42,8 @@
 class CppCoreGuidelinesModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<InitVariablesCheck>(
+        "cppcoreguidelines-init-variables");
     CheckFactories.registerCheck<modernize::AvoidCArraysCheck>(
         "cppcoreguidelines-avoid-c-arrays");
     CheckFactories.registerCheck<AvoidGotoCheck>(
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyCppCoreGuidelinesModule
   AvoidGotoCheck.cpp
   CppCoreGuidelinesTidyModule.cpp
+  InitVariablesCheck.cpp
   InterfacesGlobalInitCheck.cpp
   MacroUsageCheck.cpp
   NarrowingConversionsCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to