[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-25 Thread Benjamin Kramer via cfe-commits
bkramer added a comment.

CodeGen depending on Analysis is fine with me. Any clang tool that builds an 
AST will have Analysis linked in anyways so there's virtually no cost to it.


Repository:
  rL LLVM

https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-24 Thread Mehdi AMINI via cfe-commits
mehdi_amini added a comment.

@bkramer : is it an OK dependency to add from a clang point of view? Or should 
I refactor the patch to avoid introducing it?


Repository:
  rL LLVM

https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-24 Thread Artem Belevich via cfe-commits
tra added a comment.

CodeGen's CMakeLists.txt needs to be updated to link with clangAnalysis now, 
otherwise it breaks builds that use shared libraries.
Fixed in r285037.

  diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
  index f5d5d69..9cf34f6 100644
  --- a/lib/CodeGen/CMakeLists.txt
  +++ b/lib/CodeGen/CMakeLists.txt
  @@ -88,6 +88,7 @@ add_clang_library(clangCodeGen
   
 LINK_LIBS
 clangAST
  +  clangAnalysis
 clangBasic
 clangFrontend
 clangLex


Repository:
  rL LLVM

https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-24 Thread Mehdi AMINI via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL284990: Add support for 
__builtin_os_log_format[_buffer_size] (authored by mehdi_amini).

Changed prior to commit:
  https://reviews.llvm.org/D25888?vs=75552=75608#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D25888

Files:
  cfe/trunk/include/clang/Analysis/Analyses/FormatString.h
  cfe/trunk/include/clang/Analysis/Analyses/OSLog.h
  cfe/trunk/include/clang/Basic/Builtins.def
  cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
  cfe/trunk/include/clang/Sema/Sema.h
  cfe/trunk/lib/Analysis/CMakeLists.txt
  cfe/trunk/lib/Analysis/FormatString.cpp
  cfe/trunk/lib/Analysis/OSLog.cpp
  cfe/trunk/lib/Analysis/PrintfFormatString.cpp
  cfe/trunk/lib/CodeGen/CGBuiltin.cpp
  cfe/trunk/lib/Sema/SemaChecking.cpp
  cfe/trunk/lib/Sema/SemaDeclAttr.cpp
  cfe/trunk/test/CodeGen/builtins.c
  cfe/trunk/test/CodeGenObjC/os_log.m
  cfe/trunk/test/SemaObjC/format-strings-oslog.m

Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
===
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp
@@ -2804,20 +2804,21 @@
 /// types.
 static FormatAttrKind getFormatAttrKind(StringRef Format) {
   return llvm::StringSwitch(Format)
-// Check for formats that get handled specially.
-.Case("NSString", NSStringFormat)
-.Case("CFString", CFStringFormat)
-.Case("strftime", StrftimeFormat)
-
-// Otherwise, check for supported formats.
-.Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
-.Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
-.Case("kprintf", SupportedFormat) // OpenBSD.
-.Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
-.Case("os_trace", SupportedFormat)
+  // Check for formats that get handled specially.
+  .Case("NSString", NSStringFormat)
+  .Case("CFString", CFStringFormat)
+  .Case("strftime", StrftimeFormat)
+
+  // Otherwise, check for supported formats.
+  .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat)
+  .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat)
+  .Case("kprintf", SupportedFormat) // OpenBSD.
+  .Case("freebsd_kprintf", SupportedFormat) // FreeBSD.
+  .Case("os_trace", SupportedFormat)
+  .Case("os_log", SupportedFormat)
 
-.Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
-.Default(InvalidFormat);
+  .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat)
+  .Default(InvalidFormat);
 }
 
 /// Handle __attribute__((init_priority(priority))) attributes based on
Index: cfe/trunk/lib/Sema/SemaChecking.cpp
===
--- cfe/trunk/lib/Sema/SemaChecking.cpp
+++ cfe/trunk/lib/Sema/SemaChecking.cpp
@@ -1065,6 +1065,12 @@
   case Builtin::BIget_kernel_preferred_work_group_size_multiple:
 if (SemaOpenCLBuiltinKernelWorkGroupSize(*this, TheCall))
   return ExprError();
+  case Builtin::BI__builtin_os_log_format:
+  case Builtin::BI__builtin_os_log_format_buffer_size:
+if (SemaBuiltinOSLogFormat(TheCall)) {
+  return ExprError();
+}
+break;
   }
 
   // Since the target specific builtins for each arch overlap, only check those
@@ -3478,6 +3484,31 @@
   return false;
 }
 
