]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/Analyses/OSLog.h
MFC r345805: Unify SCSI_STATUS_BUSY retry handling with other cases.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / Analyses / 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
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       : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
76
77   OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
78       : TheKind(CountKind), ConstValue(value),
79         Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
80
81   unsigned char getDescriptorByte() const {
82     unsigned char result = 0;
83     if (getIsPrivate())
84       result |= IsPrivate;
85     if (getIsPublic())
86       result |= IsPublic;
87     result |= ((unsigned)getKind()) << 4;
88     return result;
89   }
90
91   unsigned char getSizeByte() const { return size().getQuantity(); }
92
93   Kind getKind() const { return TheKind; }
94   bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
95   bool getIsPublic() const { return (Flags & IsPublic) != 0; }
96
97   const Expr *getExpr() const { return TheExpr; }
98   CharUnits getConstValue() const { return ConstValue; }
99   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   CharUnits size() const {
109     CharUnits result;
110     result += CharUnits::fromQuantity(2); // summary byte, num-args byte
111     for (auto &item : Items) {
112       // descriptor byte, size byte
113       result += item.size() + CharUnits::fromQuantity(2);
114     }
115     return result;
116   }
117
118   bool hasPrivateItems() const {
119     return llvm::any_of(
120         Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
121   }
122
123   bool hasPublicItems() const {
124     return llvm::any_of(
125         Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
126   }
127
128   bool hasNonScalar() const {
129     return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
130       return Item.getKind() != OSLogBufferItem::ScalarKind;
131     });
132   }
133
134   unsigned char getSummaryByte() const {
135     unsigned char result = 0;
136     if (hasPrivateItems())
137       result |= HasPrivateItems;
138     if (hasNonScalar())
139       result |= HasNonScalarItems;
140     return result;
141   }
142
143   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