Hi, this patch seems to cause a build failure:
/usr/bin/ld: CMakeFiles/clangAST.dir/OSLog.cpp.o: in function `(anonymous namespace)::OSLogFormatStringHandler::~OSLogFormatStringHandler()': /home/jvesely/llvm/tools/clang/lib/AST/OSLog.cpp:18: undefined reference to `clang::analyze_format_string::FormatStringHandler::~FormatStringHandler()' /usr/bin/ld: CMakeFiles/clangAST.dir/OSLog.cpp.o: in function `(anonymous namespace)::OSLogFormatStringHandler::~OSLogFormatStringHandler()': /home/jvesely/llvm/tools/clang/lib/AST/OSLog.cpp:18: undefined reference to `clang::analyze_format_string::FormatStringHandler::~FormatStringHandler()' /usr/bin/ld: CMakeFiles/clangAST.dir/OSLog.cpp.o: in function `clang::analyze_os_log::computeOSLogBufferLayout(clang::ASTContext&, clang::CallExpr const*, clang::analyze_os_log::OSLogBufferLayout&)': /home/jvesely/llvm/tools/clang/lib/AST/OSLog.cpp:198: undefined reference to `clang::analyze_format_string::ParsePrintfString(clang::analyze_format_string::FormatStringHandler&, char const*, char const*, clang::LangOptions const&, clang::TargetInfo const&, bool)' /usr/bin/ld: /home/jvesely/llvm/tools/clang/lib/AST/OSLog.cpp:18: undefined reference to `clang::analyze_format_string::FormatStringHandler::~FormatStringHandler()' collect2: error: ld returned 1 exit status thanks, Jan On Thu, Nov 1, 2018 at 2:06 PM Tim Northover via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: tnorthover > Date: Thu Nov 1 11:04:49 2018 > New Revision: 345866 > > URL: http://llvm.org/viewvc/llvm-project?rev=345866&view=rev > Log: > Reapply Logging: make os_log buffer size an integer constant expression. > > The size of an os_log buffer is known at any stage of compilation, so > making it > a constant expression means that the common idiom of declaring a buffer > for it > won't result in a VLA. That allows the compiler to skip saving and > restoring > the stack pointer around such buffers. > > This also moves the OSLog helpers from libclangAnalysis to libclangAST > to avoid a circular dependency. > > Added: > cfe/trunk/include/clang/AST/OSLog.h > cfe/trunk/lib/AST/OSLog.cpp > Removed: > cfe/trunk/include/clang/Analysis/Analyses/OSLog.h > cfe/trunk/lib/Analysis/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 > > Added: cfe/trunk/include/clang/AST/OSLog.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=345866&view=auto > > ============================================================================== > --- cfe/trunk/include/clang/AST/OSLog.h (added) > +++ cfe/trunk/include/clang/AST/OSLog.h Thu Nov 1 11:04:49 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 > > Removed: cfe/trunk/include/clang/Analysis/Analyses/OSLog.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/OSLog.h?rev=345865&view=auto > > ============================================================================== > --- cfe/trunk/include/clang/Analysis/Analyses/OSLog.h (original) > +++ cfe/trunk/include/clang/Analysis/Analyses/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 > > Modified: cfe/trunk/lib/AST/CMakeLists.txt > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/CMakeLists.txt (original) > +++ cfe/trunk/lib/AST/CMakeLists.txt Thu Nov 1 11:04:49 2018 > @@ -48,6 +48,7 @@ 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=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ExprConstant.cpp (original) > +++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Nov 1 11:04:49 2018 > @@ -39,6 +39,7 @@ > #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" > @@ -8126,6 +8127,12 @@ 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: { > > Added: cfe/trunk/lib/AST/OSLog.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=345866&view=auto > > ============================================================================== > --- cfe/trunk/lib/AST/OSLog.cpp (added) > +++ cfe/trunk/lib/AST/OSLog.cpp Thu Nov 1 11:04:49 2018 > @@ -0,0 +1,203 @@ > +// 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=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/lib/Analysis/CMakeLists.txt (original) > +++ cfe/trunk/lib/Analysis/CMakeLists.txt Thu Nov 1 11:04:49 2018 > @@ -18,7 +18,6 @@ add_clang_library(clangAnalysis > ExprMutationAnalyzer.cpp > FormatString.cpp > LiveVariables.cpp > - OSLog.cpp > ObjCNoReturn.cpp > PostOrderCFGView.cpp > PrintfFormatString.cpp > > Removed: cfe/trunk/lib/Analysis/OSLog.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/OSLog.cpp?rev=345865&view=auto > > ============================================================================== > --- cfe/trunk/lib/Analysis/OSLog.cpp (original) > +++ cfe/trunk/lib/Analysis/OSLog.cpp (removed) > @@ -1,203 +0,0 @@ > -// 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=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original) > +++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Nov 1 11:04:49 2018 > @@ -13,7 +13,7 @@ > > > //===----------------------------------------------------------------------===// > > #include "clang/Analysis/Analyses/FormatString.h" > -#include "clang/Analysis/Analyses/OSLog.h" > +#include "clang/AST/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=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Nov 1 11:04:49 2018 > @@ -21,7 +21,7 @@ > #include "TargetInfo.h" > #include "clang/AST/ASTContext.h" > #include "clang/AST/Decl.h" > -#include "clang/Analysis/Analyses/OSLog.h" > +#include "clang/AST/OSLog.h" > #include "clang/Basic/TargetBuiltins.h" > #include "clang/Basic/TargetInfo.h" > #include "clang/CodeGen/CGFunctionInfo.h" > @@ -3609,13 +3609,6 @@ 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=345866&r1=345865&r2=345866&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGen/builtins.c (original) > +++ cfe/trunk/test/CodeGen/builtins.c Thu Nov 1 11:04:49 2018 > @@ -729,25 +729,28 @@ void test_builtin_os_log_merge_helper1(v > > // CHECK-LABEL: define void @test_builtin_os_log_errno > void test_builtin_os_log_errno() { > - // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16 > - // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]]) > + // 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 > > 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_16_2_1_0_96 > +// CHECK-LABEL: define linkonce_odr hidden void > @__os_log_helper_1_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 16 > +// CHECK: store i8 2, i8* %[[SUMMARY]], align 1 > // 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 2 > +// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 1 > // 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 >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits