r345871 - Revert "Reapply Logging: make os_log buffer size an integer constant expression."

Tim Northover via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 1 11:37:42 PDT 2018


Author: tnorthover
Date: Thu Nov  1 11:37:42 2018
New Revision: 345871

URL: http://llvm.org/viewvc/llvm-project?rev=345871&view=rev
Log:
Revert "Reapply Logging: make os_log buffer size an integer constant expression."

Still more dependency hell.

Added:
    cfe/trunk/include/clang/Analysis/Analyses/OSLog.h
    cfe/trunk/lib/Analysis/OSLog.cpp
Removed:
    cfe/trunk/include/clang/AST/OSLog.h
    cfe/trunk/lib/AST/OSLog.cpp
Modified:
    cfe/trunk/lib/AST/CMakeLists.txt
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/Analysis/CMakeLists.txt
    cfe/trunk/lib/Analysis/PrintfFormatString.cpp
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
    cfe/trunk/test/CodeGen/builtins.c

Removed: cfe/trunk/include/clang/AST/OSLog.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OSLog.h?rev=345870&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/OSLog.h (original)
+++ cfe/trunk/include/clang/AST/OSLog.h (removed)
@@ -1,155 +0,0 @@
-//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines APIs for determining the layout of the data buffer for
-// os_log() and os_trace().
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
-#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-
-namespace clang {
-namespace analyze_os_log {
-
-/// An OSLogBufferItem represents a single item in the data written by a call
-/// to os_log() or os_trace().
-class OSLogBufferItem {
-public:
-  enum Kind {
-    // The item is a scalar (int, float, raw pointer, etc.). No further copying
-    // is required. This is the only kind allowed by os_trace().
-    ScalarKind = 0,
-
-    // The item is a count, which describes the length of the following item to
-    // be copied. A count may only be followed by an item of kind StringKind,
-    // WideStringKind, or PointerKind.
-    CountKind,
-
-    // The item is a pointer to a C string. If preceded by a count 'n',
-    // os_log() will copy at most 'n' bytes from the pointer.
-    StringKind,
-
-    // The item is a pointer to a block of raw data. This item must be preceded
-    // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
-    PointerKind,
-
-    // The item is a pointer to an Objective-C object. os_log() may retain the
-    // object for later processing.
-    ObjCObjKind,
-
-    // The item is a pointer to wide-char string.
-    WideStringKind,
-
-    // The item is corresponding to the '%m' format specifier, no value is
-    // populated in the buffer and the runtime is loading the errno value.
-    ErrnoKind
-  };
-
-  enum {
-    // The item is marked "private" in the format string.
-    IsPrivate = 0x1,
-
-    // The item is marked "public" in the format string.
-    IsPublic = 0x2
-  };
-
-private:
-  Kind TheKind = ScalarKind;
-  const Expr *TheExpr = nullptr;
-  CharUnits ConstValue;
-  CharUnits Size; // size of the data, not including the header bytes
-  unsigned Flags = 0;
-
-public:
-  OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
-      : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
-
-  OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
-      : TheKind(CountKind), ConstValue(value),
-        Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
-
-  unsigned char getDescriptorByte() const {
-    unsigned char result = 0;
-    if (getIsPrivate())
-      result |= IsPrivate;
-    if (getIsPublic())
-      result |= IsPublic;
-    result |= ((unsigned)getKind()) << 4;
-    return result;
-  }
-
-  unsigned char getSizeByte() const { return size().getQuantity(); }
-
-  Kind getKind() const { return TheKind; }
-  bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
-  bool getIsPublic() const { return (Flags & IsPublic) != 0; }
-
-  const Expr *getExpr() const { return TheExpr; }
-  CharUnits getConstValue() const { return ConstValue; }
-  CharUnits size() const { return Size; }
-};
-
-class OSLogBufferLayout {
-public:
-  SmallVector<OSLogBufferItem, 4> Items;
-
-  enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
-
-  CharUnits size() const {
-    CharUnits result;
-    result += CharUnits::fromQuantity(2); // summary byte, num-args byte
-    for (auto &item : Items) {
-      // descriptor byte, size byte
-      result += item.size() + CharUnits::fromQuantity(2);
-    }
-    return result;
-  }
-
-  bool hasPrivateItems() const {
-    return llvm::any_of(
-        Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
-  }
-
-  bool hasPublicItems() const {
-    return llvm::any_of(
-        Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
-  }
-
-  bool hasNonScalar() const {
-    return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
-      return Item.getKind() != OSLogBufferItem::ScalarKind;
-    });
-  }
-
-  unsigned char getSummaryByte() const {
-    unsigned char result = 0;
-    if (hasPrivateItems())
-      result |= HasPrivateItems;
-    if (hasNonScalar())
-      result |= HasNonScalarItems;
-    return result;
-  }
-
-  unsigned char getNumArgsByte() const { return Items.size(); }
-};
-
-// Given a call 'E' to one of the builtins __builtin_os_log_format() or
-// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
-// the call will write into and store it in 'layout'. Returns 'false' if there
-// was some error encountered while computing the layout, and 'true' otherwise.
-bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
-                              OSLogBufferLayout &layout);
-
-} // namespace analyze_os_log
-} // namespace clang
-#endif

