r345866 - Reapply Logging: make os_log buffer size an integer constant expression.
Jan Vesely via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 1 11:36:46 PDT 2018
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 at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181101/204b2fb2/attachment-0001.html>
More information about the cfe-commits
mailing list