+/// CheckObjCString - Checks that the format string argument to the os_log()
+/// and os_trace() functions is correct, and converts it to const char *.
+ExprResult Sema::CheckOSLogFormatStringArg(Expr *Arg) {
+  Arg = Arg->IgnoreParenCasts();
+  auto *Literal = dyn_cast(Arg);
+  if (!Literal) {
+if (auto *ObjcLiteral = dyn_cast(Arg)) {
+  Literal = ObjcLiteral->getString();
+}
+  }
+
+  if (!Literal || (!Literal->isAscii() && !Literal->isUTF8())) {
+return ExprError(
+Diag(Arg->getLocStart(), diag::err_os_log_format_not_string_constant)
+<< Arg->getSourceRange());
+  }
+
+  ExprResult Result(Literal);
+  QualType ResultTy = Context.getPointerType(Context.CharTy.withConst());
+  InitializedEntity Entity =
+  InitializedEntity::InitializeParameter(Context, ResultTy, false);
+  Result = PerformCopyInitialization(Entity, SourceLocation(), Result);
+  return Result;
+}
+
 /// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start'
 /// for validity.  Emit an error and return true on failure; return false
 /// on success.
@@ -3939,6 +3970,86 @@
   return false;
 }
 
+bool Sema::SemaBuiltinOSLogFormat(CallExpr *TheCall) {
+  unsigned BuiltinID =
+  cast(TheCall->getCalleeDecl())->getBuiltinID();
+  bool IsSizeCall = BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
+
+  unsigned NumArgs = TheCall->getNumArgs();
+  unsigned NumRequiredArgs = IsSizeCall ? 1 : 2;
+  if (NumArgs < NumRequiredArgs) {
+return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args)
+   << 0 /* function call */ << NumRequiredArgs << 

[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-24 Thread Mehdi AMINI via cfe-commits
mehdi_amini added a comment.

Thanks!
For the API part, this is already in production ( 
https://github.com/apple/swift-clang/blob/stable/lib/CodeGen/CGBuiltin.cpp#L2071
 ), so it should be OK!


https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-24 Thread Benjamin Kramer via cfe-commits
bkramer accepted this revision.
bkramer added a comment.
This revision is now accepted and ready to land.

This looks good from a Clang perspective. You also might want to get review 
from someone who knows how the os_log API is supposed to work, as I can't 
comment on that.




Comment at: clang/test/CodeGenObjC/os_log.m:13
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log

This is only ever compile for x86 (you have a triple in the command line). Just 
drop the #ifdef.


https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-23 Thread Mehdi AMINI via cfe-commits
mehdi_amini updated this revision to Diff 75552.
mehdi_amini added a comment.

Use a separate enum to described OSLogBufferLayout header flags


https://reviews.llvm.org/D25888

Files:
  clang/include/clang/Analysis/Analyses/FormatString.h
  clang/include/clang/Analysis/Analyses/OSLog.h
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Analysis/CMakeLists.txt
  clang/lib/Analysis/FormatString.cpp
  clang/lib/Analysis/OSLog.cpp
  clang/lib/Analysis/PrintfFormatString.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGenObjC/os_log.m
  clang/test/SemaObjC/format-strings-oslog.m

Index: clang/test/SemaObjC/format-strings-oslog.m
===
--- /dev/null
+++ clang/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include 
+#include 
+#define __need_wint_t
+#include  // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+  __builtin_os_log_format(buf, "");
+  __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, "%d", i);
+  __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, "%.10P", p);
+  __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, "%.*P", i, p);
+  __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+  __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+  __builtin_os_log_format(buf, pc);   // expected-error {{os_log() format argument is not a string constant}}
+
+  printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+  __builtin_os_log_format(buf, "%{private}s", pc);
+
+  // 
+  __builtin_os_log_format_buffer_size("no-args");
+  __builtin_os_log_format(buf, "%s", "hi");
+
+  // 
+  wchar_t wc = 'a';
+  __builtin_os_log_format(buf, "%C", wc);
+  printf("%C", wc);
+  wchar_t wcs[] = {'a', 0};
+  __builtin_os_log_format(buf, "%S", wcs);
+  printf("%S", wcs);
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+  __builtin_os_log_format(buf, @"");
+  __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, @"%d", i);
+  __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, @"%.10P", p);
+  __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, @"%.*P", i, p);
+  __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+  __builtin_os_log_format(buf, @"%{private}s", pc);
+  __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+  MyOSLog("%s\n", "Hello");
+  MyOSLog("%d");// expected-warning {{more '%' conversions than data arguments}}
+  MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
Index: clang/test/CodeGenObjC/os_log.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log
+void *test_builtin_os_log(void *buf) {
+  return __builtin_os_log_format(buf, "capabilities: %@", GenString());
+
+  // CHECK: store i8 2, i8*
+  // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1
+  // CHECK: store i8 1, i8* [[NUM_ARGS]]
+  //
+  // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2
+  // CHECK: store i8 64, i8* 

[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-22 Thread Mehdi AMINI via cfe-commits
mehdi_amini updated this revision to Diff 75536.
mehdi_amini added a comment.

typo + clang-format


https://reviews.llvm.org/D25888

Files:
  clang/include/clang/Analysis/Analyses/FormatString.h
  clang/include/clang/Analysis/Analyses/OSLog.h
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Analysis/CMakeLists.txt
  clang/lib/Analysis/FormatString.cpp
  clang/lib/Analysis/OSLog.cpp
  clang/lib/Analysis/PrintfFormatString.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGenObjC/os_log.m
  clang/test/SemaObjC/format-strings-oslog.m

Index: clang/test/SemaObjC/format-strings-oslog.m
===
--- /dev/null
+++ clang/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include 
+#include 
+#define __need_wint_t
+#include  // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+  __builtin_os_log_format(buf, "");
+  __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, "%d", i);
+  __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, "%.10P", p);
+  __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, "%.*P", i, p);
+  __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+  __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+  __builtin_os_log_format(buf, pc);   // expected-error {{os_log() format argument is not a string constant}}
+
+  printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+  __builtin_os_log_format(buf, "%{private}s", pc);
+
+  // 
+  __builtin_os_log_format_buffer_size("no-args");
+  __builtin_os_log_format(buf, "%s", "hi");
+
+  // 
+  wchar_t wc = 'a';
+  __builtin_os_log_format(buf, "%C", wc);
+  printf("%C", wc);
+  wchar_t wcs[] = {'a', 0};
+  __builtin_os_log_format(buf, "%S", wcs);
+  printf("%S", wcs);
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+  __builtin_os_log_format(buf, @"");
+  __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, @"%d", i);
+  __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, @"%.10P", p);
+  __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, @"%.*P", i, p);
+  __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+  __builtin_os_log_format(buf, @"%{private}s", pc);
+  __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+  MyOSLog("%s\n", "Hello");
+  MyOSLog("%d");// expected-warning {{more '%' conversions than data arguments}}
+  MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
Index: clang/test/CodeGenObjC/os_log.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log
+void *test_builtin_os_log(void *buf) {
+  return __builtin_os_log_format(buf, "capabilities: %@", GenString());
+
+  // CHECK: store i8 2, i8*
+  // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1
+  // CHECK: store i8 1, i8* [[NUM_ARGS]]
+  //
+  // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2
+  // CHECK: store i8 64, i8* [[ARG1_DESC]]
+  // CHECK: [[ARG1_SIZE:%.*]] = 

[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-22 Thread Mehdi AMINI via cfe-commits
mehdi_amini updated this revision to Diff 75534.
mehdi_amini added a comment.

std::any_of -> llvm::any_of and more magic number replaced with enum


https://reviews.llvm.org/D25888

Files:
  clang/include/clang/Analysis/Analyses/FormatString.h
  clang/include/clang/Analysis/Analyses/OSLog.h
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Analysis/CMakeLists.txt
  clang/lib/Analysis/FormatString.cpp
  clang/lib/Analysis/OSLog.cpp
  clang/lib/Analysis/PrintfFormatString.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGenObjC/os_log.m
  clang/test/SemaObjC/format-strings-oslog.m

Index: clang/test/SemaObjC/format-strings-oslog.m
===
--- /dev/null
+++ clang/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include 
+#include 
+#define __need_wint_t
+#include  // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+  __builtin_os_log_format(buf, "");
+  __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, "%d", i);
+  __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, "%.10P", p);
+  __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, "%.*P", i, p);
+  __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+  __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+  __builtin_os_log_format(buf, pc);   // expected-error {{os_log() format argument is not a string constant}}
+
+  printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+  __builtin_os_log_format(buf, "%{private}s", pc);
+
+  // 
+  __builtin_os_log_format_buffer_size("no-args");
+  __builtin_os_log_format(buf, "%s", "hi");
+
+  // 
+  wchar_t wc = 'a';
+  __builtin_os_log_format(buf, "%C", wc);
+  printf("%C", wc);
+  wchar_t wcs[] = {'a', 0};
+  __builtin_os_log_format(buf, "%S", wcs);
+  printf("%S", wcs);
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+  __builtin_os_log_format(buf, @"");
+  __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, @"%d", i);
+  __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, @"%.10P", p);
+  __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, @"%.*P", i, p);
+  __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+  __builtin_os_log_format(buf, @"%{private}s", pc);
+  __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+  MyOSLog("%s\n", "Hello");
+  MyOSLog("%d");// expected-warning {{more '%' conversions than data arguments}}
+  MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
Index: clang/test/CodeGenObjC/os_log.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log
+void *test_builtin_os_log(void *buf) {
+  return __builtin_os_log_format(buf, "capabilities: %@", GenString());
+
+  // CHECK: store i8 2, i8*
+  // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1
+  // CHECK: store i8 1, i8* [[NUM_ARGS]]
+  //
+  // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2
+  // CHECK: store i8 64, i8* 

[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-22 Thread David Majnemer via cfe-commits
majnemer added inline comments.



Comment at: clang/include/clang/Analysis/Analyses/OSLog.h:117-129
+return std::any_of(
+Items.begin(), Items.end(),
+[](const OSLogBufferItem ) { return item.getIsPrivate(); });
+  }
+
+  bool getHasPublicItems() const {
+return std::any_of(

`llvm::any_of`



Comment at: clang/include/clang/Analysis/Analyses/OSLog.h:137-140
+if (getHasPrivateItems())
+  result |= 0x01;
+if (getHasNonScalar())
+  result |= 0x02;

Magic numbers.


https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-21 Thread Mehdi AMINI via cfe-commits
mehdi_amini updated this revision to Diff 75524.
mehdi_amini added a comment.

Address David's feedback. Thanks David!


https://reviews.llvm.org/D25888

Files:
  clang/include/clang/Analysis/Analyses/FormatString.h
  clang/include/clang/Analysis/Analyses/OSLog.h
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Analysis/CMakeLists.txt
  clang/lib/Analysis/FormatString.cpp
  clang/lib/Analysis/OSLog.cpp
  clang/lib/Analysis/PrintfFormatString.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGenObjC/os_log.m
  clang/test/SemaObjC/format-strings-oslog.m

Index: clang/test/SemaObjC/format-strings-oslog.m
===
--- /dev/null
+++ clang/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include 
+#include 
+#define __need_wint_t
+#include  // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+  __builtin_os_log_format(buf, "");
+  __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, "%d", i);
+  __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, "%.10P", p);
+  __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, "%.*P", i, p);
+  __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+  __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+  __builtin_os_log_format(buf, pc);   // expected-error {{os_log() format argument is not a string constant}}
+
+  printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+  __builtin_os_log_format(buf, "%{private}s", pc);
+
+  // 
+  __builtin_os_log_format_buffer_size("no-args");
+  __builtin_os_log_format(buf, "%s", "hi");
+
+  // 
+  wchar_t wc = 'a';
+  __builtin_os_log_format(buf, "%C", wc);
+  printf("%C", wc);
+  wchar_t wcs[] = {'a', 0};
+  __builtin_os_log_format(buf, "%S", wcs);
+  printf("%S", wcs);
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+  __builtin_os_log_format(buf, @"");
+  __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, @"%d", i);
+  __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, @"%.10P", p);
+  __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, @"%.*P", i, p);
+  __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+  __builtin_os_log_format(buf, @"%{private}s", pc);
+  __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+  MyOSLog("%s\n", "Hello");
+  MyOSLog("%d");// expected-warning {{more '%' conversions than data arguments}}
+  MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
Index: clang/test/CodeGenObjC/os_log.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+// Behavior of __builtin_os_log differs between platforms, so only test on X86
+#ifdef __x86_64__
+// CHECK-LABEL: define i8* @test_builtin_os_log
+void *test_builtin_os_log(void *buf) {
+  return __builtin_os_log_format(buf, "capabilities: %@", GenString());
+
+  // CHECK: store i8 2, i8*
+  // CHECK: [[NUM_ARGS:%.*]] = getelementptr i8, i8* {{.*}}, i64 1
+  // CHECK: store i8 1, i8* [[NUM_ARGS]]
+  //
+  // CHECK: [[ARG1_DESC:%.*]] = getelementptr i8, i8* {{.*}}, i64 2
+  // CHECK: store i8 64, i8* [[ARG1_DESC]]
+  // CHECK: 

[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-21 Thread David Majnemer via cfe-commits
majnemer added a comment.

You could use `llvm::any_of` instead of `std::any_of`.




Comment at: clang/include/clang/Analysis/Analyses/OSLog.h:84-86
+  result |= 0x01;
+if (getIsPublic())
+  result |= 0x02;

IsPublic/IsPrivate instead of magic numbers?



Comment at: clang/lib/Sema/SemaChecking.cpp:3493
+  Arg = Arg->IgnoreParenCasts();
+  StringLiteral *Literal = dyn_cast(Arg);
+  if (!Literal) {

`auto *`


https://reviews.llvm.org/D25888



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]

2016-10-21 Thread Mehdi AMINI via cfe-commits
mehdi_amini created this revision.
mehdi_amini added a reviewer: bkramer.
mehdi_amini added a subscriber: cfe-commits.
Herald added subscribers: modocache, mgorny, beanz.

These new builtins support a mechanism for logging OS events, using a
printf-like format string to specify the layout of data in a buffer.
The _buffer_size version of the builtin can be used to determine the size
of the buffer to allocate to hold the data, and then __builtin_os_log_format
can write data into that buffer. This implements format checking to report
mismatches between the format string and the data arguments. Most of this
code was written by Chris Willmore.


https://reviews.llvm.org/D25888

Files:
  clang/include/clang/Analysis/Analyses/FormatString.h
  clang/include/clang/Analysis/Analyses/OSLog.h
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Analysis/CMakeLists.txt
  clang/lib/Analysis/FormatString.cpp
  clang/lib/Analysis/OSLog.cpp
  clang/lib/Analysis/PrintfFormatString.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGenObjC/os_log.m
  clang/test/SemaObjC/format-strings-oslog.m

Index: clang/test/SemaObjC/format-strings-oslog.m
===
--- /dev/null
+++ clang/test/SemaObjC/format-strings-oslog.m
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#include 
+#include 
+#define __need_wint_t
+#include  // For wint_t and wchar_t
+
+int printf(const char *restrict, ...);
+
+@interface NSString
+@end
+
+void test_os_log_format(const char *pc, int i, void *p, void *buf) {
+  __builtin_os_log_format(buf, "");
+  __builtin_os_log_format(buf, "%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, "%d", i);
+  __builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, "%.10P", p);
+  __builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, "%.*P", i, p);
+  __builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+  __builtin_os_log_format(buf, "%n"); // expected-error {{os_log() '%n' format specifier is not allowed}}
+  __builtin_os_log_format(buf, pc);   // expected-error {{os_log() format argument is not a string constant}}
+
+  printf("%{private}s", pc); // expected-warning {{using 'private' format specifier annotation outside of os_log()/os_trace()}}
+  __builtin_os_log_format(buf, "%{private}s", pc);
+
+  // 
+  __builtin_os_log_format_buffer_size("no-args");
+  __builtin_os_log_format(buf, "%s", "hi");
+
+  // 
+  wchar_t wc = 'a';
+  __builtin_os_log_format(buf, "%C", wc);
+  printf("%C", wc);
+  wchar_t wcs[] = {'a', 0};
+  __builtin_os_log_format(buf, "%S", wcs);
+  printf("%S", wcs);
+}
+
+// Test os_log_format primitive with ObjC string literal format argument.
+void test_objc(const char *pc, int i, void *p, void *buf, NSString *nss) {
+  __builtin_os_log_format(buf, @"");
+  __builtin_os_log_format(buf, @"%d"); // expected-warning {{more '%' conversions than data arguments}}
+  __builtin_os_log_format(buf, @"%d", i);
+  __builtin_os_log_format(buf, @"%P", p); // expected-warning {{using '%P' format specifier without precision}}
+  __builtin_os_log_format(buf, @"%.10P", p);
+  __builtin_os_log_format(buf, @"%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
+  __builtin_os_log_format(buf, @"%.*P", i, p);
+  __builtin_os_log_format(buf, @"%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}
+
+  __builtin_os_log_format(buf, @"%{private}s", pc);
+  __builtin_os_log_format(buf, @"%@", nss);
+}
+
+// Test the os_log format attribute.
+void MyOSLog(const char *format, ...) __attribute__((format(os_log, 1, 2)));
+void test_attribute(void *p) {
+  MyOSLog("%s\n", "Hello");
+  MyOSLog("%d");// expected-warning {{more '%' conversions than data arguments}}
+  MyOSLog("%P", p); // expected-warning {{using '%P' format specifier without precision}}
+}
Index: clang/test/CodeGenObjC/os_log.m
===
--- /dev/null
+++ clang/test/CodeGenObjC/os_log.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple -fobjc-arc -O2 | FileCheck %s
+
+// Make sure we emit clang.arc.use before calling objc_release as part of the
+// cleanup. This way we make sure the object will not be released until the
+// end of the full expression.
+
+// rdar://problem/24528966
+
+@class NSString;
+extern __attribute__((visibility("default"))) NSString *GenString();
+
+//