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