diff options
author | Nico Weber <nicolasweber@gmx.de> | 2018-03-07 02:22:41 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2018-03-07 02:22:41 +0000 |
commit | bbf648253d096b4e25f588583df8ed8e764a28bb (patch) | |
tree | 0b02e45d28db415c8f5fa00795969510f93c1fd0 | |
parent | 204ade4102c7959cc56e03f163ad7473c94a0b38 (diff) | |
download | bcm5719-llvm-bbf648253d096b4e25f588583df8ed8e764a28bb.tar.gz bcm5719-llvm-bbf648253d096b4e25f588583df8ed8e764a28bb.zip |
Revert r326602, it caused PR36620.
llvm-svn: 326862
-rw-r--r-- | clang/include/clang/AST/Attr.h | 114 | ||||
-rw-r--r-- | clang/include/clang/Basic/Attr.td | 44 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 37 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 149 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 11 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp | 7 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/alloc-size.cpp | 18 | ||||
-rw-r--r-- | clang/test/Misc/ast-dump-attr.cpp | 4 | ||||
-rw-r--r-- | clang/test/Sema/attr-ownership.cpp | 7 | ||||
-rw-r--r-- | clang/test/Sema/attr-print.cpp | 61 | ||||
-rw-r--r-- | clang/test/Sema/error-type-safety.cpp | 39 | ||||
-rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 139 |
16 files changed, 150 insertions, 503 deletions
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 38dce44ddec..a7c766a65ce 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -195,120 +195,6 @@ 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, diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 92d1dd60151..afb516b5a6f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -169,12 +169,6 @@ class VariadicUnsignedArgument<string name> : Argument<name, 1>; 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>; @@ -620,12 +614,6 @@ 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]; } @@ -1033,8 +1021,7 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { def AllocSize : InheritableAttr { let Spellings = [GCC<"alloc_size">]; let Subjects = SubjectList<[Function]>; - let Args = [ParamIdxArgument<"ElemSizeParam">, - ParamIdxArgument<"NumElemsParam", /*opt*/ 1>]; + let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>]; let TemplateDependent = 1; let Documentation = [AllocSizeDocs]; } @@ -1121,7 +1108,7 @@ def Format : InheritableAttr { def FormatArg : InheritableAttr { let Spellings = [GCC<"format_arg">]; - let Args = [ParamIdxArgument<"FormatIdx">]; + let Args = [IntArgument<"FormatIdx">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -1401,16 +1388,16 @@ def NonNull : InheritableParamAttr { let Spellings = [GCC<"nonnull">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, "functions, methods, and parameters">; - let Args = [VariadicParamIdxArgument<"Args">]; - let AdditionalMembers = [{ - bool isNonNull(unsigned IdxAST) const { - if (!args_size()) + let Args = [VariadicUnsignedArgument<"Args">]; + let AdditionalMembers = +[{bool isNonNull(unsigned idx) const { + if (!args_size()) + return true; + for (const auto &V : args()) + if (V == idx) return true; - return args_end() != std::find_if( - args_begin(), args_end(), - [=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST; }); - } - }]; + return false; + } }]; // FIXME: We should merge duplicates into a single nonnull attribute. let InheritEvenIfAlreadyPresent = 1; let Documentation = [NonNullDocs]; @@ -1468,7 +1455,7 @@ def AssumeAligned : InheritableAttr { def AllocAlign : InheritableAttr { let Spellings = [GCC<"alloc_align">]; let Subjects = SubjectList<[HasFunctionProto]>; - let Args = [ParamIdxArgument<"ParamIndex">]; + let Args = [IntArgument<"ParamIndex">]; let Documentation = [AllocAlignDocs]; } @@ -1677,8 +1664,7 @@ def Ownership : InheritableAttr { Returns; } }]; - let Args = [IdentifierArgument<"Module">, - VariadicParamIdxArgument<"Args">]; + let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">]; let Subjects = SubjectList<[HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -2504,8 +2490,8 @@ def ArgumentWithTypeTag : InheritableAttr { Clang<"pointer_with_type_tag">]; let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>; let Args = [IdentifierArgument<"ArgumentKind">, - ParamIdxArgument<"ArgumentIdx">, - ParamIdxArgument<"TypeTagIdx">, + UnsignedArgument<"ArgumentIdx">, + UnsignedArgument<"TypeTagIdx">, BoolArgument<"IsPointer", /*opt*/0, /*fake*/1>]; let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs]; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 135e70e96ad..c3e41658c29 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5467,8 +5467,9 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, llvm::APInt &Result) { const AllocSizeAttr *AllocSize = getAllocSizeAttr(Call); - assert(AllocSize && AllocSize->elemSizeParam().isValid()); - unsigned SizeArgNo = AllocSize->elemSizeParam().getASTIndex(); + // alloc_size args are 1-indexed, 0 means not present. + assert(AllocSize && AllocSize->getElemSizeParam() != 0); + unsigned SizeArgNo = AllocSize->getElemSizeParam() - 1; unsigned BitsInSizeT = Ctx.getTypeSize(Ctx.getSizeType()); if (Call->getNumArgs() <= SizeArgNo) return false; @@ -5486,13 +5487,14 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx, if (!EvaluateAsSizeT(Call->getArg(SizeArgNo), SizeOfElem)) return false; - if (!AllocSize->numElemsParam().isValid()) { + if (!AllocSize->getNumElemsParam()) { Result = std::move(SizeOfElem); return true; } APSInt NumberOfElems; - unsigned NumArgNo = AllocSize->numElemsParam().getASTIndex(); + // Argument numbers start at 1 + unsigned NumArgNo = AllocSize->getNumElemsParam() - 1; if (!EvaluateAsSizeT(Call->getArg(NumArgNo), NumberOfElems)) return false; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 187697ee0b6..48841b564e4 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1847,9 +1847,10 @@ void CodeGenModule::ConstructAttributeList( HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { Optional<unsigned> NumElemsParam; - if (AllocSize->numElemsParam().isValid()) - NumElemsParam = AllocSize->numElemsParam().getLLVMIndex(); - FuncAttrs.addAllocSizeAttr(AllocSize->elemSizeParam().getLLVMIndex(), + // alloc_size args are base-1, 0 means not present. + if (unsigned N = AllocSize->getNumElemsParam()) + NumElemsParam = N - 1; + FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1, NumElemsParam); } } @@ -4392,7 +4393,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, OffsetValue); } else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) { llvm::Value *ParamVal = - CallArgs[AA->paramIndex().getLLVMIndex()].RV.getScalarVal(); + CallArgs[AA->getParamIndex() - 1].RV.getScalarVal(); EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal); } } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 9caabde35b6..568ba98020e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2619,13 +2619,12 @@ static void CheckNonNullArguments(Sema &S, return; } - for (const ParamIdx &Idx : NonNull->args()) { - unsigned IdxAST = Idx.getASTIndex(); - if (IdxAST >= Args.size()) + for (unsigned Val : NonNull->args()) { + if (Val >= Args.size()) continue; if (NonNullArgs.empty()) NonNullArgs.resize(Args.size()); - NonNullArgs.set(IdxAST); + NonNullArgs.set(Val); } } } @@ -5003,7 +5002,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, const CallExpr *CE = cast<CallExpr>(E); if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) { if (const FormatArgAttr *FA = ND->getAttr<FormatArgAttr>()) { - const Expr *Arg = CE->getArg(FA->formatIdx().getASTIndex()); + unsigned ArgIndex = FA->getFormatIdx(); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) + if (MD->isInstance()) + --ArgIndex; + const Expr *Arg = CE->getArg(ArgIndex - 1); + return checkFormatStringExpr(S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, InFunctionCall, @@ -5028,7 +5032,8 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args, const auto *ME = cast<ObjCMessageExpr>(E); if (const auto *ND = ME->getMethodDecl()) { if (const auto *FA = ND->getAttr<FormatArgAttr>()) { - const Expr *Arg = ME->getArg(FA->formatIdx().getASTIndex()); + unsigned ArgIndex = FA->getFormatIdx(); + const Expr *Arg = ME->getArg(ArgIndex - 1); return checkFormatStringExpr( S, Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, InFunctionCall, CheckedVarArgs, UncoveredArg, Offset); @@ -10081,8 +10086,8 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, return; } - for (const ParamIdx &ArgNo : NonNull->args()) { - if (ArgNo.getASTIndex() == ParamNo) { + for (unsigned ArgNo : NonNull->args()) { + if (ArgNo == ParamNo) { ComplainAboutNonnullParamOrCall(NonNull); return; } @@ -12237,13 +12242,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, bool IsPointerAttr = Attr->getIsPointer(); // Retrieve the argument representing the 'type_tag'. - unsigned TypeTagIdxAST = Attr->typeTagIdx().getASTIndex(); - if (TypeTagIdxAST >= ExprArgs.size()) { + if (Attr->getTypeTagIdx() >= ExprArgs.size()) { + // Add 1 to display the user's specified value. Diag(CallSiteLoc, diag::err_tag_index_out_of_range) - << 0 << Attr->typeTagIdx().getSourceIndex(); + << 0 << Attr->getTypeTagIdx() + 1; return; } - const Expr *TypeTagExpr = ExprArgs[TypeTagIdxAST]; + const Expr *TypeTagExpr = ExprArgs[Attr->getTypeTagIdx()]; bool FoundWrongKind; TypeTagData TypeInfo; if (!GetMatchingCType(ArgumentKind, TypeTagExpr, Context, @@ -12257,13 +12262,13 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, } // Retrieve the argument representing the 'arg_idx'. - unsigned ArgumentIdxAST = Attr->argumentIdx().getASTIndex(); - if (ArgumentIdxAST >= ExprArgs.size()) { + if (Attr->getArgumentIdx() >= ExprArgs.size()) { + // Add 1 to display the user's specified value. Diag(CallSiteLoc, diag::err_tag_index_out_of_range) - << 1 << Attr->argumentIdx().getSourceIndex(); + << 1 << Attr->getArgumentIdx() + 1; return; } - const Expr *ArgumentExpr = ExprArgs[ArgumentIdxAST]; + const Expr *ArgumentExpr = ExprArgs[Attr->getArgumentIdx()]; if (IsPointerAttr) { // Skip implicit cast of pointer to `void *' (as a function argument). if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr)) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 65b6d06c64e..c2e3da386ed 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13176,7 +13176,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // 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, ParamIdx(1, FD), + FD->addAttr(FormatArgAttr::CreateImplicit(Context, 1, FD->getLocation())); } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b35c3114ff6..fb430da8015 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -311,7 +311,7 @@ static bool checkAttrMutualExclusion(Sema &S, Decl *D, SourceRange Range, template <typename AttrInfo> static bool checkFunctionOrMethodParameterIndex( Sema &S, const Decl *D, const AttrInfo &AI, unsigned AttrArgNum, - const Expr *IdxExpr, ParamIdx &Idx, bool CanIndexImplicitThis = false) { + const Expr *IdxExpr, uint64_t &Idx, bool AllowImplicitThis = false) { assert(isFunctionOrMethodOrBlock(D)); // In C++ the implicit 'this' function parameter also counts. @@ -331,20 +331,21 @@ static bool checkFunctionOrMethodParameterIndex( return false; } - Idx = ParamIdx(IdxInt.getLimitedValue(UINT_MAX), D); - unsigned IdxSource = Idx.getSourceIndex(); - if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { + Idx = IdxInt.getLimitedValue(); + if (Idx < 1 || (!IV && Idx > NumParams)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) - << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange(); + << getAttrName(AI) << AttrArgNum << IdxExpr->getSourceRange(); return false; } - if (HasImplicitThisParam && !CanIndexImplicitThis) { - if (IdxSource == 1) { + Idx--; // Convert to zero-based. + if (HasImplicitThisParam && !AllowImplicitThis) { + if (Idx == 0) { S.Diag(getAttrLoc(AI), diag::err_attribute_invalid_implicit_this_argument) - << getAttrName(AI) << IdxExpr->getSourceRange(); + << getAttrName(AI) << IdxExpr->getSourceRange(); return false; } + --Idx; } return true; @@ -771,15 +772,18 @@ static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, /// 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) { + const AttrInfo &AI, unsigned AttrArgNo, + bool AllowDependentType = false) { assert(AI.isArgExpr(AttrArgNo) && "Expected expression argument"); Expr *AttrArg = AI.getArgAsExpr(AttrArgNo); - ParamIdx Idx; + uint64_t Idx; if (!checkFunctionOrMethodParameterIndex(S, FD, AI, AttrArgNo + 1, AttrArg, Idx)) return false; - const ParmVarDecl *Param = FD->getParamDecl(Idx.getASTIndex()); + const ParmVarDecl *Param = FD->getParamDecl(Idx); + if (AllowDependentType && Param->getType()->isDependentType()) + return true; if (!Param->getType()->isIntegerType() && !Param->getType()->isCharType()) { SourceLocation SrcLoc = AttrArg->getLocStart(); S.Diag(SrcLoc, diag::err_attribute_integers_only) @@ -802,23 +806,22 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &AL) { } const Expr *SizeExpr = AL.getArgAsExpr(0); - int SizeArgNoVal; + int SizeArgNo; // Parameter indices are 1-indexed, hence Index=1 - if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1)) + if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNo, /*Index=*/1)) return; - ParamIdx SizeArgNo(SizeArgNoVal, D); if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0)) return; - ParamIdx NumberArgNo; + // Args are 1-indexed, so 0 implies that the arg was not present + int NumberArgNo = 0; 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, Val, /*Index=*/2)) + if (!checkPositiveIntArgument(S, AL, NumberExpr, NumberArgNo, + /*Index=*/2)) return; - NumberArgNo = ParamIdx(Val, D); if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1)) return; @@ -1421,19 +1424,18 @@ static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &AL, } static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &AL) { - SmallVector<ParamIdx, 8> NonNullArgs; + SmallVector<unsigned, 8> NonNullArgs; for (unsigned I = 0; I < AL.getNumArgs(); ++I) { Expr *Ex = AL.getArgAsExpr(I); - ParamIdx Idx; + uint64_t Idx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, I + 1, Ex, Idx)) return; // Is the function argument a pointer type? - if (Idx.getASTIndex() < getFunctionOrMethodNumParams(D) && - !attrNonNullArgCheck( - S, getFunctionOrMethodParamType(D, Idx.getASTIndex()), AL, - Ex->getSourceRange(), - getFunctionOrMethodParamRange(D, Idx.getASTIndex()))) + if (Idx < getFunctionOrMethodNumParams(D) && + !attrNonNullArgCheck(S, getFunctionOrMethodParamType(D, Idx), AL, + Ex->getSourceRange(), + getFunctionOrMethodParamRange(D, Idx))) continue; NonNullArgs.push_back(Idx); @@ -1457,12 +1459,12 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &AL) { S.Diag(AL.getLoc(), diag::warn_attribute_nonnull_no_pointers); } - ParamIdx *Start = NonNullArgs.data(); + unsigned *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, @@ -1483,8 +1485,8 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, 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, @@ -1585,7 +1587,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr, unsigned SpellingListIndex) { QualType ResultType = getFunctionOrMethodResultType(D); - AllocAlignAttr TmpAttr(AttrRange, Context, ParamIdx(), SpellingListIndex); + AllocAlignAttr TmpAttr(AttrRange, Context, 0, SpellingListIndex); SourceLocation AttrLoc = AttrRange.getBegin(); if (!ResultType->isDependentType() && @@ -1595,22 +1597,28 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr, return; } - ParamIdx Idx; + uint64_t IndexVal; const auto *FuncDecl = cast<FunctionDecl>(D); if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr, - /*AttrArgNo=*/1, ParamExpr, Idx)) + /*AttrArgNo=*/1, ParamExpr, + IndexVal)) return; - QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); + QualType Ty = getFunctionOrMethodParamType(D, IndexVal); if (!Ty->isDependentType() && !Ty->isIntegralType(Context)) { Diag(ParamExpr->getLocStart(), diag::err_attribute_integers_only) - << &TmpAttr - << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange(); + << &TmpAttr << FuncDecl->getParamDecl(IndexVal)->getSourceRange(); return; } - D->addAttr(::new (Context) - AllocAlignAttr(AttrRange, Context, Idx, SpellingListIndex)); + // 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)); } /// Normalize the attribute, __foo__ becomes foo. @@ -1670,15 +1678,15 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { Module = &S.PP.getIdentifierTable().get(ModuleName); } - SmallVector<ParamIdx, 8> OwnershipArgs; + SmallVector<unsigned, 8> OwnershipArgs; for (unsigned i = 1; i < AL.getNumArgs(); ++i) { Expr *Ex = AL.getArgAsExpr(i); - ParamIdx Idx; + uint64_t Idx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, i, Ex, Idx)) return; // Is the function argument a pointer type? - QualType T = getFunctionOrMethodParamType(D, Idx.getASTIndex()); + QualType T = getFunctionOrMethodParamType(D, Idx); int Err = -1; // No error switch (K) { case OwnershipAttr::Takes: @@ -1709,13 +1717,14 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { } else if (K == OwnershipAttr::Returns && I->getOwnKind() == OwnershipAttr::Returns) { // A returns attribute conflicts with any other returns attribute using - // a different index. + // a different index. Note, diagnostic reporting is 1-based, but stored + // argument indexes are 0-based. 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()->getSourceIndex(); + << *(I->args_begin()) + 1; if (I->args_size()) S.Diag(AL.getLoc(), diag::note_ownership_returns_index_mismatch) - << Idx.getSourceIndex() << Ex->getSourceRange(); + << (unsigned)Idx + 1 << Ex->getSourceRange(); return; } } @@ -1723,12 +1732,13 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { OwnershipArgs.push_back(Idx); } - ParamIdx *Start = OwnershipArgs.data(); - unsigned Size = OwnershipArgs.size(); - llvm::array_pod_sort(Start, Start + Size); + unsigned* 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) { @@ -3046,12 +3056,12 @@ static void handleEnumExtensibilityAttr(Sema &S, Decl *D, /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &AL) { Expr *IdxExpr = AL.getArgAsExpr(0); - ParamIdx Idx; + uint64_t Idx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, IdxExpr, Idx)) return; // Make sure the format string is really a string. - QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); + QualType Ty = getFunctionOrMethodParamType(D, Idx); bool NotNSStringTy = !isNSStringType(Ty, S.Context); if (NotNSStringTy && @@ -3074,8 +3084,15 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &AL) { return; } - D->addAttr(::new (S.Context) FormatArgAttr( - AL.getRange(), S.Context, Idx, AL.getAttributeSpellingListIndex())); + // 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())); } enum FormatAttrKind { @@ -4469,13 +4486,13 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, << AL.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; return; } - - ParamIdx ArgumentIdx; + + uint64_t ArgumentIdx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, AL.getArgAsExpr(1), ArgumentIdx)) return; - ParamIdx TypeTagIdx; + uint64_t TypeTagIdx; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 3, AL.getArgAsExpr(2), TypeTagIdx)) return; @@ -4483,9 +4500,8 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, bool IsPointer = AL.getName()->getName() == "pointer_with_type_tag"; if (IsPointer) { // Ensure that buffer has a pointer type. - unsigned ArgumentIdxAST = ArgumentIdx.getASTIndex(); - if (ArgumentIdxAST >= getFunctionOrMethodNumParams(D) || - !getFunctionOrMethodParamType(D, ArgumentIdxAST)->isPointerType()) + if (ArgumentIdx >= getFunctionOrMethodNumParams(D) || + !getFunctionOrMethodParamType(D, ArgumentIdx)->isPointerType()) S.Diag(AL.getLoc(), diag::err_attribute_pointers_only) << AL.getName() << 0; } @@ -4525,18 +4541,19 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, AL.getAttributeSpellingListIndex())); } -static void handleXRayLogArgsAttr(Sema &S, Decl *D, const AttributeList &AL) { - ParamIdx ArgCount; +static void handleXRayLogArgsAttr(Sema &S, Decl *D, + const AttributeList &AL) { + uint64_t ArgCount; if (!checkFunctionOrMethodParameterIndex(S, D, AL, 1, AL.getArgAsExpr(0), ArgCount, - true /* CanIndexImplicitThis */)) + true /* AllowImplicitThis*/)) return; - // 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())); + // 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())); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 108724f2a18..800956dd535 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -176,7 +176,7 @@ static void instantiateDependentAllocAlignAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const AllocAlignAttr *Align, Decl *New) { Expr *Param = IntegerLiteral::Create( - S.getASTContext(), llvm::APInt(64, Align->paramIndex().getSourceIndex()), + S.getASTContext(), llvm::APInt(64, Align->getParamIndex()), S.getASTContext().UnsignedLongLongTy, Align->getLocation()); S.AddAllocAlignAttr(Align->getLocation(), New, Param, Align->getSpellingListIndex()); diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index a3da79e798d..7b644d4dadf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1231,10 +1231,9 @@ MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE, if (Att->getModule() != II_malloc) return nullptr; - ParamIdx *I = Att->args_begin(), *E = Att->args_end(); + OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end(); if (I != E) { - return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()), UndefinedVal(), - State); + return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), State); } return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State); } @@ -1332,9 +1331,9 @@ ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C, bool ReleasedAllocated = false; for (const auto &Arg : Att->args()) { - ProgramStateRef StateI = FreeMemAux( - C, CE, State, Arg.getASTIndex(), - Att->getOwnKind() == OwnershipAttr::Holds, ReleasedAllocated); + ProgramStateRef StateI = FreeMemAux(C, CE, State, Arg, + Att->getOwnKind() == OwnershipAttr::Holds, + ReleasedAllocated); if (StateI) State = StateI; } diff --git a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp index 6f279955907..6d05159e51b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -58,11 +58,10 @@ void NonNullParamChecker::checkPreCall(const CallEvent &Call, AttrNonNull.set(0, NumArgs); break; } - for (const ParamIdx &Idx : NonNull->args()) { - unsigned IdxAST = Idx.getASTIndex(); - if (IdxAST >= NumArgs) + for (unsigned Val : NonNull->args()) { + if (Val >= NumArgs) continue; - AttrNonNull.set(IdxAST); + AttrNonNull.set(Val); } } diff --git a/clang/test/CodeGenCXX/alloc-size.cpp b/clang/test/CodeGenCXX/alloc-size.cpp index 275ffe6dca9..5b8e1c5cf96 100644 --- a/clang/test/CodeGenCXX/alloc-size.cpp +++ b/clang/test/CodeGenCXX/alloc-size.cpp @@ -71,24 +71,6 @@ int testIt() { } } // 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); -} - struct D { ~D(); void *my_malloc(int N) __attribute__((alloc_size(2))); diff --git a/clang/test/Misc/ast-dump-attr.cpp b/clang/test/Misc/ast-dump-attr.cpp index 1e4eb7c3195..9e6f257a920 100644 --- a/clang/test/Misc/ast-dump-attr.cpp +++ b/clang/test/Misc/ast-dump-attr.cpp @@ -68,12 +68,12 @@ __attribute__((pointer_with_type_tag(ident1,1,2))); void TestBool(void *, int)
__attribute__((pointer_with_type_tag(bool1,1,2)));
// CHECK: FunctionDecl{{.*}}TestBool
-// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 1 2 IsPointer
+// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer
void TestUnsigned(void *, int)
__attribute__((pointer_with_type_tag(unsigned1,1,2)));
// CHECK: FunctionDecl{{.*}}TestUnsigned
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 1 2
+// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1
void TestInt(void) __attribute__((constructor(123)));
// CHECK: FunctionDecl{{.*}}TestInt
diff --git a/clang/test/Sema/attr-ownership.cpp b/clang/test/Sema/attr-ownership.cpp deleted file mode 100644 index cde195ff0aa..00000000000 --- a/clang/test/Sema/attr-ownership.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// 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}} -}; diff --git a/clang/test/Sema/attr-print.cpp b/clang/test/Sema/attr-print.cpp index 1828c3b13a6..ab6a00e203a 100644 --- a/clang/test/Sema/attr-print.cpp +++ b/clang/test/Sema/attr-print.cpp @@ -1,67 +1,6 @@ // 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))); -}; diff --git a/clang/test/Sema/error-type-safety.cpp b/clang/test/Sema/error-type-safety.cpp index c5aa48fd1e8..223645de0f7 100644 --- a/clang/test/Sema/error-type-safety.cpp +++ b/clang/test/Sema/error-type-safety.cpp @@ -3,50 +3,21 @@ #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))); - -// Argument index: 1, Type tag index: 2 -void test_bounds_index_ptr(void *, ...) - __attribute__((pointer_with_type_tag(test, 1, 2))); + __attribute__((argument_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))); - -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))); -}; + __attribute__((argument_with_type_tag(test, 3, 1))); 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_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}} + 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}} } diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 263dcae3b3e..5c786f53418 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -302,6 +302,9 @@ 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"; } @@ -745,138 +748,6 @@ 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) { @@ -1376,10 +1247,6 @@ createArgument(const Record &Arg, StringRef Attr, 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); |