UninitializedValues.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines APIs for invoking and reported uninitialized values
  15. // warnings.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
  19. #define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
  20. #include "clang/Basic/LLVM.h"
  21. #include "llvm/ADT/SmallVector.h"
  22. namespace clang {
  23. class AnalysisDeclContext;
  24. class CFG;
  25. class DeclContext;
  26. class Expr;
  27. class Stmt;
  28. class VarDecl;
  29. /// A use of a variable, which might be uninitialized.
  30. class UninitUse {
  31. public:
  32. struct Branch {
  33. const Stmt *Terminator;
  34. unsigned Output;
  35. };
  36. private:
  37. /// The expression which uses this variable.
  38. const Expr *User;
  39. /// Is this use uninitialized whenever the function is called?
  40. bool UninitAfterCall = false;
  41. /// Is this use uninitialized whenever the variable declaration is reached?
  42. bool UninitAfterDecl = false;
  43. /// Does this use always see an uninitialized value?
  44. bool AlwaysUninit;
  45. /// This use is always uninitialized if it occurs after any of these branches
  46. /// is taken.
  47. SmallVector<Branch, 2> UninitBranches;
  48. public:
  49. UninitUse(const Expr *User, bool AlwaysUninit)
  50. : User(User), AlwaysUninit(AlwaysUninit) {}
  51. void addUninitBranch(Branch B) {
  52. UninitBranches.push_back(B);
  53. }
  54. void setUninitAfterCall() { UninitAfterCall = true; }
  55. void setUninitAfterDecl() { UninitAfterDecl = true; }
  56. /// Get the expression containing the uninitialized use.
  57. const Expr *getUser() const { return User; }
  58. /// The kind of uninitialized use.
  59. enum Kind {
  60. /// The use might be uninitialized.
  61. Maybe,
  62. /// The use is uninitialized whenever a certain branch is taken.
  63. Sometimes,
  64. /// The use is uninitialized the first time it is reached after we reach
  65. /// the variable's declaration.
  66. AfterDecl,
  67. /// The use is uninitialized the first time it is reached after the function
  68. /// is called.
  69. AfterCall,
  70. /// The use is always uninitialized.
  71. Always
  72. };
  73. /// Get the kind of uninitialized use.
  74. Kind getKind() const {
  75. return AlwaysUninit ? Always :
  76. UninitAfterCall ? AfterCall :
  77. UninitAfterDecl ? AfterDecl :
  78. !branch_empty() ? Sometimes : Maybe;
  79. }
  80. using branch_iterator = SmallVectorImpl<Branch>::const_iterator;
  81. /// Branches which inevitably result in the variable being used uninitialized.
  82. branch_iterator branch_begin() const { return UninitBranches.begin(); }
  83. branch_iterator branch_end() const { return UninitBranches.end(); }
  84. bool branch_empty() const { return UninitBranches.empty(); }
  85. };
  86. class UninitVariablesHandler {
  87. public:
  88. UninitVariablesHandler() = default;
  89. virtual ~UninitVariablesHandler();
  90. /// Called when the uninitialized variable is used at the given expression.
  91. virtual void handleUseOfUninitVariable(const VarDecl *vd,
  92. const UninitUse &use) {}
  93. /// Called when the uninitialized variable is used as const refernce argument.
  94. virtual void handleConstRefUseOfUninitVariable(const VarDecl *vd,
  95. const UninitUse &use) {}
  96. /// Called when the uninitialized variable analysis detects the
  97. /// idiom 'int x = x'. All other uses of 'x' within the initializer
  98. /// are handled by handleUseOfUninitVariable.
  99. virtual void handleSelfInit(const VarDecl *vd) {}
  100. };
  101. struct UninitVariablesAnalysisStats {
  102. unsigned NumVariablesAnalyzed;
  103. unsigned NumBlockVisits;
  104. };
  105. void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg,
  106. AnalysisDeclContext &ac,
  107. UninitVariablesHandler &handler,
  108. UninitVariablesAnalysisStats &stats);
  109. } // namespace clang
  110. #endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
  111. #ifdef __GNUC__
  112. #pragma GCC diagnostic pop
  113. #endif