Author: tnorthover Date: Thu Nov 1 11:37:42 2018 New Revision: 345871 URL: http://llvm.org/viewvc/llvm-project?rev=345871&view=rev Log: Revert "Reapply Logging: make os_log buffer size an integer constant expression."
Still more dependency hell. Added: cfe/trunk/include/clang/Analysis/Analyses/OSLog.h cfe/trunk/lib/Analysis/OSLog.cpp Removed: cfe/trunk/include/clang/AST/OSLog.h cfe/trunk/lib/AST/OSLog.cpp Modified: cfe/trunk/lib/AST/CMakeLists.txt cfe/trunk/lib/AST/ExprConstant.cpp cfe/trunk/lib/Analysis/CMakeLists.txt cfe/trunk/lib/Analysis/PrintfFormatString.cpp cfe/trunk/lib/CodeGen/CGBuiltin.cpp cfe/trunk/test/CodeGen/builtins.c Removed: cfe/trunk/include/clang/AST/OSLog.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=345870&view=auto ============================================================================== --- cfe/trunk/include/clang/AST/OSLog.h (original) +++ cfe/trunk/include/clang/AST/OSLog.h (removed) @@ -1,155 +0,0 @@ -//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines APIs for determining the layout of the data buffer for -// os_log() and os_trace(). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H -#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H - -#include "clang/AST/ASTContext.h" -#include "clang/AST/Expr.h" - -namespace clang { -namespace analyze_os_log { - -/// An OSLogBufferItem represents a single item in the data written by a call -/// to os_log() or os_trace(). -class OSLogBufferItem { -public: - enum Kind { - // The item is a scalar (int, float, raw pointer, etc.). No further copying - // is required. This is the only kind allowed by os_trace(). - ScalarKind = 0, - - // The item is a count, which describes the length of the following item to - // be copied. A count may only be followed by an item of kind StringKind, - // WideStringKind, or PointerKind. - CountKind, - - // The item is a pointer to a C string. If preceded by a count 'n', - // os_log() will copy at most 'n' bytes from the pointer. - StringKind, - - // The item is a pointer to a block of raw data. This item must be preceded - // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer. - PointerKind, - - // The item is a pointer to an Objective-C object. os_log() may retain the - // object for later processing. - ObjCObjKind, - - // The item is a pointer to wide-char string. - WideStringKind, - - // The item is corresponding to the '%m' format specifier, no value is - // populated in the buffer and the runtime is loading the errno value. - ErrnoKind - }; - - enum { - // The item is marked "private" in the format string. - IsPrivate = 0x1, - - // The item is marked "public" in the format string. - IsPublic = 0x2 - }; - -private: - Kind TheKind = ScalarKind; - const Expr *TheExpr = nullptr; - CharUnits ConstValue; - CharUnits Size; // size of the data, not including the header bytes - unsigned Flags = 0; - -public: - OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags) - : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {} - - OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags) - : TheKind(CountKind), ConstValue(value), - Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {} - - unsigned char getDescriptorByte() const { - unsigned char result = 0; - if (getIsPrivate()) - result |= IsPrivate; - if (getIsPublic()) - result |= IsPublic; - result |= ((unsigned)getKind()) << 4; - return result; - } - - unsigned char getSizeByte() const { return size().getQuantity(); } - - Kind getKind() const { return TheKind; } - bool getIsPrivate() const { return (Flags & IsPrivate) != 0; } - bool getIsPublic() const { return (Flags & IsPublic) != 0; } - - const Expr *getExpr() const { return TheExpr; } - CharUnits getConstValue() const { return ConstValue; } - CharUnits size() const { return Size; } -}; - -class OSLogBufferLayout { -public: - SmallVector<OSLogBufferItem, 4> Items; - - enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 }; - - CharUnits size() const { - CharUnits result; - result += CharUnits::fromQuantity(2); // summary byte, num-args byte - for (auto &item : Items) { - // descriptor byte, size byte - result += item.size() + CharUnits::fromQuantity(2); - } - return result; - } - - bool hasPrivateItems() const { - return llvm::any_of( - Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); }); - } - - bool hasPublicItems() const { - return llvm::any_of( - Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); }); - } - - bool hasNonScalar() const { - return llvm::any_of(Items, [](const OSLogBufferItem &Item) { - return Item.getKind() != OSLogBufferItem::ScalarKind; - }); - } - - unsigned char getSummaryByte() const { - unsigned char result = 0; - if (hasPrivateItems()) - result |= HasPrivateItems; - if (hasNonScalar()) - result |= HasNonScalarItems; - return result; - } - - unsigned char getNumArgsByte() const { return Items.size(); } -}; - -// Given a call 'E' to one of the builtins __builtin_os_log_format() or -// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that -// the call will write into and store it in 'layout'. Returns 'false' if there -// was some error encountered while computing the layout, and 'true' otherwise. -bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, - OSLogBufferLayout &layout); - -} // namespace analyze_os_log -} // namespace clang -#endif Added: cfe/trunk/include/clang/Analysis/Analyses/OSLog.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/OSLog.h?rev=345871&view=auto ============================================================================== --- cfe/trunk/include/clang/Analysis/Analyses/OSLog.h (added) +++ cfe/trunk/include/clang/Analysis/Analyses/OSLog.h Thu Nov 1 11:37:42 2018 @@ -0,0 +1,155 @@ +//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines APIs for determining the layout of the data buffer for +// os_log() and os_trace(). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" + +namespace clang { +namespace analyze_os_log { + +/// An OSLogBufferItem represents a single item in the data written by a call +/// to os_log() or os_trace(). +class OSLogBufferItem { +public: + enum Kind { + // The item is a scalar (int, float, raw pointer, etc.). No further copying + // is required. This is the only kind allowed by os_trace(). + ScalarKind = 0, + + // The item is a count, which describes the length of the following item to + // be copied. A count may only be followed by an item of kind StringKind, + // WideStringKind, or PointerKind. + CountKind, + + // The item is a pointer to a C string. If preceded by a count 'n', + // os_log() will copy at most 'n' bytes from the pointer. + StringKind, + + // The item is a pointer to a block of raw data. This item must be preceded + // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer. + PointerKind, + + // The item is a pointer to an Objective-C object. os_log() may retain the + // object for later processing. + ObjCObjKind, + + // The item is a pointer to wide-char string. + WideStringKind, + + // The item is corresponding to the '%m' format specifier, no value is + // populated in the buffer and the runtime is loading the errno value. + ErrnoKind + }; + + enum { + // The item is marked "private" in the format string. + IsPrivate = 0x1, + + // The item is marked "public" in the format string. + IsPublic = 0x2 + }; + +private: + Kind TheKind = ScalarKind; + const Expr *TheExpr = nullptr; + CharUnits ConstValue; + CharUnits Size; // size of the data, not including the header bytes + unsigned Flags = 0; + +public: + OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags) + : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {} + + OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags) + : TheKind(CountKind), ConstValue(value), + Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {} + + unsigned char getDescriptorByte() const { + unsigned char result = 0; + if (getIsPrivate()) + result |= IsPrivate; + if (getIsPublic()) + result |= IsPublic; + result |= ((unsigned)getKind()) << 4; + return result; + } + + unsigned char getSizeByte() const { return size().getQuantity(); } + + Kind getKind() const { return TheKind; } + bool getIsPrivate() const { return (Flags & IsPrivate) != 0; } + bool getIsPublic() const { return (Flags & IsPublic) != 0; } + + const Expr *getExpr() const { return TheExpr; } + CharUnits getConstValue() const { return ConstValue; } + CharUnits size() const { return Size; } +}; + +class OSLogBufferLayout { +public: + SmallVector<OSLogBufferItem, 4> Items; + + enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 }; + + CharUnits size() const { + CharUnits result; + result += CharUnits::fromQuantity(2); // summary byte, num-args byte + for (auto &item : Items) { + // descriptor byte, size byte + result += item.size() + CharUnits::fromQuantity(2); + } + return result; + } + + bool hasPrivateItems() const { + return llvm::any_of( + Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); }); + } + + bool hasPublicItems() const { + return llvm::any_of( + Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); }); + } + + bool hasNonScalar() const { + return llvm::any_of(Items, [](const OSLogBufferItem &Item) { + return Item.getKind() != OSLogBufferItem::ScalarKind; + }); + } + + unsigned char getSummaryByte() const { + unsigned char result = 0; + if (hasPrivateItems()) + result |= HasPrivateItems; + if (hasNonScalar()) + result |= HasNonScalarItems; + return result; + } + + unsigned char getNumArgsByte() const { return Items.size(); } +}; + +// Given a call 'E' to one of the builtins __builtin_os_log_format() or +// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that +// the call will write into and store it in 'layout'. Returns 'false' if there +// was some error encountered while computing the layout, and 'true' otherwise. +bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, + OSLogBufferLayout &layout); + +} // namespace analyze_os_log +} // namespace clang +#endif Modified: cfe/trunk/lib/AST/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/lib/AST/CMakeLists.txt (original) +++ cfe/trunk/lib/AST/CMakeLists.txt Thu Nov 1 11:37:42 2018 @@ -48,7 +48,6 @@ add_clang_library(clangAST NestedNameSpecifier.cpp NSAPI.cpp ODRHash.cpp - OSLog.cpp OpenMPClause.cpp ParentMap.cpp QualTypeNames.cpp Modified: cfe/trunk/lib/AST/ExprConstant.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp (original) +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Nov 1 11:37:42 2018 @@ -39,7 +39,6 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" -#include "clang/AST/OSLog.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" @@ -8127,12 +8126,6 @@ bool IntExprEvaluator::VisitBuiltinCallE llvm_unreachable("unexpected EvalMode"); } - case Builtin::BI__builtin_os_log_format_buffer_size: { - analyze_os_log::OSLogBufferLayout Layout; - analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout); - return Success(Layout.size().getQuantity(), E); - } - case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { Removed: cfe/trunk/lib/AST/OSLog.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=345870&view=auto ============================================================================== --- cfe/trunk/lib/AST/OSLog.cpp (original) +++ cfe/trunk/lib/AST/OSLog.cpp (removed) @@ -1,203 +0,0 @@ -// TODO: header template - -#include "clang/AST/OSLog.h" -#include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/Analysis/Analyses/FormatString.h" -#include "clang/Basic/Builtins.h" -#include "llvm/ADT/SmallBitVector.h" - -using namespace clang; - -using clang::analyze_os_log::OSLogBufferItem; -using clang::analyze_os_log::OSLogBufferLayout; - -namespace { -class OSLogFormatStringHandler - : public analyze_format_string::FormatStringHandler { -private: - struct ArgData { - 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; - ArrayRef<const Expr *> Args; - - OSLogBufferItem::Kind - getKind(analyze_format_string::ConversionSpecifier::Kind K) { - switch (K) { - case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" - return OSLogBufferItem::StringKind; - case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S" - return OSLogBufferItem::WideStringKind; - case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" - return OSLogBufferItem::PointerKind; - case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@" - return OSLogBufferItem::ObjCObjKind; - case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m" - return OSLogBufferItem::ErrnoKind; - default: - return OSLogBufferItem::ScalarKind; - } - } - } - -public: - OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) { - ArgsData.reserve(Args.size()); - } - - virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, - const char *StartSpecifier, - unsigned SpecifierLen) { - if (!FS.consumesDataArgument() && - FS.getConversionSpecifier().getKind() != - clang::analyze_format_string::ConversionSpecifier::PrintErrno) - return true; - - ArgsData.emplace_back(); - unsigned ArgIndex = FS.getArgIndex(); - if (ArgIndex < Args.size()) - ArgsData.back().E = Args[ArgIndex]; - - // First get the Kind - ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind()); - if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind && - !ArgsData.back().E) { - // missing argument - ArgsData.pop_back(); - return false; - } - - switch (FS.getConversionSpecifier().getKind()) { - case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" - case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S" - auto &precision = FS.getPrecision(); - switch (precision.getHowSpecified()) { - case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s" - break; - case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s" - ArgsData.back().Size = precision.getConstantAmount(); - break; - case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s" - ArgsData.back().Count = Args[precision.getArgIndex()]; - break; - case clang::analyze_format_string::OptionalAmount::Invalid: - return false; - } - break; - } - case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" - auto &precision = FS.getPrecision(); - switch (precision.getHowSpecified()) { - case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P" - return false; // length must be supplied with pointer format specifier - case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P" - ArgsData.back().Size = precision.getConstantAmount(); - break; - case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P" - ArgsData.back().Count = Args[precision.getArgIndex()]; - break; - case clang::analyze_format_string::OptionalAmount::Invalid: - return false; - } - 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; - } - if (FS.isPublic()) { - ArgsData.back().Flags |= OSLogBufferItem::IsPublic; - } - return true; - } - - 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); - if (Data.Kind) { - CharUnits Size; - if (*Data.Kind == OSLogBufferItem::ErrnoKind) - Size = CharUnits::Zero(); - else - Size = Ctx.getTypeSizeInChars(Data.E->getType()); - Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags); - } else { - auto Size = Ctx.getTypeSizeInChars(Data.E->getType()); - Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size, - Data.Flags); - } - } - } -}; -} // end anonymous namespace - -bool clang::analyze_os_log::computeOSLogBufferLayout( - ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) { - ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs()); - - const Expr *StringArg; - ArrayRef<const Expr *> VarArgs; - switch (E->getBuiltinCallee()) { - case Builtin::BI__builtin_os_log_format_buffer_size: - assert(E->getNumArgs() >= 1 && - "__builtin_os_log_format_buffer_size takes at least 1 argument"); - StringArg = E->getArg(0); - VarArgs = Args.slice(1); - break; - case Builtin::BI__builtin_os_log_format: - assert(E->getNumArgs() >= 2 && - "__builtin_os_log_format takes at least 2 arguments"); - StringArg = E->getArg(1); - VarArgs = Args.slice(2); - break; - default: - llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout"); - } - - const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts()); - assert(Lit && (Lit->isAscii() || Lit->isUTF8())); - StringRef Data = Lit->getString(); - OSLogFormatStringHandler H(VarArgs); - ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(), - Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false); - - H.computeLayout(Ctx, Layout); - return true; -} Modified: cfe/trunk/lib/Analysis/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CMakeLists.txt (original) +++ cfe/trunk/lib/Analysis/CMakeLists.txt Thu Nov 1 11:37:42 2018 @@ -18,6 +18,7 @@ add_clang_library(clangAnalysis ExprMutationAnalyzer.cpp FormatString.cpp LiveVariables.cpp + OSLog.cpp ObjCNoReturn.cpp PostOrderCFGView.cpp PrintfFormatString.cpp Added: cfe/trunk/lib/Analysis/OSLog.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/OSLog.cpp?rev=345871&view=auto ============================================================================== --- cfe/trunk/lib/Analysis/OSLog.cpp (added) +++ cfe/trunk/lib/Analysis/OSLog.cpp Thu Nov 1 11:37:42 2018 @@ -0,0 +1,203 @@ +// TODO: header template + +#include "clang/Analysis/Analyses/OSLog.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Basic/Builtins.h" +#include "llvm/ADT/SmallBitVector.h" + +using namespace clang; + +using clang::analyze_os_log::OSLogBufferItem; +using clang::analyze_os_log::OSLogBufferLayout; + +namespace { +class OSLogFormatStringHandler + : public analyze_format_string::FormatStringHandler { +private: + struct ArgData { + 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; + ArrayRef<const Expr *> Args; + + OSLogBufferItem::Kind + getKind(analyze_format_string::ConversionSpecifier::Kind K) { + switch (K) { + case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" + return OSLogBufferItem::StringKind; + case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S" + return OSLogBufferItem::WideStringKind; + case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" + return OSLogBufferItem::PointerKind; + case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@" + return OSLogBufferItem::ObjCObjKind; + case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m" + return OSLogBufferItem::ErrnoKind; + default: + return OSLogBufferItem::ScalarKind; + } + } + } + +public: + OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) { + ArgsData.reserve(Args.size()); + } + + virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, + const char *StartSpecifier, + unsigned SpecifierLen) { + if (!FS.consumesDataArgument() && + FS.getConversionSpecifier().getKind() != + clang::analyze_format_string::ConversionSpecifier::PrintErrno) + return true; + + ArgsData.emplace_back(); + unsigned ArgIndex = FS.getArgIndex(); + if (ArgIndex < Args.size()) + ArgsData.back().E = Args[ArgIndex]; + + // First get the Kind + ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind()); + if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind && + !ArgsData.back().E) { + // missing argument + ArgsData.pop_back(); + return false; + } + + switch (FS.getConversionSpecifier().getKind()) { + case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s" + case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S" + auto &precision = FS.getPrecision(); + switch (precision.getHowSpecified()) { + case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s" + break; + case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s" + ArgsData.back().Size = precision.getConstantAmount(); + break; + case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s" + ArgsData.back().Count = Args[precision.getArgIndex()]; + break; + case clang::analyze_format_string::OptionalAmount::Invalid: + return false; + } + break; + } + case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P" + auto &precision = FS.getPrecision(); + switch (precision.getHowSpecified()) { + case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P" + return false; // length must be supplied with pointer format specifier + case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P" + ArgsData.back().Size = precision.getConstantAmount(); + break; + case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P" + ArgsData.back().Count = Args[precision.getArgIndex()]; + break; + case clang::analyze_format_string::OptionalAmount::Invalid: + return false; + } + 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; + } + if (FS.isPublic()) { + ArgsData.back().Flags |= OSLogBufferItem::IsPublic; + } + return true; + } + + 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); + if (Data.Kind) { + CharUnits Size; + if (*Data.Kind == OSLogBufferItem::ErrnoKind) + Size = CharUnits::Zero(); + else + Size = Ctx.getTypeSizeInChars(Data.E->getType()); + Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags); + } else { + auto Size = Ctx.getTypeSizeInChars(Data.E->getType()); + Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size, + Data.Flags); + } + } + } +}; +} // end anonymous namespace + +bool clang::analyze_os_log::computeOSLogBufferLayout( + ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) { + ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs()); + + const Expr *StringArg; + ArrayRef<const Expr *> VarArgs; + switch (E->getBuiltinCallee()) { + case Builtin::BI__builtin_os_log_format_buffer_size: + assert(E->getNumArgs() >= 1 && + "__builtin_os_log_format_buffer_size takes at least 1 argument"); + StringArg = E->getArg(0); + VarArgs = Args.slice(1); + break; + case Builtin::BI__builtin_os_log_format: + assert(E->getNumArgs() >= 2 && + "__builtin_os_log_format takes at least 2 arguments"); + StringArg = E->getArg(1); + VarArgs = Args.slice(2); + break; + default: + llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout"); + } + + const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts()); + assert(Lit && (Lit->isAscii() || Lit->isUTF8())); + StringRef Data = Lit->getString(); + OSLogFormatStringHandler H(VarArgs); + ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(), + Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false); + + H.computeLayout(Ctx, Layout); + return true; +} Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original) +++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Nov 1 11:37:42 2018 @@ -13,7 +13,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/FormatString.h" -#include "clang/AST/OSLog.h" +#include "clang/Analysis/Analyses/OSLog.h" #include "FormatStringParsing.h" #include "clang/Basic/TargetInfo.h" Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Nov 1 11:37:42 2018 @@ -21,7 +21,7 @@ #include "TargetInfo.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/OSLog.h" +#include "clang/Analysis/Analyses/OSLog.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" @@ -3609,6 +3609,13 @@ RValue CodeGenFunction::EmitBuiltinExpr( case Builtin::BI__builtin_os_log_format: return emitBuiltinOSLogFormat(*E); + case Builtin::BI__builtin_os_log_format_buffer_size: { + analyze_os_log::OSLogBufferLayout Layout; + analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout); + return RValue::get(ConstantInt::get(ConvertType(E->getType()), + Layout.size().getQuantity())); + } + case Builtin::BI__xray_customevent: { if (!ShouldXRayInstrumentFunction()) return RValue::getIgnored(); Modified: cfe/trunk/test/CodeGen/builtins.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=345871&r1=345870&r2=345871&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/builtins.c (original) +++ cfe/trunk/test/CodeGen/builtins.c Thu Nov 1 11:37:42 2018 @@ -729,28 +729,25 @@ void test_builtin_os_log_merge_helper1(v // CHECK-LABEL: define void @test_builtin_os_log_errno void test_builtin_os_log_errno() { - // CHECK-NOT: @stacksave - // CHECK: %[[BUF:.*]] = alloca [4 x i8], align 1 - // CHECK: %[[DECAY:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUF]], i32 0, i32 0 - // CHECK: call void @__os_log_helper_1_2_1_0_96(i8* %[[DECAY]]) - // CHECK-NOT: @stackrestore + // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16 + // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]]) char buf[__builtin_os_log_format_buffer_size("%m")]; __builtin_os_log_format(buf, "%m"); } -// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_0_96 +// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_16_2_1_0_96 // CHECK: (i8* %[[BUFFER:.*]]) // CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8 // CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8 // CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8 // CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0 -// CHECK: store i8 2, i8* %[[SUMMARY]], align 1 +// CHECK: store i8 2, i8* %[[SUMMARY]], align 16 // CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1 // CHECK: store i8 1, i8* %[[NUMARGS]], align 1 // CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2 -// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 1 +// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 2 // CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3 // CHECK: store i8 0, i8* %[[ARGSIZE]], align 1 // CHECK-NEXT: ret void _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits