<div dir="ltr">Assuming it's just the signedness issue, this should be fixed by r290356.<div><br></div><div>Thanks for the heads-up!</div><div>George</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Dec 22, 2016 at 10:06 AM, Galina Kistanova <span dir="ltr"><<a href="mailto:gkistanova@gmail.com" target="_blank">gkistanova@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hello George,<br><br>This commit added warning to some builders:<br><br>llvm.src\tools\clang\lib\Sema\<wbr>SemaDeclAttr.cpp(259): warning C4018: '>': signed/unsigned mismatch<br><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/2892" target="_blank">http://lab.llvm.org:8011/build<wbr>ers/llvm-clang-lld-x86_64-scei<wbr>-ps4-windows10pro-fast/builds/<wbr>2892</a><br><br>Please have a look at this?<br><br>Thanks<span class="m_5221544646239809100m_2580774537617187166m_1283169874970857783HOEnZb"><font color="#888888"><br><br>Galina<br></font></span></div><div class="m_5221544646239809100m_2580774537617187166m_1283169874970857783HOEnZb"><div class="m_5221544646239809100m_2580774537617187166m_1283169874970857783h5"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 19, 2016 at 5:05 PM, George Burgess IV via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: gbiv<br>
Date: Mon Dec 19 19:05:42 2016<br>
New Revision: 290149<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=290149&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=290149&view=rev</a><br>
Log:<br>
Add the alloc_size attribute to clang.<br>
<br>
This patch does three things:<br>
<br>
- Gives us the alloc_size attribute in clang, which lets us infer the<br>
  number of bytes handed back to us by malloc/realloc/calloc/any user<br>
  functions that act in a similar manner.<br>
- Teaches our constexpr evaluator that evaluating some `const` variables<br>
  is OK sometimes. This is why we have a change in<br>
  test/SemaCXX/constant-expressi<wbr>on-cxx11.cpp and other seemingly<br>
  unrelated tests. Richard Smith okay'ed this idea some time ago in<br>
  person.<br>
- Uniques some Blocks in CodeGen, which was reviewed separately at<br>
  D26410. Lack of uniquing only really shows up as a problem when<br>
  combined with our new eagerness in the face of const.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D14274" rel="noreferrer" target="_blank">https://reviews.llvm.org/D1427<wbr>4</a><br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/alloc-s<wbr>ize.c<br>
    cfe/trunk/test/CodeGenCXX/allo<wbr>c-size.cpp<br>
    cfe/trunk/test/Sema/alloc-size<wbr>.c<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/<wbr>Attr.td<br>
    cfe/trunk/include/clang/Basic/<wbr>AttrDocs.td<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/AST/ExprConstant<wbr>.cpp<br>
    cfe/trunk/lib/CodeGen/CGBlocks<wbr>.cpp<br>
    cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp<br>
    cfe/trunk/lib/CodeGen/CodeGenF<wbr>unction.h<br>
    cfe/trunk/lib/CodeGen/CodeGenM<wbr>odule.h<br>
    cfe/trunk/lib/Sema/SemaDeclAtt<wbr>r.cpp<br>
    cfe/trunk/test/CodeGenCXX/bloc<wbr>k-in-ctor-dtor.cpp<br>
    cfe/trunk/test/CodeGenCXX/glob<wbr>al-init.cpp<br>
    cfe/trunk/test/CodeGenOpenCL/<a href="http://cl20-device-side-enqueue.cl" rel="noreferrer" target="_blank">c<wbr>l20-device-side-enqueue.cl</a><br>
    cfe/trunk/test/SemaCXX/constan<wbr>t-expression-cxx11.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>Attr.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/Attr.td?rev=290149&r1=29<wbr>0148&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>Attr.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>Attr.td Mon Dec 19 19:05:42 2016<br>
@@ -780,6 +780,15 @@ def EmptyBases : InheritableAttr, Target<br>
   let Documentation = [EmptyBasesDocs];<br>
 }<br>
<br>
+def AllocSize : InheritableAttr {<br>
+  let Spellings = [GCC<"alloc_size">];<br>
+  let Subjects = SubjectList<[HasFunctionProto]<wbr>, WarnDiag,<br>
+                             "ExpectedFunctionWithProtoTyp<wbr>e">;<br>
+  let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>];<br>
+  let TemplateDependent = 1;<br>
+  let Documentation = [AllocSizeDocs];<br>
+}<br>
+<br>
 def EnableIf : InheritableAttr {<br>
   let Spellings = [GNU<"enable_if">];<br>
   let Subjects = SubjectList<[Function]>;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>AttrDocs.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/AttrDocs.td?rev=290149&r<wbr>1=290148&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>AttrDocs.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>AttrDocs.td Mon Dec 19 19:05:42 2016<br>
@@ -206,6 +206,44 @@ to enforce the provided alignment assump<br>
   }];<br>
 }<br>
<br>
+def AllocSizeDocs : Documentation {<br>
+  let Category = DocCatFunction;<br>
+  let Content = [{<br>
+The ``alloc_size`` attribute can be placed on functions that return pointers in<br>
+order to hint to the compiler how many bytes of memory will be available at the<br>
+returned poiner. ``alloc_size`` takes one or two arguments.<br>
+<br>
+- ``alloc_size(N)`` implies that argument number N equals the number of<br>
+  available bytes at the returned pointer.<br>
+- ``alloc_size(N, M)`` implies that the product of argument number N and<br>
+  argument number M equals the number of available bytes at the returned<br>
+  pointer.<br>
+<br>
+Argument numbers are 1-based.<br>
+<br>
+An example of how to use ``alloc_size``<br>
+<br>
+.. code-block:: c<br>
+<br>
+  void *my_malloc(int a) __attribute__((alloc_size(1)))<wbr>;<br>
+  void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2)));<br>
+<br>
+  int main() {<br>
+    void *const p = my_malloc(100);<br>
+    assert(__builtin_object_size(p<wbr>, 0) == 100);<br>
+    void *const a = my_calloc(20, 5);<br>
+    assert(__builtin_object_size(a<wbr>, 0) == 100);<br>
+  }<br>
+<br>
+.. Note:: This attribute works differently in clang than it does in GCC.<br>
+  Specifically, clang will only trace ``const`` pointers (as above); we give up<br>
+  on pointers that are not marked as ``const``. In the vast majority of cases,<br>
+  this is unimportant, because LLVM has support for the ``alloc_size``<br>
+  attribute. However, this may cause mildly unintuitive behavior when used with<br>
+  other attributes, such as ``enable_if``.<br>
+  }];<br>
+}<br>
+<br>
 def EnableIfDocs : Documentation {<br>
   let Category = DocCatFunction;<br>
   let Content = [{<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/DiagnosticSemaKinds.td?r<wbr>ev=290149&r1=290148&r2=290149&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Mon Dec 19 19:05:42 2016<br>
@@ -2297,6 +2297,9 @@ def warn_attribute_pointers_only : Warni<br>
   "%0 attribute only applies to%select{| constant}1 pointer arguments">,<br>
   InGroup<IgnoredAttributes>;<br>
 def err_attribute_pointers_only : Error<warn_attribute_pointers_<wbr>only.Text>;<br>
+def err_attribute_integers_only : Error<<br>
+  "%0 attribute argument may only refer to a function parameter of integer "<br>
+  "type">;<br>
 def warn_attribute_return_pointers<wbr>_only : Warning<<br>
   "%0 attribute only applies to return values that are pointers">,<br>
   InGroup<IgnoredAttributes>;<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant<wbr>.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/AST/ExprCo<wbr>nstant.cpp?rev=290149&r1=29014<wbr>8&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ExprConstant<wbr>.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant<wbr>.cpp Mon Dec 19 19:05:42 2016<br>
@@ -109,19 +109,57 @@ namespace {<br>
     return getAsBaseOrMember(E).getInt();<br>
   }<br>
<br>
+  /// Given a CallExpr, try to get the alloc_size attribute. May return null.<br>
+  static const AllocSizeAttr *getAllocSizeAttr(const CallExpr *CE) {<br>
+    const FunctionDecl *Callee = CE->getDirectCallee();<br>
+    return Callee ? Callee->getAttr<AllocSizeAttr><wbr>() : nullptr;<br>
+  }<br>
+<br>
+  /// Attempts to unwrap a CallExpr (with an alloc_size attribute) from an Expr.<br>
+  /// This will look through a single cast.<br>
+  ///<br>
+  /// Returns null if we couldn't unwrap a function with alloc_size.<br>
+  static const CallExpr *tryUnwrapAllocSizeCall(const Expr *E) {<br>
+    if (!E->getType()->isPointerType(<wbr>))<br>
+      return nullptr;<br>
+<br>
+    E = E->IgnoreParens();<br>
+    // If we're doing a variable assignment from e.g. malloc(N), there will<br>
+    // probably be a cast of some kind. Ignore it.<br>
+    if (const auto *Cast = dyn_cast<CastExpr>(E))<br>
+      E = Cast->getSubExpr()->IgnorePare<wbr>ns();<br>
+<br>
+    if (const auto *CE = dyn_cast<CallExpr>(E))<br>
+      return getAllocSizeAttr(CE) ? CE : nullptr;<br>
+    return nullptr;<br>
+  }<br>
+<br>
+  /// Determines whether or not the given Base contains a call to a function<br>
+  /// with the alloc_size attribute.<br>
+  static bool isBaseAnAllocSizeCall(APValue:<wbr>:LValueBase Base) {<br>
+    const auto *E = Base.dyn_cast<const Expr *>();<br>
+    return E && E->getType()->isPointerType() && tryUnwrapAllocSizeCall(E);<br>
+  }<br>
+<br>
+  /// Determines if an LValue with the given LValueBase will have an unsized<br>
+  /// array in its designator.<br>
   /// Find the path length and type of the most-derived subobject in the given<br>
   /// path, and find the size of the containing array, if any.<br>
-  static<br>
-  unsigned findMostDerivedSubobject(ASTCo<wbr>ntext &Ctx, QualType Base,<br>
-                                    ArrayRef<APValue::LValuePathEn<wbr>try> Path,<br>
-                                    uint64_t &ArraySize, QualType &Type,<br>
-                                    bool &IsArray) {<br>
+  static unsigned<br>
+  findMostDerivedSubobject(ASTCo<wbr>ntext &Ctx, APValue::LValueBase Base,<br>
+                           ArrayRef<APValue::LValuePathE<wbr>ntry> Path,<br>
+                           uint64_t &ArraySize, QualType &Type, bool &IsArray) {<br>
+    // This only accepts LValueBases from APValues, and APValues don't support<br>
+    // arrays that lack size info.<br>
+    assert(!isBaseAnAllocSizeCall(<wbr>Base) &&<br>
+           "Unsized arrays shouldn't appear here");<br>
     unsigned MostDerivedLength = 0;<br>
-    Type = Base;<br>
+    Type = getType(Base);<br>
+<br>
     for (unsigned I = 0, N = Path.size(); I != N; ++I) {<br>
       if (Type->isArrayType()) {<br>
         const ConstantArrayType *CAT =<br>
-          cast<ConstantArrayType>(Ctx.ge<wbr>tAsArrayType(Type));<br>
+            cast<ConstantArrayType>(Ctx.ge<wbr>tAsArrayType(Type));<br>
         Type = CAT->getElementType();<br>
         ArraySize = CAT->getSize().getZExtValue();<br>
         MostDerivedLength = I + 1;<br>
@@ -162,17 +200,23 @@ namespace {<br>
     /// Is this a pointer one past the end of an object?<br>
     unsigned IsOnePastTheEnd : 1;<br>
<br>
+    /// Indicator of whether the first entry is an unsized array.<br>
+    bool FirstEntryIsAnUnsizedArray : 1;<br>
+<br>
     /// Indicator of whether the most-derived object is an array element.<br>
     unsigned MostDerivedIsArrayElement : 1;<br>
<br>
     /// The length of the path to the most-derived object of which this is a<br>
     /// subobject.<br>
-    unsigned MostDerivedPathLength : 29;<br>
+    unsigned MostDerivedPathLength : 28;<br>
<br>
     /// The size of the array of which the most-derived object is an element.<br>
     /// This will always be 0 if the most-derived object is not an array<br>
     /// element. 0 is not an indicator of whether or not the most-derived object<br>
     /// is an array, however, because 0-length arrays are allowed.<br>
+    ///<br>
+    /// If the current array is an unsized array, the value of this is<br>
+    /// undefined.<br>
     uint64_t MostDerivedArraySize;<br>
<br>
     /// The type of the most derived object referred to by this address.<br>
@@ -187,23 +231,24 @@ namespace {<br>
<br>
     explicit SubobjectDesignator(QualType T)<br>
         : Invalid(false), IsOnePastTheEnd(false),<br>
-          MostDerivedIsArrayElement(fals<wbr>e), MostDerivedPathLength(0),<br>
-          MostDerivedArraySize(0), MostDerivedType(T) {}<br>
+          FirstEntryIsAnUnsizedArray(fal<wbr>se), MostDerivedIsArrayElement(fals<wbr>e),<br>
+          MostDerivedPathLength(0), MostDerivedArraySize(0),<br>
+          MostDerivedType(T) {}<br>
<br>
     SubobjectDesignator(ASTContex<wbr>t &Ctx, const APValue &V)<br>
         : Invalid(!V.isLValue() || !V.hasLValuePath()), IsOnePastTheEnd(false),<br>
-          MostDerivedIsArrayElement(fals<wbr>e), MostDerivedPathLength(0),<br>
-          MostDerivedArraySize(0) {<br>
+          FirstEntryIsAnUnsizedArray(fal<wbr>se), MostDerivedIsArrayElement(fals<wbr>e),<br>
+          MostDerivedPathLength(0), MostDerivedArraySize(0) {<br>
+      assert(V.isLValue() && "Non-LValue used to make an LValue designator?");<br>
       if (!Invalid) {<br>
         IsOnePastTheEnd = V.isLValueOnePastTheEnd();<br>
         ArrayRef<PathEntry> VEntries = V.getLValuePath();<br>
         Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());<br>
         if (V.getLValueBase()) {<br>
           bool IsArray = false;<br>
-          MostDerivedPathLength =<br>
-              findMostDerivedSubobject(Ctx, getType(V.getLValueBase()),<br>
-                                       V.getLValuePath(), MostDerivedArraySize,<br>
-                                       MostDerivedType, IsArray);<br>
+          MostDerivedPathLength = findMostDerivedSubobject(<br>
+              Ctx, V.getLValueBase(), V.getLValuePath(), MostDerivedArraySize,<br>
+              MostDerivedType, IsArray);<br>
           MostDerivedIsArrayElement = IsArray;<br>
         }<br>
       }<br>
@@ -214,12 +259,25 @@ namespace {<br>
       Entries.clear();<br>
     }<br>
<br>
+    /// Determine whether the most derived subobject is an array without a<br>
+    /// known bound.<br>
+    bool isMostDerivedAnUnsizedArray() const {<br>
+      return FirstEntryIsAnUnsizedArray && Entries.size() == 1;<br>
+    }<br>
+<br>
+    /// Determine what the most derived array's size is. Results in an assertion<br>
+    /// failure if the most derived array lacks a size.<br>
+    uint64_t getMostDerivedArraySize() const {<br>
+      assert(!isMostDerivedAnUnsized<wbr>Array() && "Unsized array has no size");<br>
+      return MostDerivedArraySize;<br>
+    }<br>
+<br>
     /// Determine whether this is a one-past-the-end pointer.<br>
     bool isOnePastTheEnd() const {<br>
       assert(!Invalid);<br>
       if (IsOnePastTheEnd)<br>
         return true;<br>
-      if (MostDerivedIsArrayElement &&<br>
+      if (!isMostDerivedAnUnsizedArray(<wbr>) && MostDerivedIsArrayElement &&<br>
           Entries[MostDerivedPathLength - 1].ArrayIndex == MostDerivedArraySize)<br>
         return true;<br>
       return false;<br>
@@ -247,6 +305,21 @@ namespace {<br>
       MostDerivedArraySize = CAT->getSize().getZExtValue();<br>
       MostDerivedPathLength = Entries.size();<br>
     }<br>
+    /// Update this designator to refer to the first element within the array of<br>
+    /// elements of type T. This is an array of unknown size.<br>
+    void addUnsizedArrayUnchecked(QualT<wbr>ype ElemTy) {<br>
+      PathEntry Entry;<br>
+      Entry.ArrayIndex = 0;<br>
+      Entries.push_back(Entry);<br>
+<br>
+      MostDerivedType = ElemTy;<br>
+      MostDerivedIsArrayElement = true;<br>
+      // The value in MostDerivedArraySize is undefined in this case. So, set it<br>
+      // to an arbitrary value that's likely to loudly break things if it's<br>
+      // used.<br>
+      MostDerivedArraySize = std::numeric_limits<uint64_t>:<wbr>:max() / 2;<br>
+      MostDerivedPathLength = Entries.size();<br>
+    }<br>
     /// Update this designator to refer to the given base or member of this<br>
     /// object.<br>
     void addDeclUnchecked(const Decl *D, bool Virtual = false) {<br>
@@ -280,10 +353,16 @@ namespace {<br>
     /// Add N to the address of this subobject.<br>
     void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {<br>
       if (Invalid) return;<br>
+      if (isMostDerivedAnUnsizedArray()<wbr>) {<br>
+        // Can't verify -- trust that the user is doing the right thing (or if<br>
+        // not, trust that the caller will catch the bad behavior).<br>
+        Entries.back().ArrayIndex += N;<br>
+        return;<br>
+      }<br>
       if (MostDerivedPathLength == Entries.size() &&<br>
           MostDerivedIsArrayElement) {<br>
         Entries.back().ArrayIndex += N;<br>
-        if (Entries.back().ArrayIndex > MostDerivedArraySize) {<br>
+        if (Entries.back().ArrayIndex > getMostDerivedArraySize()) {<br>
           diagnosePointerArithmetic(Inf<wbr>o, E, Entries.back().ArrayIndex);<br>
           setInvalid();<br>
         }<br>
@@ -524,9 +603,15 @@ namespace {<br>
       /// gets a chance to look at it.<br>
       EM_PotentialConstantExpressio<wbr>nUnevaluated,<br>
<br>
-      /// Evaluate as a constant expression. Continue evaluating if we find a<br>
-      /// MemberExpr with a base that can't be evaluated.<br>
-      EM_DesignatorFold,<br>
+      /// Evaluate as a constant expression. Continue evaluating if either:<br>
+      /// - We find a MemberExpr with a base that can't be evaluated.<br>
+      /// - We find a variable initialized with a call to a function that has<br>
+      ///   the alloc_size attribute on it.<br>
+      /// In either case, the LValue returned shall have an invalid base; in the<br>
+      /// former, the base will be the invalid MemberExpr, in the latter, the<br>
+      /// base will be either the alloc_size CallExpr or a CastExpr wrapping<br>
+      /// said CallExpr.<br>
+      EM_OffsetFold,<br>
     } EvalMode;<br>
<br>
     /// Are we checking whether the expression is a potential constant<br>
@@ -628,7 +713,7 @@ namespace {<br>
           case EM_PotentialConstantExpression<wbr>:<br>
           case EM_ConstantExpressionUnevaluat<wbr>ed:<br>
           case EM_PotentialConstantExpression<wbr>Unevaluated:<br>
-          case EM_DesignatorFold:<br>
+          case EM_OffsetFold:<br>
             HasActiveDiagnostic = false;<br>
             return OptionalDiagnostic();<br>
           }<br>
@@ -720,7 +805,7 @@ namespace {<br>
       case EM_ConstantExpression:<br>
       case EM_ConstantExpressionUnevaluat<wbr>ed:<br>
       case EM_ConstantFold:<br>
-      case EM_DesignatorFold:<br>
+      case EM_OffsetFold:<br>
         return false;<br>
       }<br>
       llvm_unreachable("Missed EvalMode case");<br>
@@ -739,7 +824,7 @@ namespace {<br>
       case EM_EvaluateForOverflow:<br>
       case EM_IgnoreSideEffects:<br>
       case EM_ConstantFold:<br>
-      case EM_DesignatorFold:<br>
+      case EM_OffsetFold:<br>
         return true;<br>
<br>
       case EM_PotentialConstantExpression<wbr>:<br>
@@ -775,7 +860,7 @@ namespace {<br>
       case EM_ConstantExpressionUnevaluat<wbr>ed:<br>
       case EM_ConstantFold:<br>
       case EM_IgnoreSideEffects:<br>
-      case EM_DesignatorFold:<br>
+      case EM_OffsetFold:<br>
         return false;<br>
       }<br>
       llvm_unreachable("Missed EvalMode case");<br>
@@ -805,7 +890,7 @@ namespace {<br>
     }<br>
<br>
     bool allowInvalidBaseExpr() const {<br>
-      return EvalMode == EM_DesignatorFold;<br>
+      return EvalMode == EM_OffsetFold;<br>
     }<br>
<br>
     class ArrayInitLoopIndex {<br>
@@ -856,11 +941,10 @@ namespace {<br>
   struct FoldOffsetRAII {<br>
     EvalInfo &Info;<br>
     EvalInfo::EvaluationMode OldMode;<br>
-    explicit FoldOffsetRAII(EvalInfo &Info, bool Subobject)<br>
+    explicit FoldOffsetRAII(EvalInfo &Info)<br>
         : Info(Info), OldMode(Info.EvalMode) {<br>
       if (!Info.checkingPotentialConsta<wbr>ntExpression())<br>
-        Info.EvalMode = Subobject ? EvalInfo::EM_DesignatorFold<br>
-                                  : EvalInfo::EM_ConstantFold;<br>
+        Info.EvalMode = EvalInfo::EM_OffsetFold;<br>
     }<br>
<br>
     ~FoldOffsetRAII() { Info.EvalMode = OldMode; }<br>
@@ -966,10 +1050,12 @@ bool SubobjectDesignator::checkSubo<wbr>bject<br>
<br>
 void SubobjectDesignator::diagnoseP<wbr>ointerArithmetic(EvalInfo &Info,<br>
                                                     const Expr *E, uint64_t N) {<br>
+  // If we're complaining, we must be able to statically determine the size of<br>
+  // the most derived array.<br>
   if (MostDerivedPathLength == Entries.size() && MostDerivedIsArrayElement)<br>
     Info.CCEDiag(E, diag::note_constexpr_array_ind<wbr>ex)<br>
       << static_cast<int>(N) << /*array*/ 0<br>
-      << static_cast<unsigned>(MostDeri<wbr>vedArraySize);<br>
+      << static_cast<unsigned>(getMostD<wbr>erivedArraySize());<br>
   else<br>
     Info.CCEDiag(E, diag::note_constexpr_array_ind<wbr>ex)<br>
       << static_cast<int>(N) << /*non-array*/ 1;<br>
@@ -1102,12 +1188,16 @@ namespace {<br>
       if (Designator.Invalid)<br>
         V = APValue(Base, Offset, APValue::NoLValuePath(), CallIndex,<br>
                     IsNullPtr);<br>
-      else<br>
+      else {<br>
+        assert(!InvalidBase && "APValues can't handle invalid LValue bases");<br>
+        assert(!Designator.FirstEntryI<wbr>sAnUnsizedArray &&<br>
+               "Unsized array with a valid base?");<br>
         V = APValue(Base, Offset, Designator.Entries,<br>
                     Designator.IsOnePastTheEnd, CallIndex, IsNullPtr);<br>
+      }<br>
     }<br>
     void setFrom(ASTContext &Ctx, const APValue &V) {<br>
-      assert(V.isLValue());<br>
+      assert(V.isLValue() && "Setting LValue from a non-LValue?");<br>
       Base = V.getLValueBase();<br>
       Offset = V.getLValueOffset();<br>
       InvalidBase = false;<br>
@@ -1118,6 +1208,15 @@ namespace {<br>
<br>
     void set(APValue::LValueBase B, unsigned I = 0, bool BInvalid = false,<br>
              bool IsNullPtr_ = false, uint64_t Offset_ = 0) {<br>
+#ifndef NDEBUG<br>
+      // We only allow a few types of invalid bases. Enforce that here.<br>
+      if (BInvalid) {<br>
+        const auto *E = B.get<const Expr *>();<br>
+        assert((isa<MemberExpr>(E) || tryUnwrapAllocSizeCall(E)) &&<br>
+               "Unexpected type of invalid base");<br>
+      }<br>
+#endif<br>
+<br>
       Base = B;<br>
       Offset = CharUnits::fromQuantity(Offset<wbr>_);<br>
       InvalidBase = BInvalid;<br>
@@ -1157,6 +1256,13 @@ namespace {<br>
       if (checkSubobject(Info, E, isa<FieldDecl>(D) ? CSK_Field : CSK_Base))<br>
         Designator.addDeclUnchecked(D<wbr>, Virtual);<br>
     }<br>
+    void addUnsizedArray(EvalInfo &Info, QualType ElemTy) {<br>
+      assert(Designator.Entries.empt<wbr>y() && getType(Base)->isPointerType()<wbr>);<br>
+      assert(isBaseAnAllocSizeCall(B<wbr>ase) &&<br>
+             "Only alloc_size bases can have unsized arrays");<br>
+      Designator.FirstEntryIsAnUnsiz<wbr>edArray = true;<br>
+      Designator.addUnsizedArrayUnch<wbr>ecked(ElemTy);<br>
+    }<br>
     void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) {<br>
       if (checkSubobject(Info, E, CSK_ArrayToPointer))<br>
         Designator.addArrayUnchecked(<wbr>CAT);<br>
@@ -2796,7 +2902,7 @@ static CompleteObject findCompleteObject<br>
         // All the remaining cases only permit reading.<br>
         Info.FFDiag(E, diag::note_constexpr_modify_gl<wbr>obal);<br>
         return CompleteObject();<br>
-      } else if (VD->isConstexpr()) {<br>
+      } else if (VD->isConstexpr() || BaseType.isConstQualified()) {<br>
         // OK, we can read this variable.<br>
       } else if (BaseType->isIntegralOrEnumera<wbr>tionType()) {<br>
         // In OpenCL if a variable is in constant address space it is a const value.<br>
@@ -5079,6 +5185,105 @@ bool LValueExprEvaluator::VisitBinA<wbr>ssign<br>
 // Pointer Evaluation<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
+/// \brief Attempts to compute the number of bytes available at the pointer<br>
+/// returned by a function with the alloc_size attribute. Returns true if we<br>
+/// were successful. Places an unsigned number into `Result`.<br>
+///<br>
+/// This expects the given CallExpr to be a call to a function with an<br>
+/// alloc_size attribute.<br>
+static bool getBytesReturnedByAllocSizeCal<wbr>l(const ASTContext &Ctx,<br>
+                                            const CallExpr *Call,<br>
+                                            llvm::APInt &Result) {<br>
+  const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call);<br>
+<br>
+  // alloc_size args are 1-indexed, 0 means not present.<br>
+  assert(AllocSize && AllocSize->getElemSizeParam() != 0);<br>
+  unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1;<br>
+  unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeTyp<wbr>e());<br>
+  if (Call->getNumArgs() <= SizeArgNo)<br>
+    return false;<br>
+<br>
+  auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {<br>
+    if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects))<br>
+      return false;<br>
+    if (Into.isNegative() || !Into.isIntN(BitsInSizeT))<br>
+      return false;<br>
+    Into = Into.zextOrSelf(BitsInSizeT);<br>
+    return true;<br>
+  };<br>
+<br>
+  APSInt SizeOfElem;<br>
+  if (!EvaluateAsSizeT(Call->getArg<wbr>(SizeArgNo), SizeOfElem))<br>
+    return false;<br>
+<br>
+  if (!AllocSize->getNumElemsParam(<wbr>)) {<br>
+    Result = std::move(SizeOfElem);<br>
+    return true;<br>
+  }<br>
+<br>
+  APSInt NumberOfElems;<br>
+  // Argument numbers start at 1<br>
+  unsigned NumArgNo = AllocSize->getNumElemsParam() - 1;<br>
+  if (!EvaluateAsSizeT(Call->getArg<wbr>(NumArgNo), NumberOfElems))<br>
+    return false;<br>
+<br>
+  bool Overflow;<br>
+  llvm::APInt BytesAvailable = SizeOfElem.umul_ov(NumberOfEle<wbr>ms, Overflow);<br>
+  if (Overflow)<br>
+    return false;<br>
+<br>
+  Result = std::move(BytesAvailable);<br>
+  return true;<br>
+}<br>
+<br>
+/// \brief Convenience function. LVal's base must be a call to an alloc_size<br>
+/// function.<br>
+static bool getBytesReturnedByAllocSizeCal<wbr>l(const ASTContext &Ctx,<br>
+                                            const LValue &LVal,<br>
+                                            llvm::APInt &Result) {<br>
+  assert(isBaseAnAllocSizeCall(L<wbr>Val.getLValueBase()) &&<br>
+         "Can't get the size of a non alloc_size function");<br>
+  const auto *Base = LVal.getLValueBase().get<const Expr *>();<br>
+  const CallExpr *CE = tryUnwrapAllocSizeCall(Base);<br>
+  return getBytesReturnedByAllocSizeCal<wbr>l(Ctx, CE, Result);<br>
+}<br>
+<br>
+/// \brief Attempts to evaluate the given LValueBase as the result of a call to<br>
+/// a function with the alloc_size attribute. If it was possible to do so, this<br>
+/// function will return true, make Result's Base point to said function call,<br>
+/// and mark Result's Base as invalid.<br>
+static bool evaluateLValueAsAllocSize(Eval<wbr>Info &Info, APValue::LValueBase Base,<br>
+                                      LValue &Result) {<br>
+  if (!Info.allowInvalidBaseExpr() || Base.isNull())<br>
+    return false;<br>
+<br>
+  // Because we do no form of static analysis, we only support const variables.<br>
+  //<br>
+  // Additionally, we can't support parameters, nor can we support static<br>
+  // variables (in the latter case, use-before-assign isn't UB; in the former,<br>
+  // we have no clue what they'll be assigned to).<br>
+  const auto *VD =<br>
+      dyn_cast_or_null<VarDecl>(Base<wbr>.dyn_cast<const ValueDecl *>());<br>
+  if (!VD || !VD->isLocalVarDecl() || !VD->getType().isConstQualifie<wbr>d())<br>
+    return false;<br>
+<br>
+  const Expr *Init = VD->getAnyInitializer();<br>
+  if (!Init)<br>
+    return false;<br>
+<br>
+  const Expr *E = Init->IgnoreParens();<br>
+  if (!tryUnwrapAllocSizeCall(E))<br>
+    return false;<br>
+<br>
+  // Store E instead of E unwrapped so that the type of the LValue's base is<br>
+  // what the user wanted.<br>
+  Result.setInvalid(E);<br>
+<br>
+  QualType Pointee = E->getType()->castAs<PointerTy<wbr>pe>()->getPointeeType();<br>
+  Result.addUnsizedArray(Info, Pointee);<br>
+  return true;<br>
+}<br>
+<br>
 namespace {<br>
 class PointerExprEvaluator<br>
   : public ExprEvaluatorBase<PointerExprE<wbr>valuator> {<br>
@@ -5088,6 +5293,8 @@ class PointerExprEvaluator<br>
     Result.set(E);<br>
     return true;<br>
   }<br>
+<br>
+  bool visitNonBuiltinCallExpr(const CallExpr *E);<br>
 public:<br>
<br>
   PointerExprEvaluator(EvalInfo &info, LValue &Result)<br>
@@ -5270,6 +5477,19 @@ bool PointerExprEvaluator::VisitCas<wbr>tExpr<br>
<br>
   case CK_FunctionToPointerDecay:<br>
     return EvaluateLValue(SubExpr, Result, Info);<br>
+<br>
+  case CK_LValueToRValue: {<br>
+    LValue LVal;<br>
+    if (!EvaluateLValue(E->getSubExpr<wbr>(), LVal, Info))<br>
+      return false;<br>
+<br>
+    APValue RVal;<br>
+    // Note, we use the subexpression's type in order to retain cv-qualifiers.<br>
+    if (!handleLValueToRValueConversi<wbr>on(Info, E, E->getSubExpr()->getType(),<br>
+                                        LVal, RVal))<br>
+      return evaluateLValueAsAllocSize(Info<wbr>, LVal.Base, Result);<br>
+    return Success(RVal, E);<br>
+  }<br>
   }<br>
<br>
   return ExprEvaluatorBaseTy::VisitCast<wbr>Expr(E);<br>
@@ -5307,6 +5527,20 @@ static CharUnits GetAlignOfExpr(EvalInfo<br>
   return GetAlignOfType(Info, E->getType());<br>
 }<br>
<br>
+// To be clear: this happily visits unsupported builtins. Better name welcomed.<br>
+bool PointerExprEvaluator::visitNon<wbr>BuiltinCallExpr(const CallExpr *E) {<br>
+  if (ExprEvaluatorBaseTy::VisitCal<wbr>lExpr(E))<br>
+    return true;<br>
+<br>
+  if (!(Info.allowInvalidBaseExpr() && getAllocSizeAttr(E)))<br>
+    return false;<br>
+<br>
+  Result.setInvalid(E);<br>
+  QualType PointeeTy = E->getType()->castAs<PointerTy<wbr>pe>()->getPointeeType();<br>
+  Result.addUnsizedArray(Info, PointeeTy);<br>
+  return true;<br>
+}<br>
+<br>
 bool PointerExprEvaluator::VisitCal<wbr>lExpr(const CallExpr *E) {<br>
   if (IsStringLiteralCall(E))<br>
     return Success(E);<br>
@@ -5314,7 +5548,7 @@ bool PointerExprEvaluator::VisitCal<wbr>lExpr<br>
   if (unsigned BuiltinOp = E->getBuiltinCallee())<br>
     return VisitBuiltinCallExpr(E, BuiltinOp);<br>
<br>
-  return ExprEvaluatorBaseTy::VisitCall<wbr>Expr(E);<br>
+  return visitNonBuiltinCallExpr(E);<br>
 }<br>
<br>
 bool PointerExprEvaluator::VisitBui<wbr>ltinCallExpr(const CallExpr *E,<br>
@@ -5473,7 +5707,7 @@ bool PointerExprEvaluator::VisitBui<wbr>ltinC<br>
   }<br>
<br>
   default:<br>
-    return ExprEvaluatorBaseTy::VisitCall<wbr>Expr(E);<br>
+    return visitNonBuiltinCallExpr(E);<br>
   }<br>
 }<br>
<br>
@@ -6512,8 +6746,6 @@ public:<br>
   bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);<br>
   bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);<br>
<br>
-private:<br>
-  bool TryEvaluateBuiltinObjectSize(c<wbr>onst CallExpr *E, unsigned Type);<br>
   // FIXME: Missing: array subscript of vector, member of vector<br>
 };<br>
 } // end anonymous namespace<br>
@@ -6785,7 +7017,7 @@ static QualType getObjectType(APValue::L<br>
 }<br>
<br>
 /// A more selective version of E->IgnoreParenCasts for<br>
-/// TryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only<br>
+/// tryEvaluateBuiltinObjectSize. This ignores some casts/parens that serve only<br>
 /// to change the type of E.<br>
 /// Ex. For E = `(short*)((char*)(&foo))`, returns `&foo`<br>
 ///<br>
@@ -6852,39 +7084,51 @@ static bool isDesignatorAtObjectEnd(cons<br>
     }<br>
   }<br>
<br>
+  unsigned I = 0;<br>
   QualType BaseType = getType(Base);<br>
-  for (int I = 0, E = LVal.Designator.Entries.size()<wbr>; I != E; ++I) {<br>
+  if (LVal.Designator.FirstEntryIsA<wbr>nUnsizedArray) {<br>
+    assert(isBaseAnAllocSizeCall(B<wbr>ase) &&<br>
+           "Unsized array in non-alloc_size call?");<br>
+    // If this is an alloc_size base, we should ignore the initial array index<br>
+    ++I;<br>
+    BaseType = BaseType->castAs<PointerType>(<wbr>)->getPointeeType();<br>
+  }<br>
+<br>
+  for (unsigned E = LVal.Designator.Entries.size()<wbr>; I != E; ++I) {<br>
+    const auto &Entry = LVal.Designator.Entries[I];<br>
     if (BaseType->isArrayType()) {<br>
       // Because __builtin_object_size treats arrays as objects, we can ignore<br>
       // the index iff this is the last array in the Designator.<br>
       if (I + 1 == E)<br>
         return true;<br>
-      auto *CAT = cast<ConstantArrayType>(Ctx.ge<wbr>tAsArrayType(BaseType));<br>
-      uint64_t Index = LVal.Designator.Entries[I].Arr<wbr>ayIndex;<br>
+      const auto *CAT = cast<ConstantArrayType>(Ctx.ge<wbr>tAsArrayType(BaseType));<br>
+      uint64_t Index = Entry.ArrayIndex;<br>
       if (Index + 1 != CAT->getSize())<br>
         return false;<br>
       BaseType = CAT->getElementType();<br>
     } else if (BaseType->isAnyComplexType()) {<br>
-      auto *CT = BaseType->castAs<ComplexType>(<wbr>);<br>
-      uint64_t Index = LVal.Designator.Entries[I].Arr<wbr>ayIndex;<br>
+      const auto *CT = BaseType->castAs<ComplexType>(<wbr>);<br>
+      uint64_t Index = Entry.ArrayIndex;<br>
       if (Index != 1)<br>
         return false;<br>
       BaseType = CT->getElementType();<br>
-    } else if (auto *FD = getAsField(LVal.Designator.Ent<wbr>ries[I])) {<br>
+    } else if (auto *FD = getAsField(Entry)) {<br>
       bool Invalid;<br>
       if (!IsLastOrInvalidFieldDecl(FD, Invalid))<br>
         return Invalid;<br>
       BaseType = FD->getType();<br>
     } else {<br>
-      assert(getAsBaseClass(LVal.Des<wbr>ignator.Entries[I]) != nullptr &&<br>
-             "Expecting cast to a base class");<br>
+      assert(getAsBaseClass(Entry) && "Expecting cast to a base class");<br>
       return false;<br>
     }<br>
   }<br>
   return true;<br>
 }<br>
<br>
-/// Tests to see if the LValue has a designator (that isn't necessarily valid).<br>
+/// Tests to see if the LValue has a user-specified designator (that isn't<br>
+/// necessarily valid). Note that this always returns 'true' if the LValue has<br>
+/// an unsized array as its first designator entry, because there's currently no<br>
+/// way to tell if the user typed *foo or foo[0].<br>
 static bool refersToCompleteObject(const LValue &LVal) {<br>
   if (LVal.Designator.Invalid || !LVal.Designator.Entries.empty<wbr>())<br>
     return false;<br>
@@ -6892,42 +7136,142 @@ static bool refersToCompleteObject(const<br>
   if (!LVal.InvalidBase)<br>
     return true;<br>
<br>
-  auto *E = LVal.Base.dyn_cast<const Expr *>();<br>
-  (void)E;<br>
-  assert(E != nullptr && isa<MemberExpr>(E));<br>
-  return false;<br>
+  // If `E` is a MemberExpr, then the first part of the designator is hiding in<br>
+  // the LValueBase.<br>
+  const auto *E = LVal.Base.dyn_cast<const Expr *>();<br>
+  return !E || !isa<MemberExpr>(E);<br>
+}<br>
+<br>
+/// Attempts to detect a user writing into a piece of memory that's impossible<br>
+/// to figure out the size of by just using types.<br>
+static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal) {<br>
+  const SubobjectDesignator &Designator = LVal.Designator;<br>
+  // Notes:<br>
+  // - Users can only write off of the end when we have an invalid base. Invalid<br>
+  //   bases imply we don't know where the memory came from.<br>
+  // - We used to be a bit more aggressive here; we'd only be conservative if<br>
+  //   the array at the end was flexible, or if it had 0 or 1 elements. This<br>
+  //   broke some common standard library extensions (PR30346), but was<br>
+  //   otherwise seemingly fine. It may be useful to reintroduce this behavior<br>
+  //   with some sort of whitelist. OTOH, it seems that GCC is always<br>
+  //   conservative with the last element in structs (if it's an array), so our<br>
+  //   current behavior is more compatible than a whitelisting approach would<br>
+  //   be.<br>
+  return LVal.InvalidBase &&<br>
+         Designator.Entries.size() == Designator.MostDerivedPathLeng<wbr>th &&<br>
+         Designator.MostDerivedIsArray<wbr>Element &&<br>
+         isDesignatorAtObjectEnd(Ctx, LVal);<br>
+}<br>
+<br>
+/// Converts the given APInt to CharUnits, assuming the APInt is unsigned.<br>
+/// Fails if the conversion would cause loss of precision.<br>
+static bool convertUnsignedAPIntToCharUnit<wbr>s(const llvm::APInt &Int,<br>
+                                            CharUnits &Result) {<br>
+  auto CharUnitsMax = std::numeric_limits<CharUnits:<wbr>:QuantityType>::max();<br>
+  if (Int.ugt(CharUnitsMax))<br>
+    return false;<br>
+  Result = CharUnits::fromQuantity(Int.ge<wbr>tZExtValue());<br>
+  return true;<br>
 }<br>
<br>
-/// Tries to evaluate the __builtin_object_size for @p E. If successful, returns<br>
-/// true and stores the result in @p Size.<br>
+/// Helper for tryEvaluateBuiltinObjectSize -- Given an LValue, this will<br>
+/// determine how many bytes exist from the beginning of the object to either<br>
+/// the end of the current subobject, or the end of the object itself, depending<br>
+/// on what the LValue looks like + the value of Type.<br>
 ///<br>
-/// If @p WasError is non-null, this will report whether the failure to evaluate<br>
-/// is to be treated as an Error in IntExprEvaluator.<br>
-static bool tryEvaluateBuiltinObjectSize(c<wbr>onst Expr *E, unsigned Type,<br>
-                                         EvalInfo &Info, uint64_t &Size,<br>
-                                         bool *WasError = nullptr) {<br>
-  if (WasError != nullptr)<br>
-    *WasError = false;<br>
-<br>
-  auto Error = [&](const Expr *E) {<br>
-    if (WasError != nullptr)<br>
-      *WasError = true;<br>
+/// If this returns false, the value of Result is undefined.<br>
+static bool determineEndOffset(EvalInfo &Info, SourceLocation ExprLoc,<br>
+                               unsigned Type, const LValue &LVal,<br>
+                               CharUnits &EndOffset) {<br>
+  // __builtin_object_size(&foo, N) == __builtin_object_size(&foo, (N & ~1U)).<br>
+  // (Where foo is an expression that has no designator). Hence, if we've no<br>
+  // designator, we can ignore the subobject bit.<br>
+  bool EvaluateAsCompleteObject =<br>
+      !(Type & 1) || LVal.Designator.isMostDerivedA<wbr>nUnsizedArray() ||<br>
+      refersToCompleteObject(LVal);<br>
+<br>
+  // We want to evaluate the size of the entire object. This is a valid fallback<br>
+  // for when Type=1 and the designator is invalid, because we're asked for an<br>
+  // upper-bound.<br>
+  if (LVal.Designator.Invalid || EvaluateAsCompleteObject) {<br>
+    // We can't give a correct lower bound for Type=3 if the designator is<br>
+    // invalid and we're meant to be evaluating it.<br>
+    if (Type == 3 && LVal.Designator.Invalid && !EvaluateAsCompleteObject)<br>
+      return false;<br>
+<br>
+    llvm::APInt APEndOffset;<br>
+    if (isBaseAnAllocSizeCall(LVal.ge<wbr>tLValueBase()) &&<br>
+        getBytesReturnedByAllocSizeCal<wbr>l(Info.Ctx, LVal, APEndOffset))<br>
+      return convertUnsignedAPIntToCharUnit<wbr>s(APEndOffset, EndOffset);<br>
+<br>
+    if (LVal.InvalidBase)<br>
+      return false;<br>
+<br>
+    QualType BaseTy = getObjectType(LVal.getLValueBa<wbr>se());<br>
+    return !BaseTy.isNull() && HandleSizeof(Info, ExprLoc, BaseTy, EndOffset);<br>
+  }<br>
+<br>
+  // We want to evaluate the size of a subobject.<br>
+  const SubobjectDesignator &Designator = LVal.Designator;<br>
+<br>
+  // The following is a moderately common idiom in C:<br>
+  //<br>
+  // struct Foo { int a; char c[1]; };<br>
+  // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));<br>
+  // strcpy(&F->c[0], Bar);<br>
+  //<br>
+  // In order to not break too much legacy code, we need to support it.<br>
+  if (isUserWritingOffTheEnd(Info.C<wbr>tx, LVal)) {<br>
+    // If we can resolve this to an alloc_size call, we can hand that back,<br>
+    // because we know for certain how many bytes there are to write to.<br>
+    llvm::APInt APEndOffset;<br>
+    if (isBaseAnAllocSizeCall(LVal.ge<wbr>tLValueBase()) &&<br>
+        getBytesReturnedByAllocSizeCal<wbr>l(Info.Ctx, LVal, APEndOffset))<br>
+      return convertUnsignedAPIntToCharUnit<wbr>s(APEndOffset, EndOffset);<br>
+<br>
+    // If we cannot determine the size of the initial allocation, then we can't<br>
+    // given an accurate upper-bound. However, we are still able to give<br>
+    // conservative lower-bounds for Type=3.<br>
+    if (Type == 1)<br>
+      return false;<br>
+  }<br>
+<br>
+  CharUnits BytesPerElem;<br>
+  if (!HandleSizeof(Info, ExprLoc, Designator.MostDerivedType, BytesPerElem))<br>
     return false;<br>
-  };<br>
<br>
-  auto Success = [&](uint64_t S, const Expr *E) {<br>
-    Size = S;<br>
-    return true;<br>
-  };<br>
+  // According to the GCC documentation, we want the size of the subobject<br>
+  // denoted by the pointer. But that's not quite right -- what we actually<br>
+  // want is the size of the immediately-enclosing array, if there is one.<br>
+  int64_t ElemsRemaining;<br>
+  if (Designator.MostDerivedIsArray<wbr>Element &&<br>
+      Designator.Entries.size() == Designator.MostDerivedPathLeng<wbr>th) {<br>
+    uint64_t ArraySize = Designator.getMostDerivedArray<wbr>Size();<br>
+    uint64_t ArrayIndex = Designator.Entries.back().Arra<wbr>yIndex;<br>
+    ElemsRemaining = ArraySize <= ArrayIndex ? 0 : ArraySize - ArrayIndex;<br>
+  } else {<br>
+    ElemsRemaining = Designator.isOnePastTheEnd() ? 0 : 1;<br>
+  }<br>
+<br>
+  EndOffset = LVal.getLValueOffset() + BytesPerElem * ElemsRemaining;<br>
+  return true;<br>
+}<br>
<br>
+/// \brief Tries to evaluate the __builtin_object_size for @p E. If successful,<br>
+/// returns true and stores the result in @p Size.<br>
+///<br>
+/// If @p WasError is non-null, this will report whether the failure to evaluate<br>
+/// is to be treated as an Error in IntExprEvaluator.<br>
+static bool tryEvaluateBuiltinObjectSize(c<wbr>onst Expr *E, unsigned Type,<br>
+                                         EvalInfo &Info, uint64_t &Size) {<br>
   // Determine the denoted object.<br>
-  LValue Base;<br>
+  LValue LVal;<br>
   {<br>
     // The operand of __builtin_object_size is never evaluated for side-effects.<br>
     // If there are any, but we can determine the pointed-to object anyway, then<br>
     // ignore the side-effects.<br>
     SpeculativeEvaluationRAII SpeculativeEval(Info);<br>
-    FoldOffsetRAII Fold(Info, Type & 1);<br>
+    FoldOffsetRAII Fold(Info);<br>
<br>
     if (E->isGLValue()) {<br>
       // It's possible for us to be given GLValues if we're called via<br>
@@ -6935,122 +7279,29 @@ static bool tryEvaluateBuiltinObjectSize<br>
       APValue RVal;<br>
       if (!EvaluateAsRValue(Info, E, RVal))<br>
         return false;<br>
-      Base.setFrom(Info.Ctx, RVal);<br>
-    } else if (!EvaluatePointer(ignorePointe<wbr>rCastsAndParens(E), Base, Info))<br>
+      LVal.setFrom(Info.Ctx, RVal);<br>
+    } else if (!EvaluatePointer(ignorePointe<wbr>rCastsAndParens(E), LVal, Info))<br>
       return false;<br>
   }<br>
<br>
-  CharUnits BaseOffset = Base.getLValueOffset();<br>
   // If we point to before the start of the object, there are no accessible<br>
   // bytes.<br>
-  if (BaseOffset.isNegative())<br>
-    return Success(0, E);<br>
-<br>
-  // In the case where we're not dealing with a subobject, we discard the<br>
-  // subobject bit.<br>
-  bool SubobjectOnly = (Type & 1) != 0 && !refersToCompleteObject(Base);<br>
-<br>
-  // If Type & 1 is 0, we need to be able to statically guarantee that the bytes<br>
-  // exist. If we can't verify the base, then we can't do that.<br>
-  //<br>
-  // As a special case, we produce a valid object size for an unknown object<br>
-  // with a known designator if Type & 1 is 1. For instance:<br>
-  //<br>
-  //   extern struct X { char buff[32]; int a, b, c; } *p;<br>
-  //   int a = __builtin_object_size(p->buff + 4, 3); // returns 28<br>
-  //   int b = __builtin_object_size(p->buff + 4, 2); // returns 0, not 40<br>
-  //<br>
-  // This matches GCC's behavior.<br>
-  if (Base.InvalidBase && !SubobjectOnly)<br>
-    return Error(E);<br>
-<br>
-  // If we're not examining only the subobject, then we reset to a complete<br>
-  // object designator<br>
-  //<br>
-  // If Type is 1 and we've lost track of the subobject, just find the complete<br>
-  // object instead. (If Type is 3, that's not correct behavior and we should<br>
-  // return 0 instead.)<br>
-  LValue End = Base;<br>
-  if (!SubobjectOnly || (End.Designator.Invalid && Type == 1)) {<br>
-    QualType T = getObjectType(End.getLValueBas<wbr>e());<br>
-    if (T.isNull())<br>
-      End.Designator.setInvalid();<br>
-    else {<br>
-      End.Designator = SubobjectDesignator(T);<br>
-      End.Offset = CharUnits::Zero();<br>
-    }<br>
+  if (LVal.getLValueOffset().isNega<wbr>tive()) {<br>
+    Size = 0;<br>
+    return true;<br>
   }<br>
<br>
-  // If it is not possible to determine which objects ptr points to at compile<br>
-  // time, __builtin_object_size should return (size_t) -1 for type 0 or 1<br>
-  // and (size_t) 0 for type 2 or 3.<br>
-  if (End.Designator.Invalid)<br>
+  CharUnits EndOffset;<br>
+  if (!determineEndOffset(Info, E->getExprLoc(), Type, LVal, EndOffset))<br>
     return false;<br>
<br>
-  // According to the GCC documentation, we want the size of the subobject<br>
-  // denoted by the pointer. But that's not quite right -- what we actually<br>
-  // want is the size of the immediately-enclosing array, if there is one.<br>
-  int64_t AmountToAdd = 1;<br>
-  if (End.Designator.MostDerivedIsA<wbr>rrayElement &&<br>
-      End.Designator.Entries.size() == End.Designator.MostDerivedPath<wbr>Length) {<br>
-    // We got a pointer to an array. Step to its end.<br>
-    AmountToAdd = End.Designator.MostDerivedArra<wbr>ySize -<br>
-                  End.Designator.Entries.back().<wbr>ArrayIndex;<br>
-  } else if (End.Designator.isOnePastTheEn<wbr>d()) {<br>
-    // We're already pointing at the end of the object.<br>
-    AmountToAdd = 0;<br>
-  }<br>
-<br>
-  QualType PointeeType = End.Designator.MostDerivedType<wbr>;<br>
-  assert(!PointeeType.isNull());<br>
-  if (PointeeType->isIncompleteType<wbr>() || PointeeType->isFunctionType())<br>
-    return Error(E);<br>
-<br>
-  if (!HandleLValueArrayAdjustment(<wbr>Info, E, End, End.Designator.MostDerivedType<wbr>,<br>
-                                   AmountToAdd))<br>
-    return false;<br>
-<br>
-  auto EndOffset = End.getLValueOffset();<br>
-<br>
-  // The following is a moderately common idiom in C:<br>
-  //<br>
-  // struct Foo { int a; char c[1]; };<br>
-  // struct Foo *F = (struct Foo *)malloc(sizeof(struct Foo) + strlen(Bar));<br>
-  // strcpy(&F->c[0], Bar);<br>
-  //<br>
-  // So, if we see that we're examining an array at the end of a struct with an<br>
-  // unknown base, we give up instead of breaking code that behaves this way.<br>
-  // Note that we only do this when Type=1, because Type=3 is a lower bound, so<br>
-  // answering conservatively is fine.<br>
-  //<br>
-  // We used to be a bit more aggressive here; we'd only be conservative if the<br>
-  // array at the end was flexible, or if it had 0 or 1 elements. This broke<br>
-  // some common standard library extensions (PR30346), but was otherwise<br>
-  // seemingly fine. It may be useful to reintroduce this behavior with some<br>
-  // sort of whitelist. OTOH, it seems that GCC is always conservative with the<br>
-  // last element in structs (if it's an array), so our current behavior is more<br>
-  // compatible than a whitelisting approach would be.<br>
-  if (End.InvalidBase && SubobjectOnly && Type == 1 &&<br>
-      End.Designator.Entries.size() == End.Designator.MostDerivedPath<wbr>Length &&<br>
-      End.Designator.MostDerivedIsAr<wbr>rayElement &&<br>
-      isDesignatorAtObjectEnd(Info.C<wbr>tx, End))<br>
-    return false;<br>
-<br>
-  if (BaseOffset > EndOffset)<br>
-    return Success(0, E);<br>
-<br>
-  return Success((EndOffset - BaseOffset).getQuantity(), E);<br>
-}<br>
-<br>
-bool IntExprEvaluator::TryEvaluateB<wbr>uiltinObjectSize(const CallExpr *E,<br>
-                                                    unsigned Type) {<br>
-  uint64_t Size;<br>
-  bool WasError;<br>
-  if (::tryEvaluateBuiltinObjectSiz<wbr>e(E->getArg(0), Type, Info, Size, &WasError))<br>
-    return Success(Size, E);<br>
-  if (WasError)<br>
-    return Error(E);<br>
-  return false;<br>
+  // If we've fallen outside of the end offset, just pretend there's nothing to<br>
+  // write to/read from.<br>
+  if (EndOffset <= LVal.getLValueOffset())<br>
+    Size = 0;<br>
+  else<br>
+    Size = (EndOffset - LVal.getLValueOffset()).getQua<wbr>ntity();<br>
+  return true;<br>
 }<br>
<br>
 bool IntExprEvaluator::VisitCallExp<wbr>r(const CallExpr *E) {<br>
@@ -7072,8 +7323,9 @@ bool IntExprEvaluator::VisitBuiltin<wbr>CallE<br>
         E->getArg(1)->EvaluateKnownCo<wbr>nstInt(Info.Ctx).getZExtValue(<wbr>);<br>
     assert(Type <= 3 && "unexpected type");<br>
<br>
-    if (TryEvaluateBuiltinObjectSize(<wbr>E, Type))<br>
-      return true;<br>
+    uint64_t Size;<br>
+    if (tryEvaluateBuiltinObjectSize(<wbr>E->getArg(0), Type, Info, Size))<br>
+      return Success(Size, E);<br>
<br>
     if (E->getArg(0)->HasSideEffects(<wbr>Info.Ctx))<br>
       return Success((Type & 2) ? 0 : -1, E);<br>
@@ -7086,7 +7338,7 @@ bool IntExprEvaluator::VisitBuiltin<wbr>CallE<br>
     case EvalInfo::EM_ConstantFold:<br>
     case EvalInfo::EM_EvaluateForOverfl<wbr>ow:<br>
     case EvalInfo::EM_IgnoreSideEffects<wbr>:<br>
-    case EvalInfo::EM_DesignatorFold:<br>
+    case EvalInfo::EM_OffsetFold:<br>
       // Leave it to IR generation.<br>
       return Error(E);<br>
     case EvalInfo::EM_ConstantExpressio<wbr>nUnevaluated:<br>
@@ -10189,5 +10441,5 @@ bool Expr::tryEvaluateObjectSize(ui<wbr>nt64_<br>
<br>
   Expr::EvalStatus Status;<br>
   EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantFold);<br>
-  return ::tryEvaluateBuiltinObjectSize<wbr>(this, Type, Info, Result);<br>
+  return tryEvaluateBuiltinObjectSize(t<wbr>his, Type, Info, Result);<br>
 }<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGBlocks<wbr>.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/CodeGen/CG<wbr>Blocks.cpp?rev=290149&r1=29014<wbr>8&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGBlocks<wbr>.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGBlocks<wbr>.cpp Mon Dec 19 19:05:42 2016<br>
@@ -686,6 +686,8 @@ llvm::Value *CodeGenFunction::EmitBlockL<br>
   // If the block has no captures, we won't have a pre-computed<br>
   // layout for it.<br>
   if (!blockExpr->getBlockDecl()->h<wbr>asCaptures()) {<br>
+    if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmit<wbr>ted(blockExpr))<br>
+      return Block;<br>
     CGBlockInfo blockInfo(blockExpr->getBlockD<wbr>ecl(), CurFn->getName());<br>
     computeBlockInfo(CGM, this, blockInfo);<br>
     blockInfo.BlockExpression = blockExpr;<br>
@@ -1047,9 +1049,19 @@ Address CodeGenFunction::GetAddrOfBloc<wbr>kD<br>
   return addr;<br>
 }<br>
<br>
+void CodeGenModule::setAddrOfGlobal<wbr>Block(const BlockExpr *BE,<br>
+                                         llvm::Constant *Addr) {<br>
+  bool Ok = EmittedGlobalBlocks.insert(std<wbr>::make_pair(BE, Addr)).second;<br>
+  (void)Ok;<br>
+  assert(Ok && "Trying to replace an already-existing global block!");<br>
+}<br>
+<br>
 llvm::Constant *<br>
 CodeGenModule::GetAddrOfGloba<wbr>lBlock(const BlockExpr *BE,<br>
                                     StringRef Name) {<br>
+  if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(<wbr>BE))<br>
+    return Block;<br>
+<br>
   CGBlockInfo blockInfo(BE->getBlockDecl(), Name);<br>
   blockInfo.BlockExpression = BE;<br>
<br>
@@ -1074,6 +1086,11 @@ static llvm::Constant *buildGlobalBlock(<br>
                                         const CGBlockInfo &blockInfo,<br>
                                         llvm::Constant *blockFn) {<br>
   assert(blockInfo.CanBeGlobal)<wbr>;<br>
+  // Callers should detect this case on their own: calling this function<br>
+  // generally requires computing layout information, which is a waste of time<br>
+  // if we've already emitted this block.<br>
+  assert(!CGM.getAddrOfGlobalBlo<wbr>ckIfEmitted(blockInfo.BlockExp<wbr>ression) &&<br>
+         "Refusing to re-emit a global block.");<br>
<br>
   // Generate the constants for the block literal initializer.<br>
   ConstantInitBuilder builder(CGM);<br>
@@ -1103,9 +1120,12 @@ static llvm::Constant *buildGlobalBlock(<br>
                                  /*constant*/ true);<br>
<br>
   // Return a constant of the appropriately-casted type.<br>
-  llvm::Type *requiredType =<br>
+  llvm::Type *RequiredType =<br>
     CGM.getTypes().ConvertType(bl<wbr>ockInfo.getBlockExpr()->getTyp<wbr>e());<br>
-  return llvm::ConstantExpr::getBitCast<wbr>(literal, requiredType);<br>
+  llvm::Constant *Result =<br>
+      llvm::ConstantExpr::getBitCast<wbr>(literal, RequiredType);<br>
+  CGM.setAddrOfGlobalBlock(block<wbr>Info.BlockExpression, Result);<br>
+  return Result;<br>
 }<br>
<br>
 void CodeGenFunction::setBlockConte<wbr>xtParameter(const ImplicitParamDecl *D,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/CodeGen/CG<wbr>Call.cpp?rev=290149&r1=290148&<wbr>r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCall.c<wbr>pp Mon Dec 19 19:05:42 2016<br>
@@ -1683,6 +1683,14 @@ void CodeGenModule::ConstructAttrib<wbr>uteLi<br>
<br>
     HasAnyX86InterruptAttr = TargetDecl->hasAttr<AnyX86Inte<wbr>rruptAttr>();<br>
     HasOptnone = TargetDecl->hasAttr<OptimizeNo<wbr>neAttr>();<br>
+    if (auto *AllocSize = TargetDecl->getAttr<AllocSizeA<wbr>ttr>()) {<br>
+      Optional<unsigned> NumElemsParam;<br>
+      // alloc_size args are base-1, 0 means not present.<br>
+      if (unsigned N = AllocSize->getNumElemsParam())<br>
+        NumElemsParam = N - 1;<br>
+      FuncAttrs.addAllocSizeAttr(All<wbr>ocSize->getElemSizeParam() - 1,<br>
+                                 NumElemsParam);<br>
+    }<br>
   }<br>
<br>
   // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenF<wbr>unction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/CodeGen/Co<wbr>deGenFunction.h?rev=290149&r1=<wbr>290148&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CodeGenF<wbr>unction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenF<wbr>unction.h Mon Dec 19 19:05:42 2016<br>
@@ -1499,7 +1499,6 @@ public:<br>
   //===------------------------<wbr>------------------------------<wbr>--------------===//<br>
<br>
   llvm::Value *EmitBlockLiteral(const BlockExpr *);<br>
-  llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);<br>
   static void destroyBlockInfos(CGBlockInfo *info);<br>
<br>
   llvm::Function *GenerateBlockFunction(GlobalD<wbr>ecl GD,<br>
@@ -2726,6 +2725,9 @@ public:<br>
                                   OMPPrivateScope &LoopScope);<br>
<br>
 private:<br>
+  /// Helpers for blocks<br>
+  llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);<br>
+<br>
   /// Helpers for the OpenMP loop directives.<br>
   void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit);<br>
   void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic = false);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenM<wbr>odule.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/CodeGen/Co<wbr>deGenModule.h?rev=290149&r1=29<wbr>0148&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CodeGenM<wbr>odule.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenM<wbr>odule.h Mon Dec 19 19:05:42 2016<br>
@@ -455,6 +455,10 @@ private:<br>
   bool isTriviallyRecursive(const FunctionDecl *F);<br>
   bool shouldEmitFunction(GlobalDecl GD);<br>
<br>
+  /// Map of the global blocks we've emitted, so that we don't have to re-emit<br>
+  /// them if the constexpr evaluator gets aggressive.<br>
+  llvm::DenseMap<const BlockExpr *, llvm::Constant *> EmittedGlobalBlocks;<br>
+<br>
   /// @name Cache for Blocks Runtime Globals<br>
   /// @{<br>
<br>
@@ -776,6 +780,16 @@ public:<br>
<br>
   /// Gets the address of a block which requires no captures.<br>
   llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, StringRef Name);<br>
+<br>
+  /// Returns the address of a block which requires no caputres, or null if<br>
+  /// we've yet to emit the block for BE.<br>
+  llvm::Constant *getAddrOfGlobalBlockIfEmitted<wbr>(const BlockExpr *BE) {<br>
+    return EmittedGlobalBlocks.lookup(BE)<wbr>;<br>
+  }<br>
+<br>
+  /// Notes that BE's global block is available via Addr. Asserts that BE<br>
+  /// isn't already emitted.<br>
+  void setAddrOfGlobalBlock(const BlockExpr *BE, llvm::Constant *Addr);<br>
<br>
   /// Return a pointer to a constant CFString object for the given string.<br>
   ConstantAddress GetAddrOfConstantCFString(cons<wbr>t StringLiteral *Literal);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDeclAtt<wbr>r.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaD<wbr>eclAttr.cpp?rev=290149&r1=2901<wbr>48&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaDeclAtt<wbr>r.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDeclAtt<wbr>r.cpp Mon Dec 19 19:05:42 2016<br>
@@ -246,6 +246,28 @@ static bool checkUInt32Argument(Sema &S,<br>
   return true;<br>
 }<br>
<br>
+/// \brief Wrapper around checkUInt32Argument, with an extra check to be sure<br>
+/// that the result will fit into a regular (signed) int. All args have the same<br>
+/// purpose as they do in checkUInt32Argument.<br>
+static bool checkPositiveIntArgument(Sema &S, const AttributeList &Attr,<br>
+                                     const Expr *Expr, int &Val,<br>
+                                     unsigned Idx = UINT_MAX) {<br>
+  uint32_t UVal;<br>
+  if (!checkUInt32Argument(S, Attr, Expr, UVal, Idx))<br>
+    return false;<br>
+<br>
+  if (UVal > std::numeric_limits<int>::max(<wbr>)) {<br>
+    llvm::APSInt I(32); // for toString<br>
+    I = UVal;<br>
+    S.Diag(Expr->getExprLoc(), diag::err_ice_too_large)<br>
+        << I.toString(10, false) << 32 << /* Unsigned */ 0;<br>
+    return false;<br>
+  }<br>
+<br>
+  Val = UVal;<br>
+  return true;<br>
+}<br>
+<br>
 /// \brief Diagnose mutually exclusive attributes when present on a given<br>
 /// declaration. Returns true if diagnosed.<br>
 template <typename AttrTy><br>
@@ -730,6 +752,69 @@ static void handleAssertExclusiveLockAtt<br>
                                      Attr.getAttributeSpellingListI<wbr>ndex()));<br>
 }<br>
<br>
+/// \brief Checks to be sure that the given parameter number is inbounds, and is<br>
+/// an some integral type. Will emit appropriate diagnostics if this returns<br>
+/// false.<br>
+///<br>
+/// FuncParamNo is expected to be from the user, so is base-1. AttrArgNo is used<br>
+/// to actually retrieve the argument, so it's base-0.<br>
+static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,<br>
+                                    const AttributeList &Attr,<br>
+                                    unsigned FuncParamNo, unsigned AttrArgNo) {<br>
+  assert(Attr.isArgExpr(AttrArgN<wbr>o) && "Expected expression argument");<br>
+  uint64_t Idx;<br>
+  if (!checkFunctionOrMethodParamet<wbr>erIndex(S, FD, Attr, FuncParamNo,<br>
+                                           Attr.getArgAsExpr(AttrArgNo), Idx))<br>
+    return false;<br>
+<br>
+  const ParmVarDecl *Param = FD->getParamDecl(Idx);<br>
+  if (!Param->getType()->isIntegerT<wbr>ype() && !Param->getType()->isCharType(<wbr>)) {<br>
+    SourceLocation SrcLoc = Attr.getArgAsExpr(AttrArgNo)-><wbr>getLocStart();<br>
+    S.Diag(SrcLoc, diag::err_attribute_integers_o<wbr>nly)<br>
+        << Attr.getName() << Param->getSourceRange();<br>
+    return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {<br>
+  if (!checkAttributeAtLeastNumArgs<wbr>(S, Attr, 1) ||<br>
+      !checkAttributeAtMostNumArgs(S<wbr>, Attr, 2))<br>
+    return;<br>
+<br>
+  const auto *FD = cast<FunctionDecl>(D);<br>
+  if (!FD->getReturnType()->isPoint<wbr>erType()) {<br>
+    S.Diag(Attr.getLoc(), diag::warn_attribute_return_po<wbr>inters_only)<br>
+        << Attr.getName();<br>
+    return;<br>
+  }<br>
+<br>
+  const Expr *SizeExpr = Attr.getArgAsExpr(0);<br>
+  int SizeArgNo;<br>
+  // Paramater indices are 1-indexed, hence Index=1<br>
+  if (!checkPositiveIntArgument(S, Attr, SizeExpr, SizeArgNo, /*Index=*/1))<br>
+    return;<br>
+<br>
+  if (!checkParamIsIntegerType(S, FD, Attr, SizeArgNo, /*AttrArgNo=*/0))<br>
+    return;<br>
+<br>
+  // Args are 1-indexed, so 0 implies that the arg was not present<br>
+  int NumberArgNo = 0;<br>
+  if (Attr.getNumArgs() == 2) {<br>
+    const Expr *NumberExpr = Attr.getArgAsExpr(1);<br>
+    // Paramater indices are 1-based, hence Index=2<br>
+    if (!checkPositiveIntArgument(S, Attr, NumberExpr, NumberArgNo,<br>
+                                  /*Index=*/2))<br>
+      return;<br>
+<br>
+    if (!checkParamIsIntegerType(S, FD, Attr, NumberArgNo, /*AttrArgNo=*/1))<br>
+      return;<br>
+  }<br>
+<br>
+  D->addAttr(::new (S.Context) AllocSizeAttr(<br>
+      Attr.getRange(), S.Context, SizeArgNo, NumberArgNo,<br>
+      Attr.getAttributeSpellingListI<wbr>ndex()));<br>
+}<br>
<br>
 static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,<br>
                                       const AttributeList &Attr,<br>
@@ -5552,6 +5637,9 @@ static void ProcessDeclAttribute(Sema &S<br>
   case AttributeList::AT_AlignValue:<br>
     handleAlignValueAttr(S, D, Attr);<br>
     break;<br>
+  case AttributeList::AT_AllocSize:<br>
+    handleAllocSizeAttr(S, D, Attr);<br>
+    break;<br>
   case AttributeList::AT_AlwaysInline<wbr>:<br>
     handleAlwaysInlineAttr(S, D, Attr);<br>
     break;<br>
<br>
Added: cfe/trunk/test/CodeGen/alloc-s<wbr>ize.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/alloc-size.c?rev=290149&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/CodeGen/a<wbr>lloc-size.c?rev=290149&view=au<wbr>to</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGen/alloc-s<wbr>ize.c (added)<br>
+++ cfe/trunk/test/CodeGen/alloc-s<wbr>ize.c Mon Dec 19 19:05:42 2016<br>
@@ -0,0 +1,352 @@<br>
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s<br>
+<br>
+#define NULL ((void *)0)<br>
+<br>
+int gi;<br>
+<br>
+typedef unsigned long size_t;<br>
+<br>
+// CHECK-DAG-RE: define void @my_malloc({{.*}}) #[[MALLOC_ATTR_NUMBER:[0-9]+]]<br>
+// N.B. LLVM's allocsize arguments are base-0, whereas ours are base-1 (for<br>
+// compat with GCC)<br>
+// CHECK-DAG-RE: attributes #[[MALLOC_ATTR_NUMBER]] = {.*allocsize(0).*}<br>
+void *my_malloc(size_t) __attribute__((alloc_size(1)))<wbr>;<br>
+<br>
+// CHECK-DAG-RE: define void @my_calloc({{.*}}) #[[CALLOC_ATTR_NUMBER:[0-9]+]]<br>
+// CHECK-DAG-RE: attributes #[[CALLOC_ATTR_NUMBER]] = {.*allocsize(0, 1).*}<br>
+void *my_calloc(size_t, size_t) __attribute__((alloc_size(1, 2)));<br>
+<br>
+// CHECK-LABEL: @test1<br>
+void test1() {<br>
+  void *const vp = my_malloc(100);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 0);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 1);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 2);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 3);<br>
+<br>
+  void *const arr = my_calloc(100, 5);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 0);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 1);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 2);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 3);<br>
+<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(my_mallo<wbr>c(100), 0);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(my_mallo<wbr>c(100), 1);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(my_mallo<wbr>c(100), 2);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(my_mallo<wbr>c(100), 3);<br>
+<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(my_callo<wbr>c(100, 5), 0);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(my_callo<wbr>c(100, 5), 1);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(my_callo<wbr>c(100, 5), 2);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(my_callo<wbr>c(100, 5), 3);<br>
+<br>
+  void *const zeroPtr = my_malloc(0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(zeroPtr, 0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(my_mallo<wbr>c(0), 0);<br>
+<br>
+  void *const zeroArr1 = my_calloc(0, 1);<br>
+  void *const zeroArr2 = my_calloc(1, 0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(zeroArr1<wbr>, 0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(zeroArr2<wbr>, 0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(my_callo<wbr>c(1, 0), 0);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(my_callo<wbr>c(0, 1), 0);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test2<br>
+void test2() {<br>
+  void *const vp = my_malloc(gi);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(vp, 0);<br>
+<br>
+  void *const arr1 = my_calloc(gi, 1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr1, 0);<br>
+<br>
+  void *const arr2 = my_calloc(1, gi);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr2, 0);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test3<br>
+void test3() {<br>
+  char *const buf = (char *)my_calloc(100, 5);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(buf, 0);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(buf, 1);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(buf, 2);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(buf, 3);<br>
+}<br>
+<br>
+struct Data {<br>
+  int a;<br>
+  int t[10];<br>
+  char pad[3];<br>
+  char end[1];<br>
+};<br>
+<br>
+// CHECK-LABEL: @test5<br>
+void test5() {<br>
+  struct Data *const data = my_malloc(sizeof(*data));<br>
+  // CHECK: store i32 48<br>
+  gi = __builtin_object_size(data, 0);<br>
+  // CHECK: store i32 48<br>
+  gi = __builtin_object_size(data, 1);<br>
+  // CHECK: store i32 48<br>
+  gi = __builtin_object_size(data, 2);<br>
+  // CHECK: store i32 48<br>
+  gi = __builtin_object_size(data, 3);<br>
+<br>
+  // CHECK: store i32 40<br>
+  gi = __builtin_object_size(&data->t<wbr>[1], 0);<br>
+  // CHECK: store i32 36<br>
+  gi = __builtin_object_size(&data->t<wbr>[1], 1);<br>
+  // CHECK: store i32 40<br>
+  gi = __builtin_object_size(&data->t<wbr>[1], 2);<br>
+  // CHECK: store i32 36<br>
+  gi = __builtin_object_size(&data->t<wbr>[1], 3);<br>
+<br>
+  struct Data *const arr = my_calloc(sizeof(*data), 2);<br>
+  // CHECK: store i32 96<br>
+  gi = __builtin_object_size(arr, 0);<br>
+  // CHECK: store i32 96<br>
+  gi = __builtin_object_size(arr, 1);<br>
+  // CHECK: store i32 96<br>
+  gi = __builtin_object_size(arr, 2);<br>
+  // CHECK: store i32 96<br>
+  gi = __builtin_object_size(arr, 3);<br>
+<br>
+  // CHECK: store i32 88<br>
+  gi = __builtin_object_size(&arr->t[<wbr>1], 0);<br>
+  // CHECK: store i32 36<br>
+  gi = __builtin_object_size(&arr->t[<wbr>1], 1);<br>
+  // CHECK: store i32 88<br>
+  gi = __builtin_object_size(&arr->t[<wbr>1], 2);<br>
+  // CHECK: store i32 36<br>
+  gi = __builtin_object_size(&arr->t[<wbr>1], 3);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test6<br>
+void test6() {<br>
+  // Things that would normally trigger conservative estimates don't need to do<br>
+  // so when we know the source of the allocation.<br>
+  struct Data *const data = my_malloc(sizeof(*data) + 10);<br>
+  // CHECK: store i32 11<br>
+  gi = __builtin_object_size(data->en<wbr>d, 0);<br>
+  // CHECK: store i32 11<br>
+  gi = __builtin_object_size(data->en<wbr>d, 1);<br>
+  // CHECK: store i32 11<br>
+  gi = __builtin_object_size(data->en<wbr>d, 2);<br>
+  // CHECK: store i32 11<br>
+  gi = __builtin_object_size(data->en<wbr>d, 3);<br>
+<br>
+  struct Data *const arr = my_calloc(sizeof(*arr) + 5, 3);<br>
+  // AFAICT, GCC treats malloc and calloc identically. So, we should do the<br>
+  // same.<br>
+  //<br>
+  // Additionally, GCC ignores the initial array index when determining whether<br>
+  // we're writing off the end of an alloc_size base. e.g.<br>
+  //   arr[0].end<br>
+  //   arr[1].end<br>
+  //   arr[2].end<br>
+  // ...Are all considered "writing off the end", because there's no way to tell<br>
+  // with high accuracy if the user meant "allocate a single N-byte `Data`",<br>
+  // or "allocate M smaller `Data`s with extra padding".<br>
+<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr->end<wbr>, 0);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr->end<wbr>, 1);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr->end<wbr>, 2);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr->end<wbr>, 3);<br>
+<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr[0].e<wbr>nd, 0);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr[0].e<wbr>nd, 1);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr[0].e<wbr>nd, 2);<br>
+  // CHECK: store i32 112<br>
+  gi = __builtin_object_size(arr[0].e<wbr>nd, 3);<br>
+<br>
+  // CHECK: store i32 64<br>
+  gi = __builtin_object_size(arr[1].e<wbr>nd, 0);<br>
+  // CHECK: store i32 64<br>
+  gi = __builtin_object_size(arr[1].e<wbr>nd, 1);<br>
+  // CHECK: store i32 64<br>
+  gi = __builtin_object_size(arr[1].e<wbr>nd, 2);<br>
+  // CHECK: store i32 64<br>
+  gi = __builtin_object_size(arr[1].e<wbr>nd, 3);<br>
+<br>
+  // CHECK: store i32 16<br>
+  gi = __builtin_object_size(arr[2].e<wbr>nd, 0);<br>
+  // CHECK: store i32 16<br>
+  gi = __builtin_object_size(arr[2].e<wbr>nd, 1);<br>
+  // CHECK: store i32 16<br>
+  gi = __builtin_object_size(arr[2].e<wbr>nd, 2);<br>
+  // CHECK: store i32 16<br>
+  gi = __builtin_object_size(arr[2].e<wbr>nd, 3);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test7<br>
+void test7() {<br>
+  struct Data *const data = my_malloc(sizeof(*data) + 5);<br>
+  // CHECK: store i32 9<br>
+  gi = __builtin_object_size(data->pa<wbr>d, 0);<br>
+  // CHECK: store i32 3<br>
+  gi = __builtin_object_size(data->pa<wbr>d, 1);<br>
+  // CHECK: store i32 9<br>
+  gi = __builtin_object_size(data->pa<wbr>d, 2);<br>
+  // CHECK: store i32 3<br>
+  gi = __builtin_object_size(data->pa<wbr>d, 3);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test8<br>
+void test8() {<br>
+  // Non-const pointers aren't currently supported.<br>
+  void *buf = my_calloc(100, 5);<br>
+  // CHECK: @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)<br>
+  gi = __builtin_object_size(buf, 0);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(buf, 1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(buf, 2);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(buf, 3);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test9<br>
+void test9() {<br>
+  // Check to be sure that we unwrap things correctly.<br>
+  short *const buf0 = (my_malloc(100));<br>
+  short *const buf1 = (short*)(my_malloc(100));<br>
+  short *const buf2 = ((short*)(my_malloc(100)));<br>
+<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(buf0, 0);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(buf1, 0);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(buf2, 0);<br>
+}<br>
+<br>
+// CHECK-LABEL: @test10<br>
+void test10() {<br>
+  // Yay overflow<br>
+  short *const arr = my_calloc((size_t)-1 / 2 + 1, 2);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr, 0);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr, 1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr, 2);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(arr, 3);<br>
+<br>
+  // As an implementation detail, CharUnits can't handle numbers greater than or<br>
+  // equal to 2**63. Realistically, this shouldn't be a problem, but we should<br>
+  // be sure we don't emit crazy results for this case.<br>
+  short *const buf = my_malloc((size_t)-1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(buf, 0);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(buf, 1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(buf, 2);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(buf, 3);<br>
+<br>
+  short *const arr_big = my_calloc((size_t)-1 / 2 - 1, 2);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr_big, 0);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr_big, 1);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr_big, 2);<br>
+  // CHECK: store i32 0<br>
+  gi = __builtin_object_size(arr_big, 3);<br>
+}<br>
+<br>
+void *my_tiny_malloc(char) __attribute__((alloc_size(1)))<wbr>;<br>
+void *my_tiny_calloc(char, char) __attribute__((alloc_size(1, 2)));<br>
+<br>
+// CHECK-LABEL: @test11<br>
+void test11() {<br>
+  void *const vp = my_tiny_malloc(100);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 0);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 1);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 2);<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(vp, 3);<br>
+<br>
+  // N.B. This causes char overflow, but not size_t overflow, so it should be<br>
+  // supported.<br>
+  void *const arr = my_tiny_calloc(100, 5);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 0);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 1);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 2);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(arr, 3);<br>
+}<br>
+<br>
+void *my_signed_malloc(long) __attribute__((alloc_size(1)))<wbr>;<br>
+void *my_signed_calloc(long, long) __attribute__((alloc_size(1, 2)));<br>
+<br>
+// CHECK-LABEL: @test12<br>
+void test12() {<br>
+  // CHECK: store i32 100<br>
+  gi = __builtin_object_size(my_signe<wbr>d_malloc(100), 0);<br>
+  // CHECK: store i32 500<br>
+  gi = __builtin_object_size(my_signe<wbr>d_calloc(100, 5), 0);<br>
+<br>
+  void *const vp = my_signed_malloc(-2);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(vp, 0);<br>
+  // N.B. These get lowered to -1 because the function calls may have<br>
+  // side-effects, and we can't determine the objectsize.<br>
+  // CHECK: store i32 -1<br>
+  gi = __builtin_object_size(my_signe<wbr>d_malloc(-2), 0);<br>
+<br>
+  void *const arr1 = my_signed_calloc(-2, 1);<br>
+  void *const arr2 = my_signed_calloc(1, -2);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr1, 0);<br>
+  // CHECK: @llvm.objectsize<br>
+  gi = __builtin_object_size(arr2, 0);<br>
+  // CHECK: store i32 -1<br>
+  gi = __builtin_object_size(my_signe<wbr>d_calloc(1, -2), 0);<br>
+  // CHECK: store i32 -1<br>
+  gi = __builtin_object_size(my_signe<wbr>d_calloc(-2, 1), 0);<br>
+}<br>
<br>
Added: cfe/trunk/test/CodeGenCXX/allo<wbr>c-size.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alloc-size.cpp?rev=290149&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/CodeGenCX<wbr>X/alloc-size.cpp?rev=290149&vi<wbr>ew=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/allo<wbr>c-size.cpp (added)<br>
+++ cfe/trunk/test/CodeGenCXX/allo<wbr>c-size.cpp Mon Dec 19 19:05:42 2016<br>
@@ -0,0 +1,72 @@<br>
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s<br>
+<br>
+namespace templates {<br>
+void *my_malloc(int N) __attribute__((alloc_size(1)))<wbr>;<br>
+void *my_calloc(int N, int M) __attribute__((alloc_size(1, 2)));<br>
+<br>
+struct MyType {<br>
+  int arr[4];<br>
+};<br>
+<br>
+template <typename T> int callMalloc();<br>
+<br>
+template <typename T, int N> int callCalloc();<br>
+<br>
+// CHECK-LABEL: define i32 @_ZN9templates6testItEv()<br>
+int testIt() {<br>
+  // CHECK: call i32 @_ZN9templates10callMallocINS_<wbr>6MyTypeEEEiv<br>
+  // CHECK: call i32 @_ZN9templates10callCallocINS_<wbr>6MyTypeELi4EEEiv<br>
+  return callMalloc<MyType>() + callCalloc<MyType, 4>();<br>
+}<br>
+<br>
+// CHECK-LABEL: define linkonce_odr i32<br>
+// @_ZN9templates10callMallocINS_<wbr>6MyTypeEEEiv<br>
+template <typename T> int callMalloc() {<br>
+  static_assert(sizeof(T) == 16, "");<br>
+  // CHECK: ret i32 16<br>
+  return __builtin_object_size(my_mallo<wbr>c(sizeof(T)), 0);<br>
+}<br>
+<br>
+// CHECK-LABEL: define linkonce_odr i32<br>
+// @_ZN9templates10callCallocINS_<wbr>6MyTypeELi4EEEiv<br>
+template <typename T, int N> int callCalloc() {<br>
+  static_assert(sizeof(T) * N == 64, "");<br>
+  // CHECK: ret i32 64<br>
+  return __builtin_object_size(my_mallo<wbr>c(sizeof(T) * N), 0);<br>
+}<br>
+}<br>
+<br>
+namespace templated_alloc_size {<br>
+using size_t = unsigned long;<br>
+<br>
+// We don't need bodies for any of these, because they're only used in<br>
+// __builtin_object_size, and that shouldn't need anything but a function<br>
+// decl with alloc_size on it.<br>
+template <typename T><br>
+T *my_malloc(size_t N = sizeof(T)) __attribute__((alloc_size(1)))<wbr>;<br>
+<br>
+template <typename T><br>
+T *my_calloc(size_t M, size_t N = sizeof(T)) __attribute__((alloc_size(2, 1)));<br>
+<br>
+template <size_t N><br>
+void *dependent_malloc(size_t NT = N) __attribute__((alloc_size(1)))<wbr>;<br>
+<br>
+template <size_t N, size_t M><br>
+void *dependent_calloc(size_t NT = N, size_t MT = M)<br>
+    __attribute__((alloc_size(1, 2)));<br>
+<br>
+template <typename T, size_t M><br>
+void *dependent_calloc2(size_t NT = sizeof(T), size_t MT = M)<br>
+    __attribute__((alloc_size(1, 2)));<br>
+<br>
+// CHECK-LABEL: define i32 @_ZN20templated_alloc_size6tes<wbr>tItEv<br>
+int testIt() {<br>
+  // 122 = 4 + 5*4 + 6 + 7*8 + 4*9<br>
+  // CHECK: ret i32 122<br>
+  return __builtin_object_size(my_mallo<wbr>c<int>(), 0) +<br>
+         __builtin_object_size(my_call<wbr>oc<int>(5), 0) +<br>
+         __builtin_object_size(depende<wbr>nt_malloc<6>(), 0) +<br>
+         __builtin_object_size(depende<wbr>nt_calloc<7, 8>(), 0) +<br>
+         __builtin_object_size(depende<wbr>nt_calloc2<int, 9>(), 0);<br>
+}<br>
+}<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/bloc<wbr>k-in-ctor-dtor.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/block-in-ctor-dtor.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/CodeGenCX<wbr>X/block-in-ctor-dtor.cpp?rev=2<wbr>90149&r1=290148&r2=290149&view<wbr>=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/bloc<wbr>k-in-ctor-dtor.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/bloc<wbr>k-in-ctor-dtor.cpp Mon Dec 19 19:05:42 2016<br>
@@ -42,7 +42,5 @@ X::~X() {<br>
 // CHECK-LABEL: define internal void @___ZN4ZoneD2Ev_block_invoke_<br>
 // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke<br>
 // CHECK-LABEL: define internal void @___ZN1XC2Ev_block_invoke_<br>
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke<br>
-// CHECK-LABEL: define internal void @___ZN1XC1Ev_block_invoke_<br>
 // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke<br>
 // CHECK-LABEL: define internal void @___ZN1XD2Ev_block_invoke_<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/glob<wbr>al-init.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-init.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/CodeGenCX<wbr>X/global-init.cpp?rev=290149&r<wbr>1=290148&r2=290149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/glob<wbr>al-init.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/glob<wbr>al-init.cpp Mon Dec 19 19:05:42 2016<br>
@@ -18,9 +18,6 @@ struct D { ~D(); };<br>
 // CHECK: @__dso_handle = external global i8<br>
 // CHECK: @c = global %struct.C zeroinitializer, align 8<br>
<br>
-// It's okay if we ever implement the IR-generation optimization to remove this.<br>
-// CHECK: @_ZN5test3L3varE = internal constant i8* getelementptr inbounds ([7 x i8], [7 x i8]*<br>
-<br>
 // PR6205: The casts should not require global initializers<br>
 // CHECK: @_ZN6PR59741cE = external global %"struct.PR5974::C"<br>
 // CHECK: @_ZN6PR59741aE = global %"struct.PR5974::A"* getelementptr inbounds (%"struct.PR5974::C", %"struct.PR5974::C"* @_ZN6PR59741cE, i32 0, i32 0)<br>
<br>
Modified: cfe/trunk/test/CodeGenOpenCL/<a href="http://cl20-device-side-enqueue.cl" rel="noreferrer" target="_blank">c<wbr>l20-device-side-enqueue.cl</a><br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/cl20-device-side-enqueue.cl?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/CodeGenOp<wbr>enCL/cl20-device-side-enqueue.<wbr>cl?rev=290149&r1=290148&r2=290<wbr>149&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenOpenCL/<a href="http://cl20-device-side-enqueue.cl" rel="noreferrer" target="_blank">c<wbr>l20-device-side-enqueue.cl</a> (original)<br>
+++ cfe/trunk/test/CodeGenOpenCL/<a href="http://cl20-device-side-enqueue.cl" rel="noreferrer" target="_blank">c<wbr>l20-device-side-enqueue.cl</a> Mon Dec 19 19:05:42 2016<br>
@@ -3,6 +3,8 @@<br>
<br>
 typedef void (^bl_t)(local void *);<br>
<br>
+// N.B. The check here only exists to set BL_GLOBAL<br>
+// COMMON: @block_G = {{.*}}bitcast ([[BL_GLOBAL:[^@]+@__block_lit<wbr>eral_global(\.[0-9]+)?]]<br>
 const bl_t block_G = (bl_t) ^ (local void *a) {};<br>
<br>
 kernel void device_side_enqueue(global int *a, global int *b, int i) {<br>
@@ -122,28 +124,24 @@ kernel void device_side_enqueue(global i<br>
                  },<br>
                  4294967296L);<br>
<br>
-<br>
+  // The full type of these expressions are long (and repeated elsewhere), so we<br>
+  // capture it as part of the regex for convenience and clarity.<br>
+  // COMMON: store void ()* bitcast ([[BL_A:[^@]+@__block_literal_<wbr>global.[0-9]+]] to void ()*), void ()** %block_A<br>
   void (^const block_A)(void) = ^{<br>
     return;<br>
   };<br>
+<br>
+  // COMMON: store void (i8 addrspace(2)*)* bitcast ([[BL_B:[^@]+@__block_literal_<wbr>global.[0-9]+]] to void (i8 addrspace(2)*)*), void (i8 addrspace(2)*)** %block_B<br>
   void (^const block_B)(local void *) = ^(local void *a) {<br>
     return;<br>
   };<br>
<br>
-  // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A<br>
-  // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*<br>
-  // COMMON: call i32 @__get_kernel_work_group_size_<wbr>impl(i8* [[BL_I8]])<br>
+  // COMMON: call i32 @__get_kernel_work_group_size_<wbr>impl(i8* bitcast ([[BL_A]] to i8*))<br>
   unsigned size = get_kernel_work_group_size(blo<wbr>ck_A);<br>
-  // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)** %block_B<br>
-  // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*<br>
-  // COMMON: call i32 @__get_kernel_work_group_size_<wbr>impl(i8* [[BL_I8]])<br>
+  // COMMON: call i32 @__get_kernel_work_group_size_<wbr>impl(i8* bitcast ([[BL_B]] to i8*))<br>
   size = get_kernel_work_group_size(blo<wbr>ck_B);<br>
-  // COMMON: [[BL:%[0-9]+]] = load void ()*, void ()** %block_A<br>
-  // COMMON: [[BL_I8:%[0-9]+]] = bitcast void ()* [[BL]] to i8*<br>
-  // COMMON: call i32 @__get_kernel_preferred_work_g<wbr>roup_multiple_impl(i8* [[BL_I8]])<br>
+  // COMMON: call i32 @__get_kernel_preferred_work_g<wbr>roup_multiple_impl(i8* bitcast ([[BL_A]] to i8*))<br>
   size = get_kernel_preferred_work_grou<wbr>p_size_multiple(block_A);<br>
-  // COMMON: [[BL:%[0-9]+]] = load void (i8 addrspace(2)*)*, void (i8 addrspace(2)*)* addrspace(1)* @block_G<br>
-  // COMMON: [[BL_I8:%[0-9]+]] = bitcast void (i8 addrspace(2)*)* [[BL]] to i8*<br>
-  // COMMON: call i32 @__get_kernel_preferred_work_g<wbr>roup_multiple_impl(i8* [[BL_I8]])<br>
+  // COMMON: call i32 @__get_kernel_preferred_work_g<wbr>roup_multiple_impl(i8* bitcast ([[BL_GLOBAL]] to i8*))<br>
   size = get_kernel_preferred_work_grou<wbr>p_size_multiple(block_G);<br>
 }<br>
<br>
Added: cfe/trunk/test/Sema/alloc-size<wbr>.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/alloc-size.c?rev=290149&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Sema/allo<wbr>c-size.c?rev=290149&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Sema/alloc-size<wbr>.c (added)<br>
+++ cfe/trunk/test/Sema/alloc-size<wbr>.c Mon Dec 19 19:05:42 2016<br>
@@ -0,0 +1,23 @@<br>
+// RUN: %clang_cc1 %s -verify<br>
+<br>
+void *fail1(int a) __attribute__((alloc_size)); //expected-error{{'alloc_size' attribute takes at least 1 argument}}<br>
+void *fail2(int a) __attribute__((alloc_size())); //expected-error{{'alloc_size' attribute takes at least 1 argument}}<br>
+<br>
+void *fail3(int a) __attribute__((alloc_size(0)))<wbr>; //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}<br>
+void *fail4(int a) __attribute__((alloc_size(2)))<wbr>; //expected-error{{'alloc_size' attribute parameter 2 is out of bounds}}<br>
+<br>
+void *fail5(int a, int b) __attribute__((alloc_size(0, 1))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}<br>
+void *fail6(int a, int b) __attribute__((alloc_size(3, 1))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}<br>
+<br>
+void *fail7(int a, int b) __attribute__((alloc_size(1, 0))); //expected-error{{'alloc_size' attribute parameter 0 is out of bounds}}<br>
+void *fail8(int a, int b) __attribute__((alloc_size(1, 3))); //expected-error{{'alloc_size' attribute parameter 3 is out of bounds}}<br>
+<br>
+int fail9(int a) __attribute__((alloc_size(1)))<wbr>; //expected-warning{{'alloc_siz<wbr>e' attribute only applies to return values that are pointers}}<br>
+<br>
+int fail10 __attribute__((alloc_size(1)))<wbr>; //expected-warning{{'alloc_siz<wbr>e' attribute only applies to non-K&R-style functions}}<br>
+<br>
+void *fail11(void *a) __attribute__((alloc_size(1)))<wbr>; //expected-error{{'alloc_size' attribute argument may only refer to a function parameter of integer type}}<br>
+<br>
+void *fail12(int a) __attribute__((alloc_size("abc<wbr>"))); //expected-error{{'alloc_size' attribute requires parameter 1 to be an integer constant}}<br>
+void *fail12(int a) __attribute__((alloc_size(1, "abc"))); //expected-error{{'alloc_size' attribute requires parameter 2 to be an integer constant}}<br>
+void *fail13(int a) __attribute__((alloc_size(1U<<<wbr>31))); //expected-error{{integer constant expression evaluates to value <a href="tel:(214)%20748-3648" value="+12147483648" target="_blank">2147483648</a> that cannot be represented in a 32-bit signed integer type}}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/constan<wbr>t-expression-cxx11.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=290149&r1=290148&r2=290149&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/SemaCXX/c<wbr>onstant-expression-cxx11.cpp?r<wbr>ev=290149&r1=290148&r2=290149&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/constan<wbr>t-expression-cxx11.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/constan<wbr>t-expression-cxx11.cpp Mon Dec 19 19:05:42 2016<br>
@@ -1183,7 +1183,7 @@ constexpr int m1b = const_cast<const int<br>
 constexpr int m2b = const_cast<const int&>(n2); // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}<br>
<br>
 struct T { int n; };<br>
-const T t = { 42 }; // expected-note {{declared here}}<br>
+const T t = { 42 };<br>
<br>
 constexpr int f(volatile int &&r) {<br>
   return r; // expected-note {{read of volatile-qualified type 'volatile int'}}<br>
@@ -1195,7 +1195,7 @@ struct S {<br>
   int j : f(0); // expected-error {{constant expression}} expected-note {{in call to 'f(0)'}}<br>
   int k : g(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'g(0)'}}<br>
   int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}<br>
-  int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}<br>
+  int m : t.n; // expected-warning{{width of bit-field 'm' (42 bits)}}<br>
 };<br>
<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>