summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMehdi Amini <mehdi.amini@apple.com>2016-12-15 04:02:31 +0000
committerMehdi Amini <mehdi.amini@apple.com>2016-12-15 04:02:31 +0000
commitab11d83048d0467e39bd5ef2b6f43f6f1686c45e (patch)
treeb6387344c9ec148e29d47eb4fe5e05104e51306b
parent6ee0b4e9f543fa108b47d3ae7c030d835cacd2c1 (diff)
downloadbcm5719-llvm-ab11d83048d0467e39bd5ef2b6f43f6f1686c45e.tar.gz
bcm5719-llvm-ab11d83048d0467e39bd5ef2b6f43f6f1686c45e.zip
Fix os_log formating with arbitrary precision and field width
llvm-svn: 289761
-rw-r--r--clang/lib/Analysis/OSLog.cpp29
-rw-r--r--clang/test/CodeGen/builtins.c49
2 files changed, 76 insertions, 2 deletions
diff --git a/clang/lib/Analysis/OSLog.cpp b/clang/lib/Analysis/OSLog.cpp
index 04183883990..3e13a153c65 100644
--- a/clang/lib/Analysis/OSLog.cpp
+++ b/clang/lib/Analysis/OSLog.cpp
@@ -22,6 +22,9 @@ private:
const Expr *E = nullptr;
Optional<OSLogBufferItem::Kind> Kind;
Optional<unsigned> Size;
+ Optional<const Expr *> Count;
+ Optional<const Expr *> Precision;
+ Optional<const Expr *> FieldWidth;
unsigned char Flags = 0;
};
SmallVector<ArgData, 4> ArgsData;
@@ -84,7 +87,7 @@ public:
ArgsData.back().Size = precision.getConstantAmount();
break;
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
- ArgsData.back().Kind = OSLogBufferItem::CountKind;
+ ArgsData.back().Count = Args[precision.getArgIndex()];
break;
case clang::analyze_format_string::OptionalAmount::Invalid:
return false;
@@ -100,7 +103,7 @@ public:
ArgsData.back().Size = precision.getConstantAmount();
break;
case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
- ArgsData.back().Kind = OSLogBufferItem::CountKind;
+ ArgsData.back().Count = Args[precision.getArgIndex()];
break;
case clang::analyze_format_string::OptionalAmount::Invalid:
return false;
@@ -108,8 +111,14 @@ public:
break;
}
default:
+ if (FS.getPrecision().hasDataArgument()) {
+ ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
+ }
break;
}
+ if (FS.getFieldWidth().hasDataArgument()) {
+ ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
+ }
if (FS.isPrivate()) {
ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
@@ -123,6 +132,22 @@ public:
void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
Layout.Items.clear();
for (auto &Data : ArgsData) {
+ if (Data.FieldWidth) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
+ Size, 0);
+ }
+ if (Data.Precision) {
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
+ Size, 0);
+ }
+ if (Data.Count) {
+ // "%.*P" has an extra "count" that we insert before the argument.
+ CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
+ Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
+ 0);
+ }
if (Data.Size)
Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
Data.Flags);
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index c604ee54e29..a0f846b14f1 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -489,6 +489,55 @@ void test_builtin_os_log_wide(void *buf, const char *data, wchar_t *str) {
__builtin_os_log_format(buf, "%S", str);
}
+// CHECK-LABEL: define void @test_builtin_os_log_precision_width
+// CHECK: (i8* [[BUF:%.*]], i8* [[DATA:%.*]], i32 [[PRECISION:%.*]], i32 [[WIDTH:%.*]])
+void test_builtin_os_log_precision_width(void *buf, const char *data,
+ int precision, int width) {
+ volatile int len;
+ // CHECK: store i8* [[BUF]], i8** [[BUF_ADDR:%.*]], align 8
+ // CHECK: store i8* [[DATA]], i8** [[DATA_ADDR:%.*]], align 8
+ // CHECK: store i32 [[PRECISION]], i32* [[PRECISION_ADDR:%.*]], align 4
+ // CHECK: store i32 [[WIDTH]], i32* [[WIDTH_ADDR:%.*]], align 4
+
+ // CHECK: store volatile i32 24,
+ len = __builtin_os_log_format_buffer_size("Hello %*.*s World", precision, width, data);
+
+ // CHECK: [[BUF2:%.*]] = load i8*, i8** [[BUF_ADDR]]
+ // CHECK: [[SUMMARY:%.*]] = getelementptr i8, i8* [[BUF2]], i64 0
+ // CHECK: store i8 2, i8* [[SUMMARY]]
+ // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* [[BUF2]], i64 1
+ // CHECK: store i8 3, i8* [[NUM_ARGS]]
+
+ // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 2
+ // CHECK: store i8 0, i8* [[ARG1_DESC]]
+ // CHECK: [[ARG1_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 3
+ // CHECK: store i8 4, i8* [[ARG1_SIZE]]
+ // CHECK: [[ARG1:%.*]] = getelementptr i8, i8* [[BUF2]], i64 4
+ // CHECK: [[ARG1_INT:%.*]] = bitcast i8* [[ARG1]] to i32*
+ // CHECK: [[ARG1_VAL:%.*]] = load i32, i32* [[PRECISION_ADDR]]
+ // CHECK: store i32 [[ARG1_VAL]], i32* [[ARG1_INT]]
+
+ // CHECK: [[ARG2_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 8
+ // CHECK: store i8 16, i8* [[ARG2_DESC]]
+ // CHECK: [[ARG2_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 9
+ // CHECK: store i8 4, i8* [[ARG2_SIZE]]
+ // CHECK: [[ARG2:%.*]] = getelementptr i8, i8* [[BUF2]], i64 10
+ // CHECK: [[ARG2_INT:%.*]] = bitcast i8* [[ARG2]] to i32*
+ // CHECK: [[ARG2_VAL:%.*]] = load i32, i32* [[WIDTH_ADDR]]
+ // CHECK: store i32 [[ARG2_VAL]], i32* [[ARG2_INT]]
+
+ // CHECK: [[ARG3_DESC:%.*]] = getelementptr i8, i8* [[BUF2]], i64 14
+ // CHECK: store i8 32, i8* [[ARG3_DESC]]
+ // CHECK: [[ARG3_SIZE:%.*]] = getelementptr i8, i8* [[BUF2]], i64 15
+ // CHECK: store i8 8, i8* [[ARG3_SIZE]]
+ // CHECK: [[ARG3:%.*]] = getelementptr i8, i8* [[BUF2]], i64 16
+ // CHECK: [[ARG3_PTR:%.*]] = bitcast i8* [[ARG3]] to i8**
+ // CHECK: [[DATA2:%.*]] = load i8*, i8** [[DATA_ADDR]]
+ // CHECK: store i8* [[DATA2]], i8** [[ARG3_PTR]]
+
+ __builtin_os_log_format(buf, "Hello %*.*s World", precision, width, data);
+}
+
// CHECK-LABEL: define void @test_builtin_os_log_percent
// CHECK: (i8* [[BUF:%.*]], i8* [[DATA1:%.*]], i8* [[DATA2:%.*]])
// Check that the %% which does not consume any argument is correctly handled
OpenPOWER on IntegriCloud