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 {

22 const Expr *E = nullptr;

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 (Data.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.