Added: cfe/trunk/include/clang/Analysis/Analyses/OSLog.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/Analyses/OSLog.h?rev=345871&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/Analyses/OSLog.h (added)
+++ cfe/trunk/include/clang/Analysis/Analyses/OSLog.h Thu Nov  1 11:37:42 2018
@@ -0,0 +1,155 @@
+//= OSLog.h - Analysis of calls to os_log builtins --*- C++ -*-===============//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines APIs for determining the layout of the data buffer for
+// os_log() and os_trace().
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_OSLOG_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+namespace analyze_os_log {
+
+/// An OSLogBufferItem represents a single item in the data written by a call
+/// to os_log() or os_trace().
+class OSLogBufferItem {
+public:
+  enum Kind {
+    // The item is a scalar (int, float, raw pointer, etc.). No further copying
+    // is required. This is the only kind allowed by os_trace().
+    ScalarKind = 0,
+
+    // The item is a count, which describes the length of the following item to
+    // be copied. A count may only be followed by an item of kind StringKind,
+    // WideStringKind, or PointerKind.
+    CountKind,
+
+    // The item is a pointer to a C string. If preceded by a count 'n',
+    // os_log() will copy at most 'n' bytes from the pointer.
+    StringKind,
+
+    // The item is a pointer to a block of raw data. This item must be preceded
+    // by a count 'n'. os_log() will copy exactly 'n' bytes from the pointer.
+    PointerKind,
+
+    // The item is a pointer to an Objective-C object. os_log() may retain the
+    // object for later processing.
+    ObjCObjKind,
+
+    // The item is a pointer to wide-char string.
+    WideStringKind,
+
+    // The item is corresponding to the '%m' format specifier, no value is
+    // populated in the buffer and the runtime is loading the errno value.
+    ErrnoKind
+  };
+
+  enum {
+    // The item is marked "private" in the format string.
+    IsPrivate = 0x1,
+
+    // The item is marked "public" in the format string.
+    IsPublic = 0x2
+  };
+
+private:
+  Kind TheKind = ScalarKind;
+  const Expr *TheExpr = nullptr;
+  CharUnits ConstValue;
+  CharUnits Size; // size of the data, not including the header bytes
+  unsigned Flags = 0;
+
+public:
+  OSLogBufferItem(Kind kind, const Expr *expr, CharUnits size, unsigned flags)
+      : TheKind(kind), TheExpr(expr), Size(size), Flags(flags) {}
+
+  OSLogBufferItem(ASTContext &Ctx, CharUnits value, unsigned flags)
+      : TheKind(CountKind), ConstValue(value),
+        Size(Ctx.getTypeSizeInChars(Ctx.IntTy)), Flags(flags) {}
+
+  unsigned char getDescriptorByte() const {
+    unsigned char result = 0;
+    if (getIsPrivate())
+      result |= IsPrivate;
+    if (getIsPublic())
+      result |= IsPublic;
+    result |= ((unsigned)getKind()) << 4;
+    return result;
+  }
+
+  unsigned char getSizeByte() const { return size().getQuantity(); }
+
+  Kind getKind() const { return TheKind; }
+  bool getIsPrivate() const { return (Flags & IsPrivate) != 0; }
+  bool getIsPublic() const { return (Flags & IsPublic) != 0; }
+
+  const Expr *getExpr() const { return TheExpr; }
+  CharUnits getConstValue() const { return ConstValue; }
+  CharUnits size() const { return Size; }
+};
+
+class OSLogBufferLayout {
+public:
+  SmallVector<OSLogBufferItem, 4> Items;
+
+  enum Flags { HasPrivateItems = 1, HasNonScalarItems = 1 << 1 };
+
+  CharUnits size() const {
+    CharUnits result;
+    result += CharUnits::fromQuantity(2); // summary byte, num-args byte
+    for (auto &item : Items) {
+      // descriptor byte, size byte
+      result += item.size() + CharUnits::fromQuantity(2);
+    }
+    return result;
+  }
+
+  bool hasPrivateItems() const {
+    return llvm::any_of(
+        Items, [](const OSLogBufferItem &Item) { return Item.getIsPrivate(); });
+  }
+
+  bool hasPublicItems() const {
+    return llvm::any_of(
+        Items, [](const OSLogBufferItem &Item) { return Item.getIsPublic(); });
+  }
+
+  bool hasNonScalar() const {
+    return llvm::any_of(Items, [](const OSLogBufferItem &Item) {
+      return Item.getKind() != OSLogBufferItem::ScalarKind;
+    });
+  }
+
+  unsigned char getSummaryByte() const {
+    unsigned char result = 0;
+    if (hasPrivateItems())
+      result |= HasPrivateItems;
+    if (hasNonScalar())
+      result |= HasNonScalarItems;
+    return result;
+  }
+
+  unsigned char getNumArgsByte() const { return Items.size(); }
+};
+
+// Given a call 'E' to one of the builtins __builtin_os_log_format() or
+// __builtin_os_log_format_buffer_size(), compute the layout of the buffer that
+// the call will write into and store it in 'layout'. Returns 'false' if there
+// was some error encountered while computing the layout, and 'true' otherwise.
+bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E,
+                              OSLogBufferLayout &layout);
+
+} // namespace analyze_os_log
+} // namespace clang
+#endif

