clang: lib/AST/OSLog.cpp Source File (original) (raw)
1
2
10#include
11
12using namespace clang;
13
16
17namespace {
18class OSLogFormatStringHandler
20private:
21 struct ArgData {
23 std::optionalOSLogBufferItem::Kind Kind;
24 std::optional Size;
25 std::optional<const Expr *> Count;
26 std::optional<const Expr *> Precision;
27 std::optional<const Expr *> FieldWidth;
28 unsigned char Flags = 0;
29 StringRef MaskType;
30 };
33
34 OSLogBufferItem::Kind
36 switch (K) {
38 return OSLogBufferItem::StringKind;
40 return OSLogBufferItem::WideStringKind;
42 return OSLogBufferItem::PointerKind;
44 return OSLogBufferItem::ObjCObjKind;
46 return OSLogBufferItem::ErrnoKind;
47 default:
48 return OSLogBufferItem::ScalarKind;
49 }
50 }
51 }
52
53public:
55 ArgsData.reserve(Args.size());
56 }
57
59 const char *StartSpecifier, unsigned SpecifierLen,
61 if (!FS.consumesDataArgument() &&
62 FS.getConversionSpecifier().getKind() !=
64 return true;
65
66 ArgsData.emplace_back();
67 unsigned ArgIndex = FS.getArgIndex();
68 if (ArgIndex < Args.size())
69 ArgsData.back().E = Args[ArgIndex];
70
71
72 ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
73 if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
74 !ArgsData.back().E) {
75
76 ArgsData.pop_back();
77 return false;
78 }
79
80 switch (FS.getConversionSpecifier().getKind()) {
83 auto &precision = FS.getPrecision();
84 switch (precision.getHowSpecified()) {
86 break;
88 ArgsData.back().Size = precision.getConstantAmount();
89 break;
91 ArgsData.back().Count = Args[precision.getArgIndex()];
92 break;
94 return false;
95 }
96 break;
97 }
99 auto &precision = FS.getPrecision();
100 switch (precision.getHowSpecified()) {
102 return false;
104 ArgsData.back().Size = precision.getConstantAmount();
105 break;
107 ArgsData.back().Count = Args[precision.getArgIndex()];
108 break;
110 return false;
111 }
112 break;
113 }
114 default:
115 if (FS.getPrecision().hasDataArgument()) {
116 ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
117 }
118 break;
119 }
120 if (FS.getFieldWidth().hasDataArgument()) {
121 ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
122 }
123
124 if (FS.isSensitive())
125 ArgsData.back().Flags |= OSLogBufferItem::IsSensitive;
126 else if (FS.isPrivate())
127 ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
128 else if (FS.isPublic())
129 ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
130
131 ArgsData.back().MaskType = FS.getMaskType();
132 return true;
133 }
134
136 Layout.Items.clear();
137 for (auto &Data : ArgsData) {
138 if (.MaskType.empty()) {
140 Layout.Items.emplace_back(OSLogBufferItem::MaskKind, nullptr,
141 Size, 0, Data.MaskType);
142 }
143
144 if (Data.FieldWidth) {
146 Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
147 Size, 0);
148 }
149 if (Data.Precision) {
151 Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
152 Size, 0);
153 }
154 if (Data.Count) {
155
157 Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
158 0);
159 }
160 if (Data.Size)
163 if (Data.Kind) {
165 if (*Data.Kind == OSLogBufferItem::ErrnoKind)
167 else
170 } else {
172 Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
174 }
175 }
176 }
177};
178}
179
183
184 const Expr *StringArg;
186 switch (E->getBuiltinCallee()) {
187 case Builtin::BI__builtin_os_log_format_buffer_size:
188 assert(E->getNumArgs() >= 1 &&
189 "__builtin_os_log_format_buffer_size takes at least 1 argument");
190 StringArg = E->getArg(0);
191 VarArgs = Args.slice(1);
192 break;
193 case Builtin::BI__builtin_os_log_format:
194 assert(E->getNumArgs() >= 2 &&
195 "__builtin_os_log_format takes at least 2 arguments");
196 StringArg = E->getArg(1);
197 VarArgs = Args.slice(2);
198 break;
199 default:
200 llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
201 }
202
206 OSLogFormatStringHandler H(VarArgs);
208 Ctx.getTargetInfo(), false);
209
210 H.computeLayout(Ctx, Layout);
211 return true;
212}
Defines enum values for all the target-independent builtin functions.
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const LangOptions & getLangOpts() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const TargetInfo & getTargetInfo() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
CharUnits - This is an opaque type for sizes expressed in character units.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
This represents one expression.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
StringLiteral - This represents a string literal expression, e.g.
StringRef getString() const
Exposes information about the current target.
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, const char *startSpecifier, unsigned specifierLen, const TargetInfo &Target)
An OSLogBufferItem represents a single item in the data written by a call to os_log() or os_trace().
SmallVector< OSLogBufferItem, 4 > Items
bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, OSLogBufferLayout &layout)
The JSON file list parser is used to communicate input to InstallAPI.