Coverage Report

Created: 2018-11-02 07:17

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Analysis/Analyses/OSLog.h
Line
Count
Source (jump to first uncovered line)
1
//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines APIs for determining the layout of the data buffer for
11
// os_log() and os_trace().
12
//
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
16
#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
17
18
#include "clang/AST/ASTContext.h"
19
#include "clang/AST/Expr.h"
20
21
namespace clang {
22
namespace analyze_os_log {
23
24
/// An OSLogBufferItem represents a single item in the data written by a call
25
/// to os_log() or os_trace().
26
class OSLogBufferItem {
27
public:
28
  enum Kind {
29
    // The item is a scalar (int, float, raw pointer, etc.). No further copying
30
    // is required. This is the only kind allowed by os_trace().
31
    ScalarKind = 0,
32
33
    // The item is a count, which describes the length of the following item to
34
    // be copied. A count may only be followed by an item of kind StringKind,
35
    // WideStringKind, or PointerKind.
36
    CountKind,
37
38
    // The item is a pointer to a C string. If preceded by a count 'n',
39
    // os_log() will copy at most 'n' bytes from the pointer.
40
    StringKind,
41
42
    // The item is a pointer to a block of raw data. This item must be preceded
43
    // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
44
    PointerKind,
45
46
    // The item is a pointer to an Objective-C object. os_log() may retain the
47
    // object for later processing.
48
    ObjCObjKind,
49
50
    // The item is a pointer to wide-char string.
51
    WideStringKind,
52
53
    // The item is corresponding to the '%m' format specifier, no value is
54
    // populated in the buffer and the runtime is loading the errno value.
55
    ErrnoKind
56
  };
57
58
  enum {
59
    // The item is marked "private" in the format string.
60
    IsPrivate = 0x1,
61
62
    // The item is marked "public" in the format string.
63
    IsPublic = 0x2
64
  };
65
66
private:
67
  Kind TheKind = ScalarKind;
68
  const Expr *TheExpr = nullptr;
69
  CharUnits ConstValue;
70
  CharUnits Size; // size of the data, not including the header bytes
71
  unsigned Flags = 0;
72
73
public:
74
  OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
75
66
      : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
76
77
  OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
78
      : TheKind(CountKind), ConstValue(value),
79
4
        Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
80
81
84
  unsigned char getDescriptorByte() const {
82
84
    unsigned char result = 0;
83
84
    if (getIsPrivate())
84
12
      result |= IsPrivate;
85
84
    if (getIsPublic())
86
8
      result |= IsPublic;
87
84
    result |= ((unsigned)getKind()) << 4;
88
84
    return result;
89
84
  }
90
91
168
  unsigned char getSizeByte() const { return size().getQuantity(); }
92
93
152
  Kind getKind() const { return TheKind; }
94
164
  bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
95
84
  bool getIsPublic() const { return (Flags & IsPublic) != 0; }
96
97
44
  const Expr *getExpr() const { return TheExpr; }
98
2
  CharUnits getConstValue() const { return ConstValue; }
99
230
  CharUnits size() const { return Size; }
100
};
101
102
class OSLogBufferLayout {
103
public:
104
  SmallVector<OSLogBufferItem, 4> Items;
105
106
  enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
107
108
147
  CharUnits size() const {
109
147
    CharUnits result;
110
147
    result += CharUnits::fromQuantity(2); // summary byte, num-args byte
111
147
    for (auto &item : Items) {
112
24
      // descriptor byte, size byte
113
24
      result += item.size() + CharUnits::fromQuantity(2);
114
24
    }
115
147
    return result;
116
147
  }
117
118
216
  bool hasPrivateItems() const {
119
216
    return llvm::any_of(
120
216
        Items, [](const OSLogBufferItem &Item) 
{ return Item.getIsPrivate(); }80
);
121
216
  }
122
123
0
  bool hasPublicItems() const {
124
0
    return llvm::any_of(
125
0
        Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
126
0
  }
127
128
216
  bool hasNonScalar() const {
129
216
    return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
130
68
      return Item.getKind() != OSLogBufferItem::ScalarKind;
131
68
    });
132
216
  }
133
134
216
  unsigned char getSummaryByte() const {
135
216
    unsigned char result = 0;
136
216
    if (hasPrivateItems())
137
8
      result |= HasPrivateItems;
138
216
    if (hasNonScalar())
139
40
      result |= HasNonScalarItems;
140
216
    return result;
141
216
  }
142
143
216
  unsigned char getNumArgsByte() const { return Items.size(); }
144
};
145
146
// Given a call 'E' to one of the builtins __builtin_os_log_format() or
147
// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
148
// the call will write into and store it in 'layout'. Returns 'false' if there
149
// was some error encountered while computing the layout, and 'true' otherwise.
150
bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
151
                              OSLogBufferLayout &layout);
152
153
} // namespace analyze_os_log
154
} // namespace clang
155
#endif