Modified: cfe/trunk/lib/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt (original)
+++ cfe/trunk/lib/AST/CMakeLists.txt Thu Nov  1 11:37:42 2018
@@ -48,7 +48,6 @@ add_clang_library(clangAST
   NestedNameSpecifier.cpp
   NSAPI.cpp
   ODRHash.cpp
-  OSLog.cpp
   OpenMPClause.cpp
   ParentMap.cpp
   QualTypeNames.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Nov  1 11:37:42 2018
@@ -39,7 +39,6 @@
 #include "clang/AST/ASTLambda.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/OSLog.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/TypeLoc.h"
@@ -8127,12 +8126,6 @@ bool IntExprEvaluator::VisitBuiltinCallE
     llvm_unreachable("unexpected EvalMode");
   }
 
-  case Builtin::BI__builtin_os_log_format_buffer_size: {
-    analyze_os_log::OSLogBufferLayout Layout;
-    analyze_os_log::computeOSLogBufferLayout(Info.Ctx, E, Layout);
-    return Success(Layout.size().getQuantity(), E);
-  }
-
   case Builtin::BI__builtin_bswap16:
   case Builtin::BI__builtin_bswap32:
   case Builtin::BI__builtin_bswap64: {

Removed: cfe/trunk/lib/AST/OSLog.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/OSLog.cpp?rev=345870&view=auto
==============================================================================
--- cfe/trunk/lib/AST/OSLog.cpp (original)
+++ cfe/trunk/lib/AST/OSLog.cpp (removed)
@@ -1,203 +0,0 @@
-// TODO: header template
-
-#include "clang/AST/OSLog.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/Analyses/FormatString.h"
-#include "clang/Basic/Builtins.h"
-#include "llvm/ADT/SmallBitVector.h"
-
-using namespace clang;
-
-using clang::analyze_os_log::OSLogBufferItem;
-using clang::analyze_os_log::OSLogBufferLayout;
-
-namespace {
-class OSLogFormatStringHandler
-    : public analyze_format_string::FormatStringHandler {
-private:
-  struct ArgData {
-    const Expr *E = nullptr;
-    Optional<OSLogBufferItem::Kind> Kind;
-    Optional<unsigned> Size;
-    Optional<const Expr *> Count;
-    Optional<const Expr *> Precision;
-    Optional<const Expr *> FieldWidth;
-    unsigned char Flags = 0;
-  };
-  SmallVector<ArgData, 4> ArgsData;
-  ArrayRef<const Expr *> Args;
-
-  OSLogBufferItem::Kind
-  getKind(analyze_format_string::ConversionSpecifier::Kind K) {
-    switch (K) {
-    case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
-      return OSLogBufferItem::StringKind;
-    case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"
-      return OSLogBufferItem::WideStringKind;
-    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
-      return OSLogBufferItem::PointerKind;
-    case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"
-      return OSLogBufferItem::ObjCObjKind;
-    case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"
-      return OSLogBufferItem::ErrnoKind;
-    default:
-      return OSLogBufferItem::ScalarKind;
-    }
-    }
-  }
-
-public:
-  OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {
-    ArgsData.reserve(Args.size());
-  }
-
-  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
-                                     const char *StartSpecifier,
-                                     unsigned SpecifierLen) {
-    if (!FS.consumesDataArgument() &&
-        FS.getConversionSpecifier().getKind() !=
-            clang::analyze_format_string::ConversionSpecifier::PrintErrno)
-      return true;
-
-    ArgsData.emplace_back();
-    unsigned ArgIndex = FS.getArgIndex();
-    if (ArgIndex < Args.size())
-      ArgsData.back().E = Args[ArgIndex];
-
-    // First get the Kind
-    ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
-    if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
-        !ArgsData.back().E) {
-      // missing argument
-      ArgsData.pop_back();
-      return false;
-    }
-
-    switch (FS.getConversionSpecifier().getKind()) {
-    case clang::analyze_format_string::ConversionSpecifier::sArg:   // "%s"
-    case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"
-      auto &precision = FS.getPrecision();
-      switch (precision.getHowSpecified()) {
-      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
-        break;
-      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
-        ArgsData.back().Size = precision.getConstantAmount();
-        break;
-      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
-        ArgsData.back().Count = Args[precision.getArgIndex()];
-        break;
-      case clang::analyze_format_string::OptionalAmount::Invalid:
-        return false;
-      }
-      break;
-    }
-    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
-      auto &precision = FS.getPrecision();
-      switch (precision.getHowSpecified()) {
-      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
-        return false; // length must be supplied with pointer format specifier
-      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
-        ArgsData.back().Size = precision.getConstantAmount();
-        break;
-      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
-        ArgsData.back().Count = Args[precision.getArgIndex()];
-        break;
-      case clang::analyze_format_string::OptionalAmount::Invalid:
-        return false;
-      }
-      break;
-    }
-    default:
-      if (FS.getPrecision().hasDataArgument()) {
-        ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
-      }
-      break;
-    }
-    if (FS.getFieldWidth().hasDataArgument()) {
-      ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
-    }
-
-    if (FS.isPrivate()) {
-      ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
-    }
-    if (FS.isPublic()) {
-      ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
-    }
-    return true;
-  }
-
-  void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
-    Layout.Items.clear();
-    for (auto &Data : ArgsData) {
-      if (Data.FieldWidth) {
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
-                                  Size, 0);
-      }
-      if (Data.Precision) {
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
-                                  Size, 0);
-      }
-      if (Data.Count) {
-        // "%.*P" has an extra "count" that we insert before the argument.
-        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
-        Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
-                                  0);
-      }
-      if (Data.Size)
-        Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
-                                  Data.Flags);
-      if (Data.Kind) {
-        CharUnits Size;
-        if (*Data.Kind == OSLogBufferItem::ErrnoKind)
-          Size = CharUnits::Zero();
-        else
-          Size = Ctx.getTypeSizeInChars(Data.E->getType());
-        Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);
-      } else {
-        auto Size = Ctx.getTypeSizeInChars(Data.E->getType());
-        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
-                                  Data.Flags);
-      }
-    }
-  }
-};
-} // end anonymous namespace
-
-bool clang::analyze_os_log::computeOSLogBufferLayout(
-    ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {
-  ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());
-
-  const Expr *StringArg;
-  ArrayRef<const Expr *> VarArgs;
-  switch (E->getBuiltinCallee()) {
-  case Builtin::BI__builtin_os_log_format_buffer_size:
-    assert(E->getNumArgs() >= 1 &&
-           "__builtin_os_log_format_buffer_size takes at least 1 argument");
-    StringArg = E->getArg(0);
-    VarArgs = Args.slice(1);
-    break;
-  case Builtin::BI__builtin_os_log_format:
-    assert(E->getNumArgs() >= 2 &&
-           "__builtin_os_log_format takes at least 2 arguments");
-    StringArg = E->getArg(1);
-    VarArgs = Args.slice(2);
-    break;
-  default:
-    llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
-  }
-
-  const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());
-  assert(Lit && (Lit->isAscii() || Lit->isUTF8()));
-  StringRef Data = Lit->getString();
-  OSLogFormatStringHandler H(VarArgs);
-  ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),
-                    Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);
-
-  H.computeLayout(Ctx, Layout);
-  return true;
-}

Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Thu Nov  1 11:37:42 2018
@@ -18,6 +18,7 @@ add_clang_library(clangAnalysis
   ExprMutationAnalyzer.cpp
   FormatString.cpp
   LiveVariables.cpp
+  OSLog.cpp
   ObjCNoReturn.cpp
   PostOrderCFGView.cpp
   PrintfFormatString.cpp

Added: cfe/trunk/lib/Analysis/OSLog.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/OSLog.cpp?rev=345871&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/OSLog.cpp (added)
+++ cfe/trunk/lib/Analysis/OSLog.cpp Thu Nov  1 11:37:42 2018
@@ -0,0 +1,203 @@
+// TODO: header template
+
+#include "clang/Analysis/Analyses/OSLog.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/Analyses/FormatString.h"
+#include "clang/Basic/Builtins.h"
+#include "llvm/ADT/SmallBitVector.h"
+
+using namespace clang;
+
+using clang::analyze_os_log::OSLogBufferItem;
+using clang::analyze_os_log::OSLogBufferLayout;
+
+namespace {
+class OSLogFormatStringHandler
+    : public analyze_format_string::FormatStringHandler {
+private:
+  struct ArgData {
+    const Expr *E = nullptr;
+    Optional<OSLogBufferItem::Kind> Kind;
+    Optional<unsigned> Size;
+    Optional<const Expr *> Count;
+    Optional<const Expr *> Precision;
+    Optional<const Expr *> FieldWidth;
+    unsigned char Flags = 0;
+  };
+  SmallVector<ArgData, 4> ArgsData;
+  ArrayRef<const Expr *> Args;
+
+  OSLogBufferItem::Kind
+  getKind(analyze_format_string::ConversionSpecifier::Kind K) {
+    switch (K) {
+    case clang::analyze_format_string::ConversionSpecifier::sArg: // "%s"
+      return OSLogBufferItem::StringKind;
+    case clang::analyze_format_string::ConversionSpecifier::SArg: // "%S"
+      return OSLogBufferItem::WideStringKind;
+    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+      return OSLogBufferItem::PointerKind;
+    case clang::analyze_format_string::ConversionSpecifier::ObjCObjArg: // "%@"
+      return OSLogBufferItem::ObjCObjKind;
+    case clang::analyze_format_string::ConversionSpecifier::PrintErrno: // "%m"
+      return OSLogBufferItem::ErrnoKind;
+    default:
+      return OSLogBufferItem::ScalarKind;
+    }
+    }
+  }
+
+public:
+  OSLogFormatStringHandler(ArrayRef<const Expr *> Args) : Args(Args) {
+    ArgsData.reserve(Args.size());
+  }
+
+  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
+                                     const char *StartSpecifier,
+                                     unsigned SpecifierLen) {
+    if (!FS.consumesDataArgument() &&
+        FS.getConversionSpecifier().getKind() !=
+            clang::analyze_format_string::ConversionSpecifier::PrintErrno)
+      return true;
+
+    ArgsData.emplace_back();
+    unsigned ArgIndex = FS.getArgIndex();
+    if (ArgIndex < Args.size())
+      ArgsData.back().E = Args[ArgIndex];
+
+    // First get the Kind
+    ArgsData.back().Kind = getKind(FS.getConversionSpecifier().getKind());
+    if (ArgsData.back().Kind != OSLogBufferItem::ErrnoKind &&
+        !ArgsData.back().E) {
+      // missing argument
+      ArgsData.pop_back();
+      return false;
+    }
+
+    switch (FS.getConversionSpecifier().getKind()) {
+    case clang::analyze_format_string::ConversionSpecifier::sArg:   // "%s"
+    case clang::analyze_format_string::ConversionSpecifier::SArg: { // "%S"
+      auto &precision = FS.getPrecision();
+      switch (precision.getHowSpecified()) {
+      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%s"
+        break;
+      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16s"
+        ArgsData.back().Size = precision.getConstantAmount();
+        break;
+      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*s"
+        ArgsData.back().Count = Args[precision.getArgIndex()];
+        break;
+      case clang::analyze_format_string::OptionalAmount::Invalid:
+        return false;
+      }
+      break;
+    }
+    case clang::analyze_format_string::ConversionSpecifier::PArg: { // "%P"
+      auto &precision = FS.getPrecision();
+      switch (precision.getHowSpecified()) {
+      case clang::analyze_format_string::OptionalAmount::NotSpecified: // "%P"
+        return false; // length must be supplied with pointer format specifier
+      case clang::analyze_format_string::OptionalAmount::Constant: // "%.16P"
+        ArgsData.back().Size = precision.getConstantAmount();
+        break;
+      case clang::analyze_format_string::OptionalAmount::Arg: // "%.*P"
+        ArgsData.back().Count = Args[precision.getArgIndex()];
+        break;
+      case clang::analyze_format_string::OptionalAmount::Invalid:
+        return false;
+      }
+      break;
+    }
+    default:
+      if (FS.getPrecision().hasDataArgument()) {
+        ArgsData.back().Precision = Args[FS.getPrecision().getArgIndex()];
+      }
+      break;
+    }
+    if (FS.getFieldWidth().hasDataArgument()) {
+      ArgsData.back().FieldWidth = Args[FS.getFieldWidth().getArgIndex()];
+    }
+
+    if (FS.isPrivate()) {
+      ArgsData.back().Flags |= OSLogBufferItem::IsPrivate;
+    }
+    if (FS.isPublic()) {
+      ArgsData.back().Flags |= OSLogBufferItem::IsPublic;
+    }
+    return true;
+  }
+
+  void computeLayout(ASTContext &Ctx, OSLogBufferLayout &Layout) const {
+    Layout.Items.clear();
+    for (auto &Data : ArgsData) {
+      if (Data.FieldWidth) {
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.FieldWidth)->getType());
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.FieldWidth,
+                                  Size, 0);
+      }
+      if (Data.Precision) {
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Precision)->getType());
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, *Data.Precision,
+                                  Size, 0);
+      }
+      if (Data.Count) {
+        // "%.*P" has an extra "count" that we insert before the argument.
+        CharUnits Size = Ctx.getTypeSizeInChars((*Data.Count)->getType());
+        Layout.Items.emplace_back(OSLogBufferItem::CountKind, *Data.Count, Size,
+                                  0);
+      }
+      if (Data.Size)
+        Layout.Items.emplace_back(Ctx, CharUnits::fromQuantity(*Data.Size),
+                                  Data.Flags);
+      if (Data.Kind) {
+        CharUnits Size;
+        if (*Data.Kind == OSLogBufferItem::ErrnoKind)
+          Size = CharUnits::Zero();
+        else
+          Size = Ctx.getTypeSizeInChars(Data.E->getType());
+        Layout.Items.emplace_back(*Data.Kind, Data.E, Size, Data.Flags);
+      } else {
+        auto Size = Ctx.getTypeSizeInChars(Data.E->getType());
+        Layout.Items.emplace_back(OSLogBufferItem::ScalarKind, Data.E, Size,
+                                  Data.Flags);
+      }
+    }
+  }
+};
+} // end anonymous namespace
+
+bool clang::analyze_os_log::computeOSLogBufferLayout(
+    ASTContext &Ctx, const CallExpr *E, OSLogBufferLayout &Layout) {
+  ArrayRef<const Expr *> Args(E->getArgs(), E->getArgs() + E->getNumArgs());
+
+  const Expr *StringArg;
+  ArrayRef<const Expr *> VarArgs;
+  switch (E->getBuiltinCallee()) {
+  case Builtin::BI__builtin_os_log_format_buffer_size:
+    assert(E->getNumArgs() >= 1 &&
+           "__builtin_os_log_format_buffer_size takes at least 1 argument");
+    StringArg = E->getArg(0);
+    VarArgs = Args.slice(1);
+    break;
+  case Builtin::BI__builtin_os_log_format:
+    assert(E->getNumArgs() >= 2 &&
+           "__builtin_os_log_format takes at least 2 arguments");
+    StringArg = E->getArg(1);
+    VarArgs = Args.slice(2);
+    break;
+  default:
+    llvm_unreachable("non-os_log builtin passed to computeOSLogBufferLayout");
+  }
+
+  const StringLiteral *Lit = cast<StringLiteral>(StringArg->IgnoreParenCasts());
+  assert(Lit && (Lit->isAscii() || Lit->isUTF8()));
+  StringRef Data = Lit->getString();
+  OSLogFormatStringHandler H(VarArgs);
+  ParsePrintfString(H, Data.begin(), Data.end(), Ctx.getLangOpts(),
+                    Ctx.getTargetInfo(), /*isFreeBSDKPrintf*/ false);
+
+  H.computeLayout(Ctx, Layout);
+  return true;
+}

