<div dir="ltr"><div>Hi Aaron, Nico,<br><br>Thanks for letting me know.  I'll follow up in bugzilla as soon as my bugzilla account is created.<br><br></div>Joel<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 7, 2018 at 4:49 PM, Aaron Ballman <span dir="ltr"><<a href="mailto:aaron@aaronballman.com" target="_blank">aaron@aaronballman.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Joel, can you investigate the issue?<br>
<span class="HOEnZb"><font color="#888888"><br>
~Aaron<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Wed, Mar 7, 2018 at 4:32 PM, Nico Weber via cfe-commits<br>
<<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
> (I had to revert this since it caused<br>
> <a href="https://bugs.llvm.org/show_bug.cgi?id=36620" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=36620</a>)<br>
><br>
> On Fri, Mar 2, 2018 at 2:03 PM, Joel E. Denny via cfe-commits<br>
> <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> Author: jdenny<br>
>> Date: Fri Mar  2 11:03:22 2018<br>
>> New Revision: 326602<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=326602&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=326602&view=rev</a><br>
>> Log:<br>
>> [Attr] Fix parameter indexing for several attributes<br>
>><br>
>> The patch fixes a number of bugs related to parameter indexing in<br>
>> attributes:<br>
>><br>
>> * Parameter indices in some attributes (argument_with_type_tag,<br>
>>   pointer_with_type_tag, nonnull, ownership_takes, ownership_holds,<br>
>>   and ownership_returns) are specified in source as one-origin<br>
>>   including any C++ implicit this parameter, were stored as<br>
>>   zero-origin excluding any this parameter, and were erroneously<br>
>>   printing (-ast-print) and confusingly dumping (-ast-dump) as the<br>
>>   stored values.<br>
>><br>
>> * For alloc_size, the C++ implicit this parameter was not subtracted<br>
>>   correctly in Sema, leading to assert failures or to silent failures<br>
>>   of __builtin_object_size to compute a value.<br>
>><br>
>> * For argument_with_type_tag, pointer_with_type_tag, and<br>
>>   ownership_returns, the C++ implicit this parameter was not added<br>
>>   back to parameter indices in some diagnostics.<br>
>><br>
>> This patch fixes the above bugs and aims to prevent similar bugs in<br>
>> the future by introducing careful mechanisms for handling parameter<br>
>> indices in attributes.  ParamIdx stores a parameter index and is<br>
>> designed to hide the stored encoding while providing accessors that<br>
>> require each use (such as printing) to make explicit the encoding that<br>
>> is needed.  Attribute declarations declare parameter index arguments<br>
>> as [Variadic]ParamIdxArgument, which are exposed as ParamIdx[*].  This<br>
>> patch rewrites all attribute arguments that are processed by<br>
>> checkFunctionOrMethodParameter<wbr>Index in SemaDeclAttr.cpp to be declared<br>
>> as [Variadic]ParamIdxArgument.  The only exception is xray_log_args's<br>
>> argument, which is encoded as a count not an index.<br>
>><br>
>> Differential Revision: <a href="https://reviews.llvm.org/D43248" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D43248</a><br>
>><br>
>> Added:<br>
>>     cfe/trunk/test/Sema/attr-<wbr>ownership.cpp<br>
>> Modified:<br>
>>     cfe/trunk/include/clang/AST/<wbr>Attr.h<br>
>>     cfe/trunk/include/clang/Basic/<wbr>Attr.td<br>
>>     cfe/trunk/lib/AST/<wbr>ExprConstant.cpp<br>
>>     cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp<br>
>>     cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp<br>
>>     cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
>>     cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp<br>
>>     cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp<br>
>>     cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/MallocChecker.cpp<br>
>>     cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/NonNullParamChecker.<wbr>cpp<br>
>>     cfe/trunk/test/CodeGenCXX/<wbr>alloc-size.cpp<br>
>>     cfe/trunk/test/Misc/ast-dump-<wbr>attr.cpp<br>
>>     cfe/trunk/test/Sema/attr-<wbr>print.cpp<br>
>>     cfe/trunk/test/Sema/error-<wbr>type-safety.cpp<br>
>>     cfe/trunk/utils/TableGen/<wbr>ClangAttrEmitter.cpp<br>
>><br>
>> Modified: cfe/trunk/include/clang/AST/<wbr>Attr.h<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/Attr.h?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/include/clang/AST/<wbr>Attr.h (original)<br>
>> +++ cfe/trunk/include/clang/AST/<wbr>Attr.h Fri Mar  2 11:03:22 2018<br>
>> @@ -195,6 +195,120 @@ public:<br>
>>     }<br>
>>  };<br>
>><br>
>> +/// A single parameter index whose accessors require each use to make<br>
>> explicit<br>
>> +/// the parameter index encoding needed.<br>
>> +class ParamIdx {<br>
>> +  // Idx is exposed only via accessors that specify specific encodings.<br>
>> +  unsigned Idx : 30;<br>
>> +  unsigned HasThis : 1;<br>
>> +  unsigned IsValid : 1;<br>
>> +<br>
>> +  void assertComparable(const ParamIdx &I) const {<br>
>> +    assert(isValid() && I.isValid() &&<br>
>> +           "ParamIdx must be valid to be compared");<br>
>> +    // It's possible to compare indices from separate functions, but so<br>
>> far<br>
>> +    // it's not proven useful.  Moreover, it might be confusing because a<br>
>> +    // comparison on the results of getASTIndex might be inconsistent<br>
>> with a<br>
>> +    // comparison on the ParamIdx objects themselves.<br>
>> +    assert(HasThis == I.HasThis &&<br>
>> +           "ParamIdx must be for the same function to be compared");<br>
>> +  }<br>
>> +<br>
>> +public:<br>
>> +  /// Construct an invalid parameter index (\c isValid returns false and<br>
>> +  /// accessors fail an assert).<br>
>> +  ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}<br>
>> +<br>
>> +  /// \param Idx is the parameter index as it is normally specified in<br>
>> +  /// attributes in the source: one-origin including any C++ implicit<br>
>> this<br>
>> +  /// parameter.<br>
>> +  ///<br>
>> +  /// \param D is the declaration containing the parameters.  It is used<br>
>> to<br>
>> +  /// determine if there is a C++ implicit this parameter.<br>
>> +  ParamIdx(unsigned Idx, const Decl *D)<br>
>> +      : Idx(Idx), HasThis(false), IsValid(true) {<br>
>> +    if (const auto *FD = dyn_cast<FunctionDecl>(D))<br>
>> +      HasThis = FD->isCXXInstanceMember();<br>
>> +  }<br>
>> +<br>
>> +  /// \param Idx is the parameter index as it is normally specified in<br>
>> +  /// attributes in the source: one-origin including any C++ implicit<br>
>> this<br>
>> +  /// parameter.<br>
>> +  ///<br>
>> +  /// \param HasThis specifies whether the function has a C++ implicit<br>
>> this<br>
>> +  /// parameter.<br>
>> +  ParamIdx(unsigned Idx, bool HasThis)<br>
>> +      : Idx(Idx), HasThis(HasThis), IsValid(true) {}<br>
>> +<br>
>> +  /// Is this parameter index valid?<br>
>> +  bool isValid() const { return IsValid; }<br>
>> +<br>
>> +  /// Is there a C++ implicit this parameter?<br>
>> +  bool hasThis() const {<br>
>> +    assert(isValid() && "ParamIdx must be valid");<br>
>> +    return HasThis;<br>
>> +  }<br>
>> +<br>
>> +  /// Get the parameter index as it would normally be encoded for<br>
>> attributes at<br>
>> +  /// the source level of representation: one-origin including any C++<br>
>> implicit<br>
>> +  /// this parameter.<br>
>> +  ///<br>
>> +  /// This encoding thus makes sense for diagnostics, pretty printing,<br>
>> and<br>
>> +  /// constructing new attributes from a source-like specification.<br>
>> +  unsigned getSourceIndex() const {<br>
>> +    assert(isValid() && "ParamIdx must be valid");<br>
>> +    return Idx;<br>
>> +  }<br>
>> +<br>
>> +  /// Get the parameter index as it would normally be encoded at the AST<br>
>> level<br>
>> +  /// of representation: zero-origin not including any C++ implicit this<br>
>> +  /// parameter.<br>
>> +  ///<br>
>> +  /// This is the encoding primarily used in Sema.  However, in<br>
>> diagnostics,<br>
>> +  /// Sema uses \c getSourceIndex instead.<br>
>> +  unsigned getASTIndex() const {<br>
>> +    assert(isValid() && "ParamIdx must be valid");<br>
>> +    assert(Idx >= 1 + HasThis &&<br>
>> +           "stored index must be base-1 and not specify C++ implicit<br>
>> this");<br>
>> +    return Idx - 1 - HasThis;<br>
>> +  }<br>
>> +<br>
>> +  /// Get the parameter index as it would normally be encoded at the LLVM<br>
>> level<br>
>> +  /// of representation: zero-origin including any C++ implicit this<br>
>> parameter.<br>
>> +  ///<br>
>> +  /// This is the encoding primarily used in CodeGen.<br>
>> +  unsigned getLLVMIndex() const {<br>
>> +    assert(isValid() && "ParamIdx must be valid");<br>
>> +    assert(Idx >= 1 && "stored index must be base-1");<br>
>> +    return Idx - 1;<br>
>> +  }<br>
>> +<br>
>> +  bool operator==(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx == I.Idx;<br>
>> +  }<br>
>> +  bool operator!=(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx != I.Idx;<br>
>> +  }<br>
>> +  bool operator<(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx < I.Idx;<br>
>> +  }<br>
>> +  bool operator>(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx > I.Idx;<br>
>> +  }<br>
>> +  bool operator<=(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx <= I.Idx;<br>
>> +  }<br>
>> +  bool operator>=(const ParamIdx &I) const {<br>
>> +    assertComparable(I);<br>
>> +    return Idx >= I.Idx;<br>
>> +  }<br>
>> +};<br>
>> +<br>
>>  #include "clang/AST/Attrs.inc"<br>
>><br>
>>  inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,<br>
>><br>
>> Modified: cfe/trunk/include/clang/Basic/<wbr>Attr.td<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/Attr.td?rev=<wbr>326602&r1=326601&r2=326602&<wbr>view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/include/clang/Basic/<wbr>Attr.td (original)<br>
>> +++ cfe/trunk/include/clang/Basic/<wbr>Attr.td Fri Mar  2 11:03:22 2018<br>
>> @@ -166,6 +166,12 @@ class VariadicUnsignedArgument<<wbr>string na<br>
>>  class VariadicExprArgument<string name> : Argument<name, 1>;<br>
>>  class VariadicStringArgument<string name> : Argument<name, 1>;<br>
>><br>
>> +// Like VariadicUnsignedArgument except values are ParamIdx.<br>
>> +class VariadicParamIdxArgument<<wbr>string name> : Argument<name, 1>;<br>
>> +<br>
>> +// Like VariadicParamIdxArgument but for a single function parameter<br>
>> index.<br>
>> +class ParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>;<br>
>> +<br>
>>  // A version of the form major.minor[.subminor].<br>
>>  class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;<br>
>><br>
>> @@ -611,6 +617,12 @@ def XRayInstrument : InheritableAttr {<br>
>>  def XRayLogArgs : InheritableAttr {<br>
>>    let Spellings = [Clang<"xray_log_args">];<br>
>>    let Subjects = SubjectList<[Function, ObjCMethod]>;<br>
>> +  // This argument is a count not an index, so it has the same encoding<br>
>> (base<br>
>> +  // 1 including C++ implicit this parameter) at the source and LLVM<br>
>> levels of<br>
>> +  // representation, so ParamIdxArgument is inappropriate.  It is never<br>
>> used<br>
>> +  // at the AST level of representation, so it never needs to be adjusted<br>
>> not<br>
>> +  // to include any C++ implicit this parameter.  Thus, we just store it<br>
>> and<br>
>> +  // use it as an unsigned that never needs adjustment.<br>
>>    let Args = [UnsignedArgument<"<wbr>ArgumentCount">];<br>
>>    let Documentation = [XRayDocs];<br>
>>  }<br>
>> @@ -1018,7 +1030,8 @@ def EmptyBases : InheritableAttr, Target<br>
>>  def AllocSize : InheritableAttr {<br>
>>    let Spellings = [GCC<"alloc_size">];<br>
>>    let Subjects = SubjectList<[Function]>;<br>
>> -  let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam",<br>
>> 1>];<br>
>> +  let Args = [ParamIdxArgument<"<wbr>ElemSizeParam">,<br>
>> +              ParamIdxArgument<"<wbr>NumElemsParam", /*opt*/ 1>];<br>
>>    let TemplateDependent = 1;<br>
>>    let Documentation = [AllocSizeDocs];<br>
>>  }<br>
>> @@ -1105,7 +1118,7 @@ def Format : InheritableAttr {<br>
>><br>
>>  def FormatArg : InheritableAttr {<br>
>>    let Spellings = [GCC<"format_arg">];<br>
>> -  let Args = [IntArgument<"FormatIdx">];<br>
>> +  let Args = [ParamIdxArgument<"FormatIdx"><wbr>];<br>
>>    let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>;<br>
>>    let Documentation = [Undocumented];<br>
>>  }<br>
>> @@ -1385,16 +1398,16 @@ def NonNull : InheritableParamAttr {<br>
>>    let Spellings = [GCC<"nonnull">];<br>
>>    let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar],<br>
>> WarnDiag,<br>
>>                               "functions, methods, and parameters">;<br>
>> -  let Args = [VariadicUnsignedArgument<"<wbr>Args">];<br>
>> -  let AdditionalMembers =<br>
>> -[{bool isNonNull(unsigned idx) const {<br>
>> -    if (!args_size())<br>
>> -      return true;<br>
>> -    for (const auto &V : args())<br>
>> -      if (V == idx)<br>
>> +  let Args = [VariadicParamIdxArgument<"<wbr>Args">];<br>
>> +  let AdditionalMembers = [{<br>
>> +    bool isNonNull(unsigned IdxAST) const {<br>
>> +      if (!args_size())<br>
>>          return true;<br>
>> -    return false;<br>
>> -  } }];<br>
>> +      return args_end() != std::find_if(<br>
>> +          args_begin(), args_end(),<br>
>> +          [=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST;<br>
>> });<br>
>> +    }<br>
>> +  }];<br>
>>    // FIXME: We should merge duplicates into a single nonnull attribute.<br>
>>    let InheritEvenIfAlreadyPresent = 1;<br>
>>    let Documentation = [NonNullDocs];<br>
>> @@ -1452,7 +1465,7 @@ def AssumeAligned : InheritableAttr {<br>
>>  def AllocAlign : InheritableAttr {<br>
>>    let Spellings = [GCC<"alloc_align">];<br>
>>    let Subjects = SubjectList<[HasFunctionProto]<wbr>>;<br>
>> -  let Args = [IntArgument<"ParamIndex">];<br>
>> +  let Args = [ParamIdxArgument<"ParamIndex"<wbr>>];<br>
>>    let Documentation = [AllocAlignDocs];<br>
>>  }<br>
>><br>
>> @@ -1661,7 +1674,8 @@ def Ownership : InheritableAttr {<br>
>>               Returns;<br>
>>      }<br>
>>    }];<br>
>> -  let Args = [IdentifierArgument<"Module">,<br>
>> VariadicUnsignedArgument<"<wbr>Args">];<br>
>> +  let Args = [IdentifierArgument<"Module">,<br>
>> +              VariadicParamIdxArgument<"<wbr>Args">];<br>
>>    let Subjects = SubjectList<[HasFunctionProto]<wbr>>;<br>
>>    let Documentation = [Undocumented];<br>
>>  }<br>
>> @@ -2486,8 +2500,8 @@ def ArgumentWithTypeTag : InheritableAtt<br>
>>                     Clang<"pointer_with_type_tag"><wbr>];<br>
>>    let Subjects = SubjectList<[HasFunctionProto]<wbr>, ErrorDiag>;<br>
>>    let Args = [IdentifierArgument<"<wbr>ArgumentKind">,<br>
>> -              UnsignedArgument<"ArgumentIdx"<wbr>>,<br>
>> -              UnsignedArgument<"TypeTagIdx"><wbr>,<br>
>> +              ParamIdxArgument<"ArgumentIdx"<wbr>>,<br>
>> +              ParamIdxArgument<"TypeTagIdx"><wbr>,<br>
>>                BoolArgument<"IsPointer", /*opt*/0, /*fake*/1>];<br>
>>    let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];<br>
>>  }<br>
>><br>
>> Modified: cfe/trunk/lib/AST/<wbr>ExprConstant.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ExprConstant.cpp?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/AST/<wbr>ExprConstant.cpp (original)<br>
>> +++ cfe/trunk/lib/AST/<wbr>ExprConstant.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -5463,9 +5463,8 @@ static bool getBytesReturnedByAllocSizeC<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>
>> +  assert(AllocSize && AllocSize->elemSizeParam().<wbr>isValid());<br>
>> +  unsigned SizeArgNo = AllocSize->elemSizeParam().<wbr>getASTIndex();<br>
>>    unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.<wbr>getSizeType());<br>
>>    if (Call->getNumArgs() <= SizeArgNo)<br>
>>      return false;<br>
>> @@ -5483,14 +5482,13 @@ static bool getBytesReturnedByAllocSizeC<br>
>>    if (!EvaluateAsSizeT(Call-><wbr>getArg(SizeArgNo), SizeOfElem))<br>
>>      return false;<br>
>><br>
>> -  if (!AllocSize->getNumElemsParam(<wbr>)) {<br>
>> +  if (!AllocSize->numElemsParam().<wbr>isValid()) {<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>
>> +  unsigned NumArgNo = AllocSize->numElemsParam().<wbr>getASTIndex();<br>
>>    if (!EvaluateAsSizeT(Call-><wbr>getArg(NumArgNo), NumberOfElems))<br>
>>      return false;<br>
>><br>
>><br>
>> Modified: cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGCall.cpp?rev=326602&r1=<wbr>326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp (original)<br>
>> +++ cfe/trunk/lib/CodeGen/CGCall.<wbr>cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -1847,10 +1847,9 @@ void CodeGenModule::<wbr>ConstructAttributeLi<br>
>>      HasOptnone = TargetDecl->hasAttr<<wbr>OptimizeNoneAttr>();<br>
>>      if (auto *AllocSize = TargetDecl->getAttr<<wbr>AllocSizeAttr>()) {<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(<wbr>AllocSize->getElemSizeParam() - 1,<br>
>> +      if (AllocSize->numElemsParam().<wbr>isValid())<br>
>> +        NumElemsParam = AllocSize->numElemsParam().<wbr>getLLVMIndex();<br>
>> +<br>
>> FuncAttrs.addAllocSizeAttr(<wbr>AllocSize->elemSizeParam().<wbr>getLLVMIndex(),<br>
>>                                   NumElemsParam);<br>
>>      }<br>
>>    }<br>
>> @@ -4395,7 +4394,7 @@ RValue CodeGenFunction::EmitCall(<wbr>const C<br>
>>                                OffsetValue);<br>
>>      } else if (const auto *AA = TargetDecl->getAttr<<wbr>AllocAlignAttr>()) {<br>
>>        llvm::Value *ParamVal =<br>
>> -          CallArgs[AA->getParamIndex() - 1].RV.getScalarVal();<br>
>> +          CallArgs[AA->paramIndex().<wbr>getLLVMIndex()].RV.<wbr>getScalarVal();<br>
>>        EmitAlignmentAssumption(Ret.<wbr>getScalarVal(), ParamVal);<br>
>>      }<br>
>>    }<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaChecking.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -2619,12 +2619,13 @@ static void CheckNonNullArguments(Sema &<br>
>>          return;<br>
>>        }<br>
>><br>
>> -      for (unsigned Val : NonNull->args()) {<br>
>> -        if (Val >= Args.size())<br>
>> +      for (const ParamIdx &Idx : NonNull->args()) {<br>
>> +        unsigned IdxAST = Idx.getASTIndex();<br>
>> +        if (IdxAST >= Args.size())<br>
>>            continue;<br>
>>          if (NonNullArgs.empty())<br>
>>            NonNullArgs.resize(Args.size()<wbr>);<br>
>> -        NonNullArgs.set(Val);<br>
>> +        NonNullArgs.set(IdxAST);<br>
>>        }<br>
>>      }<br>
>>    }<br>
>> @@ -5002,12 +5003,7 @@ checkFormatStringExpr(Sema &S, const Exp<br>
>>      const CallExpr *CE = cast<CallExpr>(E);<br>
>>      if (const NamedDecl *ND =<br>
>> dyn_cast_or_null<NamedDecl>(<wbr>CE->getCalleeDecl())) {<br>
>>        if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) {<br>
>> -        unsigned ArgIndex = FA->getFormatIdx();<br>
>> -        if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))<br>
>> -          if (MD->isInstance())<br>
>> -            --ArgIndex;<br>
>> -        const Expr *Arg = CE->getArg(ArgIndex - 1);<br>
>> -<br>
>> +        const Expr *Arg = CE->getArg(FA->formatIdx().<wbr>getASTIndex());<br>
>>          return checkFormatStringExpr(S, Arg, Args,<br>
>>                                       HasVAListArg, format_idx,<br>
>> firstDataArg,<br>
>>                                       Type, CallType, InFunctionCall,<br>
>> @@ -5032,8 +5028,7 @@ checkFormatStringExpr(Sema &S, const Exp<br>
>>      const auto *ME = cast<ObjCMessageExpr>(E);<br>
>>      if (const auto *ND = ME->getMethodDecl()) {<br>
>>        if (const auto *FA = ND->getAttr<FormatArgAttr>()) {<br>
>> -        unsigned ArgIndex = FA->getFormatIdx();<br>
>> -        const Expr *Arg = ME->getArg(ArgIndex - 1);<br>
>> +        const Expr *Arg = ME->getArg(FA->formatIdx().<wbr>getASTIndex());<br>
>>          return checkFormatStringExpr(<br>
>>              S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type,<br>
>>              CallType, InFunctionCall, CheckedVarArgs, UncoveredArg,<br>
>> Offset);<br>
>> @@ -10086,8 +10081,8 @@ void Sema::<wbr>DiagnoseAlwaysNonNullPointer(<br>
>>                return;<br>
>>            }<br>
>><br>
>> -          for (unsigned ArgNo : NonNull->args()) {<br>
>> -            if (ArgNo == ParamNo) {<br>
>> +          for (const ParamIdx &ArgNo : NonNull->args()) {<br>
>> +            if (ArgNo.getASTIndex() == ParamNo) {<br>
>>                ComplainAboutNonnullParamOrCal<wbr>l(NonNull);<br>
>>                return;<br>
>>              }<br>
>> @@ -12242,13 +12237,13 @@ void Sema::<wbr>CheckArgumentWithTypeTag(cons<br>
>>    bool IsPointerAttr = Attr->getIsPointer();<br>
>><br>
>>    // Retrieve the argument representing the 'type_tag'.<br>
>> -  if (Attr->getTypeTagIdx() >= ExprArgs.size()) {<br>
>> -    // Add 1 to display the user's specified value.<br>
>> +  unsigned TypeTagIdxAST = Attr->typeTagIdx().<wbr>getASTIndex();<br>
>> +  if (TypeTagIdxAST >= ExprArgs.size()) {<br>
>>      Diag(CallSiteLoc, diag::err_tag_index_out_of_<wbr>range)<br>
>> -        << 0 << Attr->getTypeTagIdx() + 1;<br>
>> +        << 0 << Attr->typeTagIdx().<wbr>getSourceIndex();<br>
>>      return;<br>
>>    }<br>
>> -  const Expr *TypeTagExpr = ExprArgs[Attr->getTypeTagIdx()<wbr>];<br>
>> +  const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST];<br>
>>    bool FoundWrongKind;<br>
>>    TypeTagData TypeInfo;<br>
>>    if (!GetMatchingCType(<wbr>ArgumentKind, TypeTagExpr, Context,<br>
>> @@ -12262,13 +12257,13 @@ void Sema::<wbr>CheckArgumentWithTypeTag(cons<br>
>>    }<br>
>><br>
>>    // Retrieve the argument representing the 'arg_idx'.<br>
>> -  if (Attr->getArgumentIdx() >= ExprArgs.size()) {<br>
>> -    // Add 1 to display the user's specified value.<br>
>> +  unsigned ArgumentIdxAST = Attr->argumentIdx().<wbr>getASTIndex();<br>
>> +  if (ArgumentIdxAST >= ExprArgs.size()) {<br>
>>      Diag(CallSiteLoc, diag::err_tag_index_out_of_<wbr>range)<br>
>> -        << 1 << Attr->getArgumentIdx() + 1;<br>
>> +        << 1 << Attr->argumentIdx().<wbr>getSourceIndex();<br>
>>      return;<br>
>>    }<br>
>> -  const Expr *ArgumentExpr = ExprArgs[Attr->getArgumentIdx(<wbr>)];<br>
>> +  const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST];<br>
>>    if (IsPointerAttr) {<br>
>>      // Skip implicit cast of pointer to `void *' (as a function<br>
>> argument).<br>
>>      if (const ImplicitCastExpr *ICE =<br>
>> dyn_cast<ImplicitCastExpr>(<wbr>ArgumentExpr))<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDecl.cpp?rev=326602&r1=<wbr>326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -13176,7 +13176,7 @@ void Sema::<wbr>AddKnownFunctionAttributes(Fu<br>
>>      // We already have a __builtin___<wbr>CFStringMakeConstantString,<br>
>>      // but builds that use -fno-constant-cfstrings don't go through that.<br>
>>      if (!FD->hasAttr<FormatArgAttr>()<wbr>)<br>
>> -      FD->addAttr(FormatArgAttr::<wbr>CreateImplicit(Context, 1,<br>
>> +      FD->addAttr(FormatArgAttr::<wbr>CreateImplicit(Context, ParamIdx(1, FD),<br>
>>                                                  FD->getLocation()));<br>
>>    }<br>
>>  }<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaDeclAttr.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -311,7 +311,7 @@ static bool checkAttrMutualExclusion(Sem<br>
>>  template <typename AttrInfo><br>
>>  static bool checkFunctionOrMethodParameter<wbr>Index(<br>
>>      Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum,<br>
>> -    const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) {<br>
>> +    const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis =<br>
>> false) {<br>
>>    assert(<wbr>isFunctionOrMethodOrBlock(D));<br>
>><br>
>>    // In C++ the implicit 'this' function parameter also counts.<br>
>> @@ -331,21 +331,20 @@ static bool checkFunctionOrMethodParamet<br>
>>      return false;<br>
>>    }<br>
>><br>
>> -  Idx = IdxInt.getLimitedValue();<br>
>> -  if (Idx < 1 || (!IV && Idx > NumParams)) {<br>
>> +  Idx = ParamIdx(IdxInt.<wbr>getLimitedValue(UINT_MAX), D);<br>
>> +  unsigned IdxSource = Idx.getSourceIndex();<br>
>> +  if (IdxSource < 1 || (!IV && IdxSource > NumParams)) {<br>
>>      S.Diag(getAttrLoc(AI), diag::err_attribute_argument_<wbr>out_of_bounds)<br>
>> -      << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange();<br>
>> +        << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange();<br>
>>      return false;<br>
>>    }<br>
>> -  Idx--; // Convert to zero-based.<br>
>> -  if (HasImplicitThisParam && !AllowImplicitThis) {<br>
>> -    if (Idx == 0) {<br>
>> +  if (HasImplicitThisParam && !CanIndexImplicitThis) {<br>
>> +    if (IdxSource == 1) {<br>
>>        S.Diag(getAttrLoc(AI),<br>
>>               diag::err_attribute_invalid_<wbr>implicit_this_argument)<br>
>> -        << getAttrName(AI) << IdxExpr->getSourceRange();<br>
>> +          << getAttrName(AI) << IdxExpr->getSourceRange();<br>
>>        return false;<br>
>>      }<br>
>> -    --Idx;<br>
>>    }<br>
>><br>
>>    return true;<br>
>> @@ -772,18 +771,15 @@ static void handleAssertExclusiveLockAtt<br>
>>  /// AttrArgNo is used to actually retrieve the argument, so it's base-0.<br>
>>  template <typename AttrInfo><br>
>>  static bool checkParamIsIntegerType(Sema &S, const FunctionDecl *FD,<br>
>> -                                    const AttrInfo &AI, unsigned<br>
>> AttrArgNo,<br>
>> -                                    bool AllowDependentType = false) {<br>
>> +                                    const AttrInfo &AI, unsigned<br>
>> AttrArgNo) {<br>
>>    assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument");<br>
>>    Expr *AttrArg = AI.getArgAsExpr(AttrArgNo);<br>
>> -  uint64_t Idx;<br>
>> +  ParamIdx Idx;<br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, FD, AI, AttrArgNo + 1,<br>
>> AttrArg,<br>
>>                                             Idx))<br>
>>      return false;<br>
>><br>
>> -  const ParmVarDecl *Param = FD->getParamDecl(Idx);<br>
>> -  if (AllowDependentType && Param->getType()-><wbr>isDependentType())<br>
>> -    return true;<br>
>> +  const ParmVarDecl *Param = FD->getParamDecl(Idx.<wbr>getASTIndex());<br>
>>    if (!Param->getType()-><wbr>isIntegerType() &&<br>
>> !Param->getType()->isCharType(<wbr>)) {<br>
>>      SourceLocation SrcLoc = AttrArg->getLocStart();<br>
>>      S.Diag(SrcLoc, diag::err_attribute_integers_<wbr>only)<br>
>> @@ -806,22 +802,23 @@ static void handleAllocSizeAttr(Sema &S,<br>
>>    }<br>
>><br>
>>    const Expr *SizeExpr = AL.getArgAsExpr(0);<br>
>> -  int SizeArgNo;<br>
>> +  int SizeArgNoVal;<br>
>>    // Parameter indices are 1-indexed, hence Index=1<br>
>> -  if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNo, /*Index=*/1))<br>
>> +  if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal,<br>
>> /*Index=*/1))<br>
>>      return;<br>
>> +  ParamIdx SizeArgNo(SizeArgNoVal, D);<br>
>><br>
>>    if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0))<br>
>>      return;<br>
>><br>
>> -  // Args are 1-indexed, so 0 implies that the arg was not present<br>
>> -  int NumberArgNo = 0;<br>
>> +  ParamIdx NumberArgNo;<br>
>>    if (AL.getNumArgs() == 2) {<br>
>>      const Expr *NumberExpr = AL.getArgAsExpr(1);<br>
>> +    int Val;<br>
>>      // Parameter indices are 1-based, hence Index=2<br>
>> -    if (!checkPositiveIntArgument(S, AL, NumberExpr, NumberArgNo,<br>
>> -                                  /*Index=*/2))<br>
>> +    if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2))<br>
>>        return;<br>
>> +    NumberArgNo = ParamIdx(Val, D);<br>
>><br>
>>      if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1))<br>
>>        return;<br>
>> @@ -1424,18 +1421,19 @@ static bool attrNonNullArgCheck(Sema &S,<br>
>>  }<br>
>><br>
>>  static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &AL)<br>
>> {<br>
>> -  SmallVector<unsigned, 8> NonNullArgs;<br>
>> +  SmallVector<ParamIdx, 8> NonNullArgs;<br>
>>    for (unsigned I = 0; I < AL.getNumArgs(); ++I) {<br>
>>      Expr *Ex = AL.getArgAsExpr(I);<br>
>> -    uint64_t Idx;<br>
>> +    ParamIdx Idx;<br>
>>      if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, I + 1, Ex, Idx))<br>
>>        return;<br>
>><br>
>>      // Is the function argument a pointer type?<br>
>> -    if (Idx < getFunctionOrMethodNumParams(<wbr>D) &&<br>
>> -        !attrNonNullArgCheck(S, getFunctionOrMethodParamType(<wbr>D, Idx), AL,<br>
>> -                             Ex->getSourceRange(),<br>
>> -                             getFunctionOrMethodParamRange(<wbr>D, Idx)))<br>
>> +    if (Idx.getASTIndex() < getFunctionOrMethodNumParams(<wbr>D) &&<br>
>> +        !attrNonNullArgCheck(<br>
>> +            S, getFunctionOrMethodParamType(<wbr>D, Idx.getASTIndex()), AL,<br>
>> +            Ex->getSourceRange(),<br>
>> +            getFunctionOrMethodParamRange(<wbr>D, Idx.getASTIndex())))<br>
>>        continue;<br>
>><br>
>>      NonNullArgs.push_back(Idx);<br>
>> @@ -1459,12 +1457,12 @@ static void handleNonNullAttr(Sema &S, D<br>
>>        S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_<wbr>no_pointers);<br>
>>    }<br>
>><br>
>> -  unsigned *Start = NonNullArgs.data();<br>
>> +  ParamIdx *Start = NonNullArgs.data();<br>
>>    unsigned Size = NonNullArgs.size();<br>
>>    llvm::array_pod_sort(Start, Start + Size);<br>
>>    D->addAttr(::new (S.Context)<br>
>> -             NonNullAttr(AL.getRange(), S.Context, Start, Size,<br>
>> -                         AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>> +                 NonNullAttr(AL.getRange(), S.Context, Start, Size,<br>
>> +                             AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>>  static void handleNonNullAttrParameter(<wbr>Sema &S, ParmVarDecl *D,<br>
>> @@ -1485,8 +1483,8 @@ static void handleNonNullAttrParameter(S<br>
>>      return;<br>
>><br>
>>    D->addAttr(::new (S.Context)<br>
>> -             NonNullAttr(AL.getRange(), S.Context, nullptr, 0,<br>
>> -                         AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>> +                 NonNullAttr(AL.getRange(), S.Context, nullptr, 0,<br>
>> +                             AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>>  static void handleReturnsNonNullAttr(Sema &S, Decl *D,<br>
>> @@ -1587,7 +1585,7 @@ void Sema::AddAllocAlignAttr(<wbr>SourceRange<br>
>>                               unsigned SpellingListIndex) {<br>
>>    QualType ResultType = getFunctionOrMethodResultType(<wbr>D);<br>
>><br>
>> -  AllocAlignAttr TmpAttr(AttrRange, Context, 0, SpellingListIndex);<br>
>> +  AllocAlignAttr TmpAttr(AttrRange, Context, ParamIdx(),<br>
>> SpellingListIndex);<br>
>>    SourceLocation AttrLoc = AttrRange.getBegin();<br>
>><br>
>>    if (!ResultType->isDependentType(<wbr>) &&<br>
>> @@ -1597,28 +1595,22 @@ void Sema::AddAllocAlignAttr(<wbr>SourceRange<br>
>>      return;<br>
>>    }<br>
>><br>
>> -  uint64_t IndexVal;<br>
>> +  ParamIdx Idx;<br>
>>    const auto *FuncDecl = cast<FunctionDecl>(D);<br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(*this, FuncDecl, TmpAttr,<br>
>> -                                           /*AttrArgNo=*/1, ParamExpr,<br>
>> -                                           IndexVal))<br>
>> +                                           /*AttrArgNo=*/1, ParamExpr,<br>
>> Idx))<br>
>>      return;<br>
>><br>
>> -  QualType Ty = getFunctionOrMethodParamType(<wbr>D, IndexVal);<br>
>> +  QualType Ty = getFunctionOrMethodParamType(<wbr>D, Idx.getASTIndex());<br>
>>    if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) {<br>
>>      Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_<wbr>only)<br>
>> -        << &TmpAttr <<<br>
>> FuncDecl->getParamDecl(<wbr>IndexVal)->getSourceRange();<br>
>> +        << &TmpAttr<br>
>> +        << FuncDecl->getParamDecl(Idx.<wbr>getASTIndex())-><wbr>getSourceRange();<br>
>>      return;<br>
>>    }<br>
>><br>
>> -  // We cannot use the Idx returned from<br>
>> checkFunctionOrMethodParameter<wbr>Index<br>
>> -  // because that has corrected for the implicit this parameter, and is<br>
>> zero-<br>
>> -  // based.  The attribute expects what the user wrote explicitly.<br>
>> -  llvm::APSInt Val;<br>
>> -  ParamExpr->EvaluateAsInt(Val, Context);<br>
>> -<br>
>> -  D->addAttr(::new (Context) AllocAlignAttr(<br>
>> -      AttrRange, Context, Val.getZExtValue(), SpellingListIndex));<br>
>> +  D->addAttr(::new (Context)<br>
>> +                 AllocAlignAttr(AttrRange, Context, Idx,<br>
>> SpellingListIndex));<br>
>>  }<br>
>><br>
>>  /// Normalize the attribute, __foo__ becomes foo.<br>
>> @@ -1678,15 +1670,15 @@ static void handleOwnershipAttr(Sema &S,<br>
>>      Module = &S.PP.getIdentifierTable().<wbr>get(ModuleName);<br>
>>    }<br>
>><br>
>> -  SmallVector<unsigned, 8> OwnershipArgs;<br>
>> +  SmallVector<ParamIdx, 8> OwnershipArgs;<br>
>>    for (unsigned i = 1; i < AL.getNumArgs(); ++i) {<br>
>>      Expr *Ex = AL.getArgAsExpr(i);<br>
>> -    uint64_t Idx;<br>
>> +    ParamIdx Idx;<br>
>>      if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, i, Ex, Idx))<br>
>>        return;<br>
>><br>
>>      // Is the function argument a pointer type?<br>
>> -    QualType T = getFunctionOrMethodParamType(<wbr>D, Idx);<br>
>> +    QualType T = getFunctionOrMethodParamType(<wbr>D, Idx.getASTIndex());<br>
>>      int Err = -1;  // No error<br>
>>      switch (K) {<br>
>>        case OwnershipAttr::Takes:<br>
>> @@ -1717,14 +1709,13 @@ static void handleOwnershipAttr(Sema &S,<br>
>>        } else if (K == OwnershipAttr::Returns &&<br>
>>                   I->getOwnKind() == OwnershipAttr::Returns) {<br>
>>          // A returns attribute conflicts with any other returns attribute<br>
>> using<br>
>> -        // a different index. Note, diagnostic reporting is 1-based, but<br>
>> stored<br>
>> -        // argument indexes are 0-based.<br>
>> +        // a different index.<br>
>>          if (std::find(I->args_begin(), I->args_end(), Idx) ==<br>
>> I->args_end()) {<br>
>>            S.Diag(I->getLocation(),<br>
>> diag::err_ownership_returns_<wbr>index_mismatch)<br>
>> -              << *(I->args_begin()) + 1;<br>
>> +              << I->args_begin()-><wbr>getSourceIndex();<br>
>>            if (I->args_size())<br>
>>              S.Diag(AL.getLoc(),<br>
>> diag::note_ownership_returns_<wbr>index_mismatch)<br>
>> -                << (unsigned)Idx + 1 << Ex->getSourceRange();<br>
>> +                << Idx.getSourceIndex() << Ex->getSourceRange();<br>
>>            return;<br>
>>          }<br>
>>        }<br>
>> @@ -1732,13 +1723,12 @@ static void handleOwnershipAttr(Sema &S,<br>
>>      OwnershipArgs.push_back(Idx);<br>
>>    }<br>
>><br>
>> -  unsigned* start = OwnershipArgs.data();<br>
>> -  unsigned size = OwnershipArgs.size();<br>
>> -  llvm::array_pod_sort(start, start + size);<br>
>> -<br>
>> +  ParamIdx *Start = OwnershipArgs.data();<br>
>> +  unsigned Size = OwnershipArgs.size();<br>
>> +  llvm::array_pod_sort(Start, Start + Size);<br>
>>    D->addAttr(::new (S.Context)<br>
>> -             OwnershipAttr(AL.getLoc(), S.Context, Module, start, size,<br>
>> -                           AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>> +                 OwnershipAttr(AL.getLoc(), S.Context, Module, Start,<br>
>> Size,<br>
>> +                               AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>>  static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &AL)<br>
>> {<br>
>> @@ -3109,12 +3099,12 @@ static void handleEnumExtensibilityAttr(<br>
>>  /// <a href="http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html" rel="noreferrer" target="_blank">http://gcc.gnu.org/onlinedocs/<wbr>gcc/Function-Attributes.html</a><br>
>>  static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList<br>
>> &AL) {<br>
>>    Expr *IdxExpr = AL.getArgAsExpr(0);<br>
>> -  uint64_t Idx;<br>
>> +  ParamIdx Idx;<br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, 1, IdxExpr, Idx))<br>
>>      return;<br>
>><br>
>>    // Make sure the format string is really a string.<br>
>> -  QualType Ty = getFunctionOrMethodParamType(<wbr>D, Idx);<br>
>> +  QualType Ty = getFunctionOrMethodParamType(<wbr>D, Idx.getASTIndex());<br>
>><br>
>>    bool NotNSStringTy = !isNSStringType(Ty, S.Context);<br>
>>    if (NotNSStringTy &&<br>
>> @@ -3137,15 +3127,8 @@ static void handleFormatArgAttr(Sema &S,<br>
>>      return;<br>
>>    }<br>
>><br>
>> -  // We cannot use the Idx returned from<br>
>> checkFunctionOrMethodParameter<wbr>Index<br>
>> -  // because that has corrected for the implicit this parameter, and is<br>
>> zero-<br>
>> -  // based.  The attribute expects what the user wrote explicitly.<br>
>> -  llvm::APSInt Val;<br>
>> -  IdxExpr->EvaluateAsInt(Val, S.Context);<br>
>> -<br>
>> -  D->addAttr(::new (S.Context)<br>
>> -             FormatArgAttr(AL.getRange(), S.Context, Val.getZExtValue(),<br>
>> -                           AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>> +  D->addAttr(::new (S.Context) FormatArgAttr(<br>
>> +      AL.getRange(), S.Context, Idx,<br>
>> AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>>  enum FormatAttrKind {<br>
>> @@ -4539,13 +4522,13 @@ static void handleArgumentWithTypeTagAtt<br>
>>        << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;<br>
>>      return;<br>
>>    }<br>
>> -<br>
>> -  uint64_t ArgumentIdx;<br>
>> +<br>
>> +  ParamIdx ArgumentIdx;<br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, 2,<br>
>> AL.getArgAsExpr(1),<br>
>>                                             ArgumentIdx))<br>
>>      return;<br>
>><br>
>> -  uint64_t TypeTagIdx;<br>
>> +  ParamIdx TypeTagIdx;<br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, 3,<br>
>> AL.getArgAsExpr(2),<br>
>>                                             TypeTagIdx))<br>
>>      return;<br>
>> @@ -4553,8 +4536,9 @@ static void handleArgumentWithTypeTagAtt<br>
>>    bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag";<br>
>>    if (IsPointer) {<br>
>>      // Ensure that buffer has a pointer type.<br>
>> -    if (ArgumentIdx >= getFunctionOrMethodNumParams(<wbr>D) ||<br>
>> -        !getFunctionOrMethodParamType(<wbr>D, ArgumentIdx)->isPointerType())<br>
>> +    unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex();<br>
>> +    if (ArgumentIdxAST >= getFunctionOrMethodNumParams(<wbr>D) ||<br>
>> +        !getFunctionOrMethodParamType(<wbr>D,<br>
>> ArgumentIdxAST)-><wbr>isPointerType())<br>
>>        S.Diag(AL.getLoc(), diag::err_attribute_pointers_<wbr>only)<br>
>>            << AL.getName() << 0;<br>
>>    }<br>
>> @@ -4594,19 +4578,18 @@ static void handleTypeTagForDatatypeAttr<br>
>>                                      AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>> -static void handleXRayLogArgsAttr(Sema &S, Decl *D,<br>
>> -                                  const AttributeList &AL) {<br>
>> -  uint64_t ArgCount;<br>
>> +static void handleXRayLogArgsAttr(Sema &S, Decl *D, const AttributeList<br>
>> &AL) {<br>
>> +  ParamIdx ArgCount;<br>
>><br>
>>    if (!<wbr>checkFunctionOrMethodParameter<wbr>Index(S, D, AL, 1,<br>
>> AL.getArgAsExpr(0),<br>
>>                                             ArgCount,<br>
>> -                                           true /* AllowImplicitThis*/))<br>
>> +                                           true /* CanIndexImplicitThis<br>
>> */))<br>
>>      return;<br>
>><br>
>> -  // ArgCount isn't a parameter index [0;n), it's a count [1;n] - hence +<br>
>> 1.<br>
>> -  D->addAttr(::new (S.Context)<br>
>> -                 XRayLogArgsAttr(AL.getRange(), S.Context, ++ArgCount,<br>
>> -                                 AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>> +  // ArgCount isn't a parameter index [0;n), it's a count [1;n]<br>
>> +  D->addAttr(::new (S.Context) XRayLogArgsAttr(<br>
>> +      AL.getRange(), S.Context, ArgCount.getSourceIndex(),<br>
>> +      AL.<wbr>getAttributeSpellingListIndex(<wbr>)));<br>
>>  }<br>
>><br>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
>><br>
>> Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp?rev=326602&r1=326601&r2=<wbr>326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp (original)<br>
>> +++ cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp Fri Mar  2 11:03:22<br>
>> 2018<br>
>> @@ -176,7 +176,7 @@ static void instantiateDependentAllocAli<br>
>>      Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,<br>
>>      const AllocAlignAttr *Align, Decl *New) {<br>
>>    Expr *Param = IntegerLiteral::Create(<br>
>> -      S.getASTContext(), llvm::APInt(64, Align->getParamIndex()),<br>
>> +      S.getASTContext(), llvm::APInt(64,<br>
>> Align->paramIndex().<wbr>getSourceIndex()),<br>
>>        S.getASTContext().<wbr>UnsignedLongLongTy, Align->getLocation());<br>
>>    S.AddAllocAlignAttr(Align-><wbr>getLocation(), New, Param,<br>
>>                        Align->getSpellingListIndex())<wbr>;<br>
>><br>
>> Modified: cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/MallocChecker.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>StaticAnalyzer/Checkers/<wbr>MallocChecker.cpp?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/MallocChecker.cpp (original)<br>
>> +++ cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/MallocChecker.cpp Fri Mar  2<br>
>> 11:03:22 2018<br>
>> @@ -1231,9 +1231,10 @@ MallocChecker::<wbr>MallocMemReturnsAttr(Chec<br>
>>    if (Att->getModule() != II_malloc)<br>
>>      return nullptr;<br>
>><br>
>> -  OwnershipAttr::args_iterator I = Att->args_begin(), E =<br>
>> Att->args_end();<br>
>> +  ParamIdx *I = Att->args_begin(), *E = Att->args_end();<br>
>>    if (I != E) {<br>
>> -    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State);<br>
>> +    return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()),<br>
>> UndefinedVal(),<br>
>> +                        State);<br>
>>    }<br>
>>    return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);<br>
>>  }<br>
>> @@ -1331,9 +1332,9 @@ ProgramStateRef MallocChecker::FreeMemAt<br>
>>    bool ReleasedAllocated = false;<br>
>><br>
>>    for (const auto &Arg : Att->args()) {<br>
>> -    ProgramStateRef StateI = FreeMemAux(C, CE, State, Arg,<br>
>> -                               Att->getOwnKind() == OwnershipAttr::Holds,<br>
>> -                               ReleasedAllocated);<br>
>> +    ProgramStateRef StateI = FreeMemAux(<br>
>> +        C, CE, State, Arg.getASTIndex(),<br>
>> +        Att->getOwnKind() == OwnershipAttr::Holds, ReleasedAllocated);<br>
>>      if (StateI)<br>
>>        State = StateI;<br>
>>    }<br>
>><br>
>> Modified: cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/NonNullParamChecker.<wbr>cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>StaticAnalyzer/Checkers/<wbr>NonNullParamChecker.cpp?rev=<wbr>326602&r1=326601&r2=326602&<wbr>view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/NonNullParamChecker.<wbr>cpp<br>
>> (original)<br>
>> +++ cfe/trunk/lib/StaticAnalyzer/<wbr>Checkers/NonNullParamChecker.<wbr>cpp Fri Mar<br>
>> 2 11:03:22 2018<br>
>> @@ -58,10 +58,11 @@ void NonNullParamChecker::<wbr>checkPreCall(c<br>
>>        AttrNonNull.set(0, NumArgs);<br>
>>        break;<br>
>>      }<br>
>> -    for (unsigned Val : NonNull->args()) {<br>
>> -      if (Val >= NumArgs)<br>
>> +    for (const ParamIdx &Idx : NonNull->args()) {<br>
>> +      unsigned IdxAST = Idx.getASTIndex();<br>
>> +      if (IdxAST >= NumArgs)<br>
>>          continue;<br>
>> -      AttrNonNull.set(Val);<br>
>> +      AttrNonNull.set(IdxAST);<br>
>>      }<br>
>>    }<br>
>><br>
>><br>
>> Modified: cfe/trunk/test/CodeGenCXX/<wbr>alloc-size.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/alloc-size.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/alloc-size.cpp?rev=<wbr>326602&r1=326601&r2=326602&<wbr>view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/CodeGenCXX/<wbr>alloc-size.cpp (original)<br>
>> +++ cfe/trunk/test/CodeGenCXX/<wbr>alloc-size.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -69,4 +69,22 @@ int testIt() {<br>
>>           __builtin_object_size(<wbr>dependent_calloc<7, 8>(), 0) +<br>
>>           __builtin_object_size(<wbr>dependent_calloc2<int, 9>(), 0);<br>
>>  }<br>
>> +} // namespace templated_alloc_size<br>
>> +<br>
>> +class C {<br>
>> +public:<br>
>> +  void *my_malloc(int N) __attribute__((alloc_size(2)))<wbr>;<br>
>> +  void *my_calloc(int N, int M) __attribute__((alloc_size(2, 3)));<br>
>> +};<br>
>> +<br>
>> +// CHECK-LABEL: define i32 @_Z16callMemberMallocv<br>
>> +int callMemberMalloc() {<br>
>> +  // CHECK: ret i32 16<br>
>> +  return __builtin_object_size(C().my_<wbr>malloc(16), 0);<br>
>> +}<br>
>> +<br>
>> +// CHECK-LABEL: define i32 @_Z16callMemberCallocv<br>
>> +int callMemberCalloc() {<br>
>> +  // CHECK: ret i32 32<br>
>> +  return __builtin_object_size(C().my_<wbr>calloc(16, 2), 0);<br>
>>  }<br>
>><br>
>> Modified: cfe/trunk/test/Misc/ast-dump-<wbr>attr.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-attr.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Misc/<wbr>ast-dump-attr.cpp?rev=326602&<wbr>r1=326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/Misc/ast-dump-<wbr>attr.cpp (original)<br>
>> +++ cfe/trunk/test/Misc/ast-dump-<wbr>attr.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -68,12 +68,12 @@ __attribute__((pointer_with_<wbr>type_tag(ide<br>
>>  void TestBool(void *, int)<br>
>>  __attribute__((pointer_with_<wbr>type_tag(bool1,1,2)));<br>
>>  // CHECK: FunctionDecl{{.*}}TestBool<br>
>> -// CHECK:   ArgumentWithTypeTagAttr{{.*}}<wbr>pointer_with_type_tag bool1 0 1<br>
>> IsPointer<br>
>> +// CHECK:   ArgumentWithTypeTagAttr{{.*}}<wbr>pointer_with_type_tag bool1 1 2<br>
>> IsPointer<br>
>><br>
>>  void TestUnsigned(void *, int)<br>
>>  __attribute__((pointer_with_<wbr>type_tag(unsigned1,1,2)));<br>
>>  // CHECK: FunctionDecl{{.*}}TestUnsigned<br>
>> -// CHECK:   ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1<br>
>> 0 1<br>
>> +// CHECK:   ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1<br>
>> 1 2<br>
>><br>
>>  void TestInt(void) __attribute__((constructor(<wbr>123)));<br>
>>  // CHECK:      FunctionDecl{{.*}}TestInt<br>
>><br>
>> Added: cfe/trunk/test/Sema/attr-<wbr>ownership.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-ownership.cpp?rev=326602&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>attr-ownership.cpp?rev=326602&<wbr>view=auto</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/Sema/attr-<wbr>ownership.cpp (added)<br>
>> +++ cfe/trunk/test/Sema/attr-<wbr>ownership.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -0,0 +1,7 @@<br>
>> +// RUN: %clang_cc1 %s -verify -fsyntax-only<br>
>> +<br>
>> +class C {<br>
>> +  void f(int, int)<br>
>> +      __attribute__((ownership_<wbr>returns(foo, 2)))  // expected-note<br>
>> {{declared with index 2 here}}<br>
>> +      __attribute__((ownership_<wbr>returns(foo, 3))); // expected-error<br>
>> {{'ownership_returns' attribute index does not match; here it is 3}}<br>
>> +};<br>
>><br>
>> Modified: cfe/trunk/test/Sema/attr-<wbr>print.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-print.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>attr-print.cpp?rev=326602&r1=<wbr>326601&r2=326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/Sema/attr-<wbr>print.cpp (original)<br>
>> +++ cfe/trunk/test/Sema/attr-<wbr>print.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -1,6 +1,67 @@<br>
>>  // RUN: %clang_cc1 %s -ast-print | FileCheck %s<br>
>><br>
>> +// CHECK: void xla(int a) __attribute__((xray_log_args(<wbr>1)));<br>
>> +void xla(int a) __attribute__((xray_log_args(<wbr>1)));<br>
>> +<br>
>>  // CHECK: void *as2(int, int) __attribute__((alloc_size(1, 2)));<br>
>>  void *as2(int, int) __attribute__((alloc_size(1, 2)));<br>
>>  // CHECK: void *as1(void *, int) __attribute__((alloc_size(2)))<wbr>;<br>
>>  void *as1(void *, int) __attribute__((alloc_size(2)))<wbr>;<br>
>> +<br>
>> +// CHECK: void fmt(int, const char *, ...) __attribute__((format(printf,<br>
>> 2, 3)));<br>
>> +void fmt(int, const char *, ...) __attribute__((format(printf, 2, 3)));<br>
>> +<br>
>> +// CHECK: char *fmta(int, const char *) __attribute__((format_arg(2)))<wbr>;<br>
>> +char *fmta(int, const char *) __attribute__((format_arg(2)))<wbr>;<br>
>> +<br>
>> +// CHECK: void nn(int *, int *) __attribute__((nonnull(1, 2)));<br>
>> +void nn(int *, int *) __attribute__((nonnull(1, 2)));<br>
>> +<br>
>> +// CHECK: int *aa(int i) __attribute__((alloc_align(1))<wbr>);<br>
>> +int *aa(int i) __attribute__((alloc_align(1))<wbr>);<br>
>> +<br>
>> +// CHECK: void ownt(int *, int *) __attribute__((ownership_<wbr>takes(foo, 1,<br>
>> 2)));<br>
>> +void ownt(int *, int *) __attribute__((ownership_<wbr>takes(foo, 1, 2)));<br>
>> +// CHECK: void ownh(int *, int *) __attribute__((ownership_<wbr>holds(foo, 1,<br>
>> 2)));<br>
>> +void ownh(int *, int *) __attribute__((ownership_<wbr>holds(foo, 1, 2)));<br>
>> +// CHECK: void ownr(int) __attribute__((ownership_<wbr>returns(foo, 1)));<br>
>> +void ownr(int) __attribute__((ownership_<wbr>returns(foo, 1)));<br>
>> +<br>
>> +// CHECK: void awtt(int, int, ...)<br>
>> __attribute__((argument_with_<wbr>type_tag(foo, 3, 2)));<br>
>> +void awtt(int, int, ...) __attribute__((argument_with_<wbr>type_tag(foo, 3,<br>
>> 2)));<br>
>> +// CHECK: void pwtt(void *, int)<br>
>> __attribute__((pointer_with_<wbr>type_tag(foo, 1, 2)));<br>
>> +void pwtt(void *, int) __attribute__((pointer_with_<wbr>type_tag(foo, 1, 2)));<br>
>> +<br>
>> +class C {<br>
>> +  // CHECK: void xla(int a) __attribute__((xray_log_args(<wbr>2)));<br>
>> +  void xla(int a) __attribute__((xray_log_args(<wbr>2)));<br>
>> +<br>
>> +  // CHECK: void *as2(int, int) __attribute__((alloc_size(2, 3)));<br>
>> +  void *as2(int, int) __attribute__((alloc_size(2, 3)));<br>
>> +  // CHECK: void *as1(void *, int) __attribute__((alloc_size(3)))<wbr>;<br>
>> +  void *as1(void *, int) __attribute__((alloc_size(3)))<wbr>;<br>
>> +<br>
>> +  // CHECK: void fmt(int, const char *, ...)<br>
>> __attribute__((format(printf, 3, 4)));<br>
>> +  void fmt(int, const char *, ...) __attribute__((format(printf, 3, 4)));<br>
>> +<br>
>> +  // CHECK: char *fmta(int, const char *) __attribute__((format_arg(3)))<wbr>;<br>
>> +  char *fmta(int, const char *) __attribute__((format_arg(3)))<wbr>;<br>
>> +<br>
>> +  // CHECK: void nn(int *, int *) __attribute__((nonnull(2, 3)));<br>
>> +  void nn(int *, int *) __attribute__((nonnull(2, 3)));<br>
>> +<br>
>> +  // CHECK: int *aa(int i) __attribute__((alloc_align(2))<wbr>);<br>
>> +  int *aa(int i) __attribute__((alloc_align(2))<wbr>);<br>
>> +<br>
>> +  // CHECK: void ownt(int *, int *) __attribute__((ownership_<wbr>takes(foo,<br>
>> 2, 3)));<br>
>> +  void ownt(int *, int *) __attribute__((ownership_<wbr>takes(foo, 2, 3)));<br>
>> +  // CHECK: void ownh(int *, int *) __attribute__((ownership_<wbr>holds(foo,<br>
>> 2, 3)));<br>
>> +  void ownh(int *, int *) __attribute__((ownership_<wbr>holds(foo, 2, 3)));<br>
>> +  // CHECK: void ownr(int) __attribute__((ownership_<wbr>returns(foo, 2)));<br>
>> +  void ownr(int) __attribute__((ownership_<wbr>returns(foo, 2)));<br>
>> +<br>
>> +  // CHECK: void awtt(int, int, ...)<br>
>> __attribute__((argument_with_<wbr>type_tag(foo, 4, 3)));<br>
>> +  void awtt(int, int, ...) __attribute__((argument_with_<wbr>type_tag(foo, 4,<br>
>> 3)));<br>
>> +  // CHECK: void pwtt(void *, int)<br>
>> __attribute__((pointer_with_<wbr>type_tag(foo, 2, 3)));<br>
>> +  void pwtt(void *, int) __attribute__((pointer_with_<wbr>type_tag(foo, 2,<br>
>> 3)));<br>
>> +};<br>
>><br>
>> Modified: cfe/trunk/test/Sema/error-<wbr>type-safety.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/error-type-safety.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Sema/<wbr>error-type-safety.cpp?rev=<wbr>326602&r1=326601&r2=326602&<wbr>view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/test/Sema/error-<wbr>type-safety.cpp (original)<br>
>> +++ cfe/trunk/test/Sema/error-<wbr>type-safety.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -3,21 +3,50 @@<br>
>>  #define INT_TAG 42<br>
>><br>
>>  static const int test_in<br>
>> -  __attribute__((type_tag_for_<wbr>datatype(test, int))) = INT_TAG;<br>
>> +    __attribute__((type_tag_for_<wbr>datatype(test, int))) = INT_TAG;<br>
>><br>
>>  // Argument index: 1, Type tag index: 2<br>
>>  void test_bounds_index(...)<br>
>> -  __attribute__((argument_with_<wbr>type_tag(test, 1, 2)));<br>
>> +    __attribute__((argument_with_<wbr>type_tag(test, 1, 2)));<br>
>> +<br>
>> +// Argument index: 1, Type tag index: 2<br>
>> +void test_bounds_index_ptr(void *, ...)<br>
>> +    __attribute__((pointer_with_<wbr>type_tag(test, 1, 2)));<br>
>><br>
>>  // Argument index: 3, Type tag index: 1<br>
>>  void test_bounds_arg_index(...)<br>
>> -  __attribute__((argument_with_<wbr>type_tag(test, 3, 1)));<br>
>> +    __attribute__((argument_with_<wbr>type_tag(test, 3, 1)));<br>
>> +<br>
>> +class C {<br>
>> +public:<br>
>> +  // Argument index: 2, Type tag index: 3<br>
>> +  void test_bounds_index(...)<br>
>> +      __attribute__((argument_with_<wbr>type_tag(test, 2, 3)));<br>
>> +<br>
>> +  // Argument index: 2, Type tag index: 3<br>
>> +  void test_bounds_index_ptr(void *, ...)<br>
>> +      __attribute__((pointer_with_<wbr>type_tag(test, 2, 3)));<br>
>> +<br>
>> +  // Argument index: 4, Type tag index: 2<br>
>> +  void test_bounds_arg_index(...)<br>
>> +      __attribute__((argument_with_<wbr>type_tag(test, 4, 2)));<br>
>> +};<br>
>><br>
>>  void test_bounds()<br>
>>  {<br>
>> +  C c;<br>
>> +<br>
>>    // Test the boundary edges (ensure no off-by-one) with argument<br>
>> indexing.<br>
>>    test_bounds_index(1, INT_TAG);<br>
>> +  c.test_bounds_index(1, INT_TAG);<br>
>> +  test_bounds_index_ptr(0, INT_TAG);<br>
>> +  c.test_bounds_index_ptr(0, INT_TAG);<br>
>> +<br>
>> +  test_bounds_index(1);       // expected-error {{type tag index 2 is<br>
>> greater than the number of arguments specified}}<br>
>> +  c.test_bounds_index(1);     // expected-error {{type tag index 3 is<br>
>> greater than the number of arguments specified}}<br>
>> +  test_bounds_index_ptr(0);   // expected-error {{type tag index 2 is<br>
>> greater than the number of arguments specified}}<br>
>> +  c.test_bounds_index_ptr(0); // expected-error {{type tag index 3 is<br>
>> greater than the number of arguments specified}}<br>
>><br>
>> -  test_bounds_index(1); // expected-error {{type tag index 2 is greater<br>
>> than the number of arguments specified}}<br>
>> -  test_bounds_arg_index(INT_TAG, 1); // expected-error {{argument index 3<br>
>> is greater than the number of arguments specified}}<br>
>> +  test_bounds_arg_index(INT_TAG, 1);   // expected-error {{argument index<br>
>> 3 is greater than the number of arguments specified}}<br>
>> +  c.test_bounds_arg_index(INT_<wbr>TAG, 1); // expected-error {{argument index<br>
>> 4 is greater than the number of arguments specified}}<br>
>>  }<br>
>><br>
>> Modified: cfe/trunk/utils/TableGen/<wbr>ClangAttrEmitter.cpp<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=326602&r1=326601&r2=326602&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/utils/<wbr>TableGen/ClangAttrEmitter.cpp?<wbr>rev=326602&r1=326601&r2=<wbr>326602&view=diff</a><br>
>><br>
>> ==============================<wbr>==============================<wbr>==================<br>
>> --- cfe/trunk/utils/TableGen/<wbr>ClangAttrEmitter.cpp (original)<br>
>> +++ cfe/trunk/utils/TableGen/<wbr>ClangAttrEmitter.cpp Fri Mar  2 11:03:22 2018<br>
>> @@ -302,9 +302,6 @@ namespace {<br>
>>      std::string getIsOmitted() const override {<br>
>>        if (type == "IdentifierInfo *")<br>
>>          return "!get" + getUpperName().str() + "()";<br>
>> -      // FIXME: Do this declaratively in Attr.td.<br>
>> -      if (getAttrName() == "AllocSize")<br>
>> -        return "0 == get" + getUpperName().str() + "()";<br>
>>        return "false";<br>
>>      }<br>
>><br>
>> @@ -748,6 +745,138 @@ namespace {<br>
>>      }<br>
>>    };<br>
>><br>
>> +  class VariadicParamIdxArgument : public VariadicArgument {<br>
>> +  public:<br>
>> +    VariadicParamIdxArgument(const Record &Arg, StringRef Attr)<br>
>> +        : VariadicArgument(Arg, Attr, "ParamIdx") {}<br>
>> +<br>
>> +  public:<br>
>> +    void writeCtorBody(raw_ostream &OS) const override {<br>
>> +      VariadicArgument::<wbr>writeCtorBody(OS);<br>
>> +      OS << "    #ifndef NDEBUG\n"<br>
>> +         << "    if (" << getLowerName() << "_size()) {\n"<br>
>> +         << "      bool HasThis = " << getLowerName()<br>
>> +         << "_begin()->hasThis();\n"<br>
>> +         << "      for (const auto Idx : " << getLowerName() << "()) {\n"<br>
>> +         << "        assert(Idx.isValid() && \"ParamIdx must be<br>
>> valid\");\n"<br>
>> +         << "        assert(HasThis == Idx.hasThis() && "<br>
>> +         << "\"HasThis must be consistent\");\n"<br>
>> +         << "      }\n"<br>
>> +         << "    }\n"<br>
>> +         << "    #endif\n";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHReadDecls(raw_ostream &OS) const override {<br>
>> +      OS << "    unsigned " << getUpperName() << "Size =<br>
>> Record.readInt();\n";<br>
>> +      OS << "    bool " << getUpperName() << "HasThis = " <<<br>
>> getUpperName()<br>
>> +         << "Size ? Record.readInt() : false;\n";<br>
>> +      OS << "    SmallVector<ParamIdx, 4> " << getUpperName() << ";\n"<br>
>> +         << "    " << getUpperName() << ".reserve(" << getUpperName()<br>
>> +         << "Size);\n"<br>
>> +         << "    for (unsigned i = 0; i != " << getUpperName()<br>
>> +         << "Size; ++i) {\n"<br>
>> +         << "      " << getUpperName()<br>
>> +         << ".push_back(ParamIdx(Record.<wbr>readInt(), " << getUpperName()<br>
>> +         << "HasThis));\n"<br>
>> +         << "    }\n";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHReadArgs(raw_ostream &OS) const override {<br>
>> +      OS << getUpperName() << ".data(), " << getUpperName() << "Size";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHWrite(raw_ostream &OS) const override {<br>
>> +      OS << "    Record.push_back(SA->" << getLowerName() <<<br>
>> "_size());\n";<br>
>> +      OS << "    if (SA->" << getLowerName() << "_size())\n"<br>
>> +         << "      Record.push_back(SA->" << getLowerName()<br>
>> +         << "_begin()->hasThis());\n";<br>
>> +      OS << "    for (auto Idx : SA->" << getLowerName() << "())\n"<br>
>> +         << "      Record.push_back(Idx.<wbr>getSourceIndex());\n";<br>
>> +    }<br>
>> +<br>
>> +    void writeValueImpl(raw_ostream &OS) const override {<br>
>> +      OS << "    OS << Val.getSourceIndex();\n";<br>
>> +    }<br>
>> +<br>
>> +    void writeDump(raw_ostream &OS) const override {<br>
>> +      OS << "    for (auto Idx : SA->" << getLowerName() << "())\n";<br>
>> +      OS << "      OS << \" \" << Idx.getSourceIndex();\n";<br>
>> +    }<br>
>> +  };<br>
>> +<br>
>> +  class ParamIdxArgument : public Argument {<br>
>> +    std::string IdxName;<br>
>> +<br>
>> +  public:<br>
>> +    ParamIdxArgument(const Record &Arg, StringRef Attr)<br>
>> +        : Argument(Arg, Attr), IdxName(getUpperName()) {}<br>
>> +<br>
>> +    void writeDeclarations(raw_ostream &OS) const override {<br>
>> +      OS << "ParamIdx " << IdxName << ";\n";<br>
>> +    }<br>
>> +<br>
>> +    void writeAccessors(raw_ostream &OS) const override {<br>
>> +      OS << "\n"<br>
>> +         << "  ParamIdx " << getLowerName() << "() const {"<br>
>> +         << " return " << IdxName << "; }\n";<br>
>> +    }<br>
>> +<br>
>> +    void writeCtorParameters(raw_<wbr>ostream &OS) const override {<br>
>> +      OS << "ParamIdx " << IdxName;<br>
>> +    }<br>
>> +<br>
>> +    void writeCloneArgs(raw_ostream &OS) const override { OS << IdxName;<br>
>> }<br>
>> +<br>
>> +    void writeTemplateInstantiationArgs<wbr>(raw_ostream &OS) const override {<br>
>> +      OS << "A->" << getLowerName() << "()";<br>
>> +    }<br>
>> +<br>
>> +    void writeImplicitCtorArgs(raw_<wbr>ostream &OS) const override {<br>
>> +      OS << IdxName;<br>
>> +    }<br>
>> +<br>
>> +    void writeCtorInitializers(raw_<wbr>ostream &OS) const override {<br>
>> +      OS << IdxName << "(" << IdxName << ")";<br>
>> +    }<br>
>> +<br>
>> +    void writeCtorDefaultInitializers(<wbr>raw_ostream &OS) const override {<br>
>> +      OS << IdxName << "()";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHReadDecls(raw_ostream &OS) const override {<br>
>> +      OS << "    unsigned " << IdxName << "Src = Record.readInt();\n";<br>
>> +      OS << "    bool " << IdxName << "HasThis = Record.readInt();\n";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHReadArgs(raw_ostream &OS) const override {<br>
>> +      OS << "ParamIdx(" << IdxName << "Src, " << IdxName << "HasThis)";<br>
>> +    }<br>
>> +<br>
>> +    void writePCHWrite(raw_ostream &OS) const override {<br>
>> +      OS << "    Record.push_back(SA->" << getLowerName()<br>
>> +         << "().isValid() ? SA->" << getLowerName()<br>
>> +         << "().getSourceIndex() : 0);\n";<br>
>> +      OS << "    Record.push_back(SA->" << getLowerName()<br>
>> +         << "().isValid() ? SA->" << getLowerName()<br>
>> +         << "().hasThis() : false);\n";<br>
>> +    }<br>
>> +<br>
>> +    std::string getIsOmitted() const override {<br>
>> +      return "!" + IdxName + ".isValid()";<br>
>> +    }<br>
>> +<br>
>> +    void writeValue(raw_ostream &OS) const override {<br>
>> +      OS << "\" << " << IdxName << ".getSourceIndex() << \"";<br>
>> +    }<br>
>> +<br>
>> +    void writeDump(raw_ostream &OS) const override {<br>
>> +      if (isOptional())<br>
>> +        OS << "    if (SA->" << getLowerName() << "().isValid())\n  ";<br>
>> +      OS << "    OS << \" \" << SA->" << getLowerName()<br>
>> +         << "().getSourceIndex();\n";<br>
>> +    }<br>
>> +  };<br>
>> +<br>
>>    // Unique the enums, but maintain the original declaration ordering.<br>
>>    std::vector<StringRef><br>
>>    uniqueEnumsInOrder(const std::vector<StringRef> &enums) {<br>
>> @@ -1247,6 +1376,10 @@ createArgument(const Record &Arg, String<br>
>>      Ptr = llvm::make_unique<<wbr>VariadicEnumArgument>(Arg, Attr);<br>
>>    else if (ArgName == "VariadicExprArgument")<br>
>>      Ptr = llvm::make_unique<<wbr>VariadicExprArgument>(Arg, Attr);<br>
>> +  else if (ArgName == "VariadicParamIdxArgument")<br>
>> +    Ptr = llvm::make_unique<<wbr>VariadicParamIdxArgument>(Arg, Attr);<br>
>> +  else if (ArgName == "ParamIdxArgument")<br>
>> +    Ptr = llvm::make_unique<<wbr>ParamIdxArgument>(Arg, Attr);<br>
>>    else if (ArgName == "VersionArgument")<br>
>>      Ptr = llvm::make_unique<<wbr>VersionArgument>(Arg, Attr);<br>
>><br>
>><br>
>><br>
>> ______________________________<wbr>_________________<br>
>> cfe-commits mailing list<br>
>> <a href="mailto:cfe-commits@lists.llvm.org">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>
><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@lists.llvm.org">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>
><br>
</div></div></blockquote></div><br></div>