]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/OSLog.h
MFC r345805: Unify SCSI_STATUS_BUSY retry handling with other cases.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / AST / OSLog.h
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     // The item is a mask type.
58     MaskKind
59   };
60
61   enum {
62     // The item is marked "private" in the format string.
63     IsPrivate = 0x1,
64
65     // The item is marked "public" in the format string.
66     IsPublic = 0x2,
67
68     // The item is marked "sensitive" in the format string.
69     IsSensitive = 0x4 | IsPrivate
70   };
71
72 private:
73   Kind TheKind = ScalarKind;
74   const Expr *TheExpr = nullptr;
75   CharUnits ConstValue;
76   CharUnits Size; // size of the data, not including the header bytes
77   unsigned Flags = 0;
78   StringRef MaskType;
79
80 public:
81   OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags,
82                   StringRef maskType = StringRef())
83       : TheKind(kind), TheExpr(expr), Size(size), Flags(flags),
84         MaskType(maskType) {
85     assert(((Flags == 0) || (Flags == IsPrivate) || (Flags == IsPublic) ||
86             (Flags == IsSensitive)) &&
87            "unexpected privacy flag");
88   }
89
90   OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
91       : TheKind(CountKind), ConstValue(value),
92         Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
93
94   unsigned char getDescriptorByte() const {
95     unsigned char result = Flags;
96     result |= ((unsigned)getKind()) << 4;
97     return result;
98   }
99
100   unsigned char getSizeByte() const { return size().getQuantity(); }
101
102   Kind getKind() const { return TheKind; }
103   bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
104
105   const Expr *getExpr() const { return TheExpr; }
106   CharUnits getConstValue() const { return ConstValue; }
107   CharUnits size() const { return Size; }
108
109   StringRef getMaskType() const { return MaskType; }
110 };
111
112 class OSLogBufferLayout {
113 public:
114   SmallVector<OSLogBufferItem, 4> Items;
115
116   enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
117
118   CharUnits size() const {
119     CharUnits result;
120     result += CharUnits::fromQuantity(2); // summary byte, num-args byte
121     for (auto &item : Items) {
122       // descriptor byte, size byte
123       result += item.size() + CharUnits::fromQuantity(2);
124     }
125     return result;
126   }
127
128   bool hasPrivateItems() const {
129     return llvm::any_of(
130         Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
131   }
132
133   bool hasNonScalarOrMask() const {
134     return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
135       return Item.getKind() != OSLogBufferItem::ScalarKind ||
136              !Item.getMaskType().empty();
137     });
138   }
139
140   unsigned char getSummaryByte() const {
141     unsigned char result = 0;
142     if (hasPrivateItems())
143       result |= HasPrivateItems;
144     if (hasNonScalarOrMask())
145       result |= HasNonScalarItems;
146     return result;
147   }
148
149   unsigned char getNumArgsByte() const { return Items.size(); }
150 };
151
152 // Given a call 'E' to one of the builtins __builtin_os_log_format() or
153 // __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
154 // the call will write into and store it in 'layout'. Returns 'false' if there
155 // was some error encountered while computing the layout, and 'true' otherwise.
156 bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
157                               OSLogBufferLayout &layout);
158
159 } // namespace analyze_os_log
160 } // namespace clang
161 #endif