Modified: cfe/trunk/lib/Analysis/PrintfFormatString.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PrintfFormatString.cpp?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/PrintfFormatString.cpp (original)
+++ cfe/trunk/lib/Analysis/PrintfFormatString.cpp Thu Nov  1 11:37:42 2018
@@ -13,7 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Analysis/Analyses/FormatString.h"
-#include "clang/AST/OSLog.h"
+#include "clang/Analysis/Analyses/OSLog.h"
 #include "FormatStringParsing.h"
 #include "clang/Basic/TargetInfo.h"
 

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Thu Nov  1 11:37:42 2018
@@ -21,7 +21,7 @@
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/OSLog.h"
+#include "clang/Analysis/Analyses/OSLog.h"
 #include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
@@ -3609,6 +3609,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(
   case Builtin::BI__builtin_os_log_format:
     return emitBuiltinOSLogFormat(*E);
 
+  case Builtin::BI__builtin_os_log_format_buffer_size: {
+    analyze_os_log::OSLogBufferLayout Layout;
+    analyze_os_log::computeOSLogBufferLayout(CGM.getContext(), E, Layout);
+    return RValue::get(ConstantInt::get(ConvertType(E->getType()),
+                                        Layout.size().getQuantity()));
+  }
+
   case Builtin::BI__xray_customevent: {
     if (!ShouldXRayInstrumentFunction())
       return RValue::getIgnored();

Modified: cfe/trunk/test/CodeGen/builtins.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtins.c?rev=345871&r1=345870&r2=345871&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/builtins.c (original)
+++ cfe/trunk/test/CodeGen/builtins.c Thu Nov  1 11:37:42 2018
@@ -729,28 +729,25 @@ void test_builtin_os_log_merge_helper1(v
 
 // CHECK-LABEL: define void @test_builtin_os_log_errno
 void test_builtin_os_log_errno() {
-  // CHECK-NOT: @stacksave
-  // CHECK: %[[BUF:.*]] = alloca [4 x i8], align 1
-  // CHECK: %[[DECAY:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUF]], i32 0, i32 0
-  // CHECK: call void @__os_log_helper_1_2_1_0_96(i8* %[[DECAY]])
-  // CHECK-NOT: @stackrestore
+  // CHECK: %[[VLA:.*]] = alloca i8, i64 4, align 16
+  // CHECK: call void @__os_log_helper_16_2_1_0_96(i8* %[[VLA]])
 
   char buf[__builtin_os_log_format_buffer_size("%m")];
   __builtin_os_log_format(buf, "%m");
 }
 
-// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_1_2_1_0_96
+// CHECK-LABEL: define linkonce_odr hidden void @__os_log_helper_16_2_1_0_96
 // CHECK: (i8* %[[BUFFER:.*]])
 
 // CHECK: %[[BUFFER_ADDR:.*]] = alloca i8*, align 8
 // CHECK: store i8* %[[BUFFER]], i8** %[[BUFFER_ADDR]], align 8
 // CHECK: %[[BUF:.*]] = load i8*, i8** %[[BUFFER_ADDR]], align 8
 // CHECK: %[[SUMMARY:.*]] = getelementptr i8, i8* %[[BUF]], i64 0
-// CHECK: store i8 2, i8* %[[SUMMARY]], align 1
+// CHECK: store i8 2, i8* %[[SUMMARY]], align 16
 // CHECK: %[[NUMARGS:.*]] = getelementptr i8, i8* %[[BUF]], i64 1
 // CHECK: store i8 1, i8* %[[NUMARGS]], align 1
 // CHECK: %[[ARGDESCRIPTOR:.*]] = getelementptr i8, i8* %[[BUF]], i64 2
-// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 1
+// CHECK: store i8 96, i8* %[[ARGDESCRIPTOR]], align 2
 // CHECK: %[[ARGSIZE:.*]] = getelementptr i8, i8* %[[BUF]], i64 3
 // CHECK: store i8 0, i8* %[[ARGSIZE]], align 1
 // CHECK-NEXT: ret void




More information about the cfe-commits mailing list