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