Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
Line
Count
Source (jump to first uncovered line)
1
//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
//  This file defines several static functions for use in checkers.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
14
#include "clang/AST/Decl.h"
15
#include "clang/AST/Expr.h"
16
#include "clang/Lex/Preprocessor.h"
17
18
namespace clang {
19
20
namespace ento {
21
22
// Recursively find any substatements containing macros
23
44
bool containsMacro(const Stmt *S) {
24
44
  if (S->getBeginLoc().isMacroID())
25
2
    return true;
26
27
42
  if (S->getEndLoc().isMacroID())
28
0
    return true;
29
30
42
  for (const Stmt *Child : S->children())
31
31
    if (Child && containsMacro(Child))
32
0
      return true;
33
34
42
  return false;
35
42
}
36
37
// Recursively find any substatements containing enum constants
38
42
bool containsEnum(const Stmt *S) {
39
42
  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
40
41
42
  if (DR && 
isa<EnumConstantDecl>(DR->getDecl())10
)
42
0
    return true;
43
44
42
  for (const Stmt *Child : S->children())
45
31
    if (Child && containsEnum(Child))
46
0
      return true;
47
48
42
  return false;
49
42
}
50
51
// Recursively find any substatements containing static vars
52
42
bool containsStaticLocal(const Stmt *S) {
53
42
  const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
54
55
42
  if (DR)
56
10
    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
57
10
      if (VD->isStaticLocal())
58
1
        return true;
59
60
41
  for (const Stmt *Child : S->children())
61
31
    if (Child && containsStaticLocal(Child))
62
1
      return true;
63
64
40
  return false;
65
41
}
66
67
// Recursively find any substatements containing __builtin_offsetof
68
40
bool containsBuiltinOffsetOf(const Stmt *S) {
69
40
  if (isa<OffsetOfExpr>(S))
70
0
    return true;
71
72
40
  for (const Stmt *Child : S->children())
73
30
    if (Child && containsBuiltinOffsetOf(Child))
74
0
      return true;
75
76
40
  return false;
77
40
}
78
79
// Extract lhs and rhs from assignment statement
80
std::pair<const clang::VarDecl *, const clang::Expr *>
81
23
parseAssignment(const Stmt *S) {
82
23
  const VarDecl *VD = nullptr;
83
23
  const Expr *RHS = nullptr;
84
85
23
  if (auto Assign = dyn_cast_or_null<BinaryOperator>(S)) {
86
6
    if (Assign->isAssignmentOp()) {
87
      // Ordinary assignment
88
2
      RHS = Assign->getRHS();
89
2
      if (auto DE = dyn_cast_or_null<DeclRefExpr>(Assign->getLHS()))
90
2
        VD = dyn_cast_or_null<VarDecl>(DE->getDecl());
91
2
    }
92
17
  } else if (auto PD = dyn_cast_or_null<DeclStmt>(S)) {
93
    // Initialization
94
9
    assert(PD->isSingleDecl() && "We process decls one by one");
95
9
    VD = cast<VarDecl>(PD->getSingleDecl());
96
9
    RHS = VD->getAnyInitializer();
97
9
  }
98
99
23
  return std::make_pair(VD, RHS);
100
23
}
101
102
5.26k
Nullability getNullabilityAnnotation(QualType Type) {
103
5.26k
  const auto *AttrType = Type->getAs<AttributedType>();
104
5.26k
  if (!AttrType)
105
3.18k
    return Nullability::Unspecified;
106
2.08k
  if (AttrType->getAttrKind() == attr::TypeNullable)
107
631
    return Nullability::Nullable;
108
1.45k
  else if (AttrType->getAttrKind() == attr::TypeNonNull)
109
1.45k
    return Nullability::Nonnull;
110
0
  return Nullability::Unspecified;
111
0
}
112
113
llvm::Optional<int> tryExpandAsInteger(StringRef Macro,
114
92
                                       const Preprocessor &PP) {
115
92
  const auto *MacroII = PP.getIdentifierInfo(Macro);
116
92
  if (!MacroII)
117
0
    return llvm::None;
118
92
  const MacroInfo *MI = PP.getMacroInfo(MacroII);
119
92
  if (!MI)
120
69
    return llvm::None;
121
122
  // Filter out parens.
123
23
  std::vector<Token> FilteredTokens;
124
23
  FilteredTokens.reserve(MI->tokens().size());
125
23
  for (auto &T : MI->tokens())
126
69
    if (!T.isOneOf(tok::l_paren, tok::r_paren))
127
47
      FilteredTokens.push_back(T);
128
129
  // Parse an integer at the end of the macro definition.
130
23
  const Token &T = FilteredTokens.back();
131
  // FIXME: EOF macro token coming from a PCH file on macOS while marked as
132
  //        literal, doesn't contain any literal data
133
23
  if (!T.isLiteral() || !T.getLiteralData())
134
6
    return llvm::None;
135
17
  StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
136
17
  llvm::APInt IntValue;
137
17
  constexpr unsigned AutoSenseRadix = 0;
138
17
  if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))
139
0
    return llvm::None;
140
141
  // Parse an optional minus sign.
142
17
  size_t Size = FilteredTokens.size();
143
17
  if (Size >= 2) {
144
17
    if (FilteredTokens[Size - 2].is(tok::minus))
145
16
      IntValue = -IntValue;
146
17
  }
147
148
17
  return IntValue.getSExtValue();
149
17
}
150
151
} // namespace ento
152
} // namespace clang