[PATCH] D25888: Add support for __builtin_os_log_format[_buffer_size]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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(); + +//