Coverage Report

Created: 2020-02-15 09:57

/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
42
27
42
  if (S->getEndLoc().isMacroID())
28
0
    return true;
29
42
30
42
  for (const Stmt *Child : S->children())
31
31
    if (Child && containsMacro(Child))
32
0
      return true;
33
42
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
42
41
42
  if (DR && 
isa<EnumConstantDecl>(DR->getDecl())10
)
42
0
    return true;
43
42
44
42
  for (const Stmt *Child : S->children())
45
31
    if (Child && containsEnum(Child))
46
0
      return true;
47
42
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
42
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
41
60
41
  for (const Stmt *Child : S->children())
61
31
    if (Child && containsStaticLocal(Child))
62
1
      return true;
63
41
64
41
  
return false40
;
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
40
72
40
  for (const Stmt *Child : S->children())
73
30
    if (Child && containsBuiltinOffsetOf(Child))
74
0
      return true;
75
40
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
23
85
23
  if (auto Assign = dyn_cast_or_null<BinaryOperator>(S)) {
86
6
    if (Assign->isAssignmentOp()) {
87
2
      // 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
9
    // 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
23
99
23
  return std::make_pair(VD, RHS);
100
23
}
101
102
4.10k
Nullability getNullabilityAnnotation(QualType Type) {
103
4.10k
  const auto *AttrType = Type->getAs<AttributedType>();
104
4.10k
  if (!AttrType)
105
2.21k
    return Nullability::Unspecified;
106
1.88k
  if (AttrType->getAttrKind() == attr::TypeNullable)
107
550
    return Nullability::Nullable;
108
1.33k
  else if (AttrType->getAttrKind() == attr::TypeNonNull)
109
1.33k
    return Nullability::Nonnull;
110
0
  return Nullability::Unspecified;
111
0
}
112
113
llvm::Optional<int> tryExpandAsInteger(StringRef Macro,
114
19
                                       const Preprocessor &PP) {
115
19
  const auto *MacroII = PP.getIdentifierInfo(Macro);
116
19
  if (!MacroII)
117
0
    return llvm::None;
118
19
  const MacroInfo *MI = PP.getMacroInfo(MacroII);
119
19
  if (!MI)
120
8
    return llvm::None;
121
11
122
11
  // Filter out parens.
123
11
  std::vector<Token> FilteredTokens;
124
11
  FilteredTokens.reserve(MI->tokens().size());
125
11
  for (auto &T : MI->tokens())
126
34
    if (!T.isOneOf(tok::l_paren, tok::r_paren))
127
22
      FilteredTokens.push_back(T);
128
11
129
11
  if (FilteredTokens.size() > 2)
130
0
    return llvm::None;
131
11
132
11
  // Parse an integer at the end of the macro definition.
133
11
  const Token &T = FilteredTokens.back();
134
11
  if (!T.isLiteral())
135
0
    return llvm::None;
136
11
  StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
137
11
  llvm::APInt IntValue;
138
11
  constexpr unsigned AutoSenseRadix = 0;
139
11
  if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))
140
0
    return llvm::None;
141
11
142
11
  // Parse an optional minus sign.
143
11
  if (FilteredTokens.size() == 2) {
144
11
    if (FilteredTokens.front().is(tok::minus))
145
11
      IntValue = -IntValue;
146
0
    else
147
0
      return llvm::None;
148
11
  }
149
11
150
11
  return IntValue.getSExtValue();
151
11
}
152
153
} // namespace ento
154
} // namespace clang