https://github.com/bwendling created https://github.com/llvm/llvm-project/pull/75857
There are many issues that popped up with the counted_by feature. The patch has grown too large and approval is blocking Linux testing. Includes reverts of: commit 769bc11f684d ("[Clang] Implement the 'counted_by' attribute (#68750)") commit bc09ec696209 ("[CodeGen] Revamp counted_by calculations (#70606)") commit 1a09cfb2f35d ("[Clang] counted_by attr can apply only to C99 flexible array members (#72347)") commit a76adfb992c6 ("[NFC][Clang] Refactor code to calculate flexible array member size (#72790)") commit d8447c78ab16 ("[Clang] Correct handling of negative and out-of-bounds indices (#71877)") Partial commit b31cd07de5b7 ("[Clang] Regenerate test checks (NFC)") >From 5e2be944ff657b55db55423717cc37f646ddc8e9 Mon Sep 17 00:00:00 2001 From: Bill Wendling <mo...@google.com> Date: Mon, 18 Dec 2023 12:46:45 -0800 Subject: [PATCH] Revert counted_by attribute feature There are many issues that popped up with the counted_by feature. The patch has grown too large and approval is blocking Linux testing. Includes reverts of: commit 769bc11f684d ("[Clang] Implement the 'counted_by' attribute (#68750)") commit bc09ec696209 ("[CodeGen] Revamp counted_by calculations (#70606)") commit 1a09cfb2f35d ("[Clang] counted_by attr can apply only to C99 flexible array members (#72347)") commit a76adfb992c6 ("[NFC][Clang] Refactor code to calculate flexible array member size (#72790)") commit d8447c78ab16 ("[Clang] Correct handling of negative and out-of-bounds indices (#71877)") Partial commit b31cd07de5b7 ("[Clang] Regenerate test checks (NFC)") --- clang/docs/ReleaseNotes.rst | 5 - clang/include/clang/AST/Decl.h | 24 - clang/include/clang/AST/DeclBase.h | 10 - clang/include/clang/Basic/Attr.td | 18 - clang/include/clang/Basic/AttrDocs.td | 66 -- .../clang/Basic/DiagnosticSemaKinds.td | 11 - clang/include/clang/Sema/Sema.h | 3 - clang/include/clang/Sema/TypoCorrection.h | 12 +- clang/lib/AST/ASTImporter.cpp | 13 - clang/lib/AST/DeclBase.cpp | 74 +- clang/lib/AST/Expr.cpp | 83 +- clang/lib/CodeGen/CGBuiltin.cpp | 167 ---- clang/lib/CodeGen/CGExpr.cpp | 129 +-- clang/lib/CodeGen/CodeGenFunction.h | 16 - clang/lib/Sema/SemaDecl.cpp | 14 - clang/lib/Sema/SemaDeclAttr.cpp | 90 --- clang/lib/Sema/SemaExpr.cpp | 16 +- clang/test/CodeGen/attr-counted-by.c | 742 ------------------ clang/test/CodeGen/bounds-checking.c | 10 +- ...a-attribute-supported-attributes-list.test | 1 - clang/test/Sema/attr-counted-by.c | 55 -- 21 files changed, 89 insertions(+), 1470 deletions(-) delete mode 100644 clang/test/CodeGen/attr-counted-by.c delete mode 100644 clang/test/Sema/attr-counted-by.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2e32f8b36d23de..edb97347f07716 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -199,11 +199,6 @@ C Language Changes - ``structs``, ``unions``, and ``arrays`` that are const may now be used as constant expressions. This change is more consistent with the behavior of GCC. -- Clang now supports the C-only attribute ``counted_by``. When applied to a - struct's flexible array member, it points to the struct field that holds the - number of elements in the flexible array member. This information can improve - the results of the array bound sanitizer and the - ``__builtin_dynamic_object_size`` builtin. - Enums will now be represented in TBAA metadata using their actual underlying integer type. Previously they were treated as chars, which meant they could alias with all other types. diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index cd0878d7082514..f9bf9cc5de7cb4 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4332,30 +4332,6 @@ class RecordDecl : public TagDecl { return field_begin() == field_end(); } - FieldDecl *getLastField() { - FieldDecl *FD = nullptr; - for (FieldDecl *Field : fields()) - FD = Field; - return FD; - } - const FieldDecl *getLastField() const { - return const_cast<RecordDecl *>(this)->getLastField(); - } - - template <typename Functor> - const FieldDecl *findFieldIf(Functor &Pred) const { - for (const Decl *D : decls()) { - if (const auto *FD = dyn_cast<FieldDecl>(D); FD && Pred(FD)) - return FD; - - if (const auto *RD = dyn_cast<RecordDecl>(D)) - if (const FieldDecl *FD = RD->findFieldIf(Pred)) - return FD; - } - - return nullptr; - } - /// Note that the definition of this type is now complete. virtual void completeDefinition(); diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 5b1038582bc674..10dcbdb262d84e 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -19,7 +19,6 @@ #include "clang/AST/SelectorLocationsKind.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" @@ -489,15 +488,6 @@ class alignas(8) Decl { // Return true if this is a FileContext Decl. bool isFileContextDecl() const; - /// Whether it resembles a flexible array member. This is a static member - /// because we want to be able to call it with a nullptr. That allows us to - /// perform non-Decl specific checks based on the object's type and strict - /// flex array level. - static bool isFlexibleArrayMemberLike( - ASTContext &Context, const Decl *D, QualType Ty, - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, - bool IgnoreTemplateOrMacroSubstitution); - ASTContext &getASTContext() const LLVM_READONLY; /// Helper to get the language options from the ASTContext. diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 2b57058d3f1c75..db17211747b17d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4331,24 +4331,6 @@ def AvailableOnlyInDefaultEvalMethod : InheritableAttr { let Documentation = [Undocumented]; } -def CountedBy : InheritableAttr { - let Spellings = [Clang<"counted_by">]; - let Subjects = SubjectList<[Field]>; - let Args = [IdentifierArgument<"CountedByField">]; - let Documentation = [CountedByDocs]; - let LangOpts = [COnly]; - // FIXME: This is ugly. Let using a DeclArgument would be nice, but a Decl - // isn't yet available due to the fact that we're still parsing the - // structure. Maybe that code could be changed sometime in the future. - code AdditionalMembers = [{ - private: - SourceRange CountedByFieldLoc; - public: - SourceRange getCountedByFieldLoc() const { return CountedByFieldLoc; } - void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; } - }]; -} - def PreferredType: InheritableAttr { let Spellings = [Clang<"preferred_type">]; let Subjects = SubjectList<[BitField], ErrorDiag>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 90041fa8dbb30b..98a7ecc7fd7df3 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7500,72 +7500,6 @@ attribute, they default to the value ``65535``. }]; } -def CountedByDocs : Documentation { - let Category = DocCatField; - let Content = [{ -Clang supports the ``counted_by`` attribute on the flexible array member of a -structure in C. The argument for the attribute is the name of a field member in -the same structure holding the count of elements in the flexible array. This -information can be used to improve the results of the array bound sanitizer and -the ``__builtin_dynamic_object_size`` builtin. - -For example, the following code: - -.. code-block:: c - - struct bar; - - struct foo { - size_t count; - char other; - struct bar *array[] __attribute__((counted_by(count))); - }; - -specifies that the flexible array member ``array`` has the number of elements -allocated for it stored in ``count``. This establishes a relationship between -``array`` and ``count``. Specifically, ``p->array`` must have at least -``p->count`` number of elements available. It's the user's responsibility to -ensure that this relationship is maintained through changes to the structure. - -In the following example, the allocated array erroneously has fewer elements -than what's specified by ``p->count``. This would result in an out-of-bounds -access not being detected. - -.. code-block:: c - - #define SIZE_INCR 42 - - struct foo *p; - - void foo_alloc(size_t count) { - p = malloc(MAX(sizeof(struct foo), - offsetof(struct foo, array[0]) + count * sizeof(struct bar *))); - p->count = count + SIZE_INCR; - } - -The next example updates ``p->count``, breaking the relationship requirement -that ``p->array`` must have at least ``p->count`` number of elements available: - -.. code-block:: c - - #define SIZE_INCR 42 - - struct foo *p; - - void foo_alloc(size_t count) { - p = malloc(MAX(sizeof(struct foo), - offsetof(struct foo, array[0]) + count * sizeof(struct bar *))); - p->count = count; - } - - void use_foo(int index) { - p->count += SIZE_INCR + 1; /* 'count' is now larger than the number of elements of 'array'. */ - p->array[index] = 0; /* the sanitizer can't properly check if this is an out-of-bounds access. */ - } - - }]; -} - def CoroOnlyDestroyWhenCompleteDocs : Documentation { let Category = DocCatDecl; let Content = [{ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6e6f56ff75e5f9..c100041ca400f2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6429,17 +6429,6 @@ def warn_superclass_variable_sized_type_not_at_end : Warning< "field %0 can overwrite instance variable %1 with variable sized type %2" " in superclass %3">, InGroup<ObjCFlexibleArray>; -def err_counted_by_attr_not_on_flexible_array_member : Error< - "'counted_by' only applies to C99 flexible array members">; -def err_counted_by_attr_refers_to_flexible_array : Error< - "'counted_by' cannot refer to the flexible array %0">; -def err_counted_by_must_be_in_structure : Error< - "field %0 in 'counted_by' not inside structure">; -def err_flexible_array_counted_by_attr_field_not_integer : Error< - "field %0 in 'counted_by' must be a non-boolean integer type">; -def note_flexible_array_counted_by_attr_field : Note< - "field %0 declared here">; - let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a4f8fc1845b1ce..9887cc4ba4658d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4799,8 +4799,6 @@ class Sema final { bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, const AttributeCommonInfo &A); - bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); - /// Adjust the calling convention of a method to be the ABI default if it /// wasn't specified explicitly. This handles method types formed from /// function type typedefs and typename template arguments. @@ -5644,7 +5642,6 @@ class Sema final { CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, ArrayRef<Expr *> Args = std::nullopt, - DeclContext *LookupCtx = nullptr, TypoExpr **Out = nullptr); DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S, diff --git a/clang/include/clang/Sema/TypoCorrection.h b/clang/include/clang/Sema/TypoCorrection.h index 09de164297e7ba..e0f8d152dbe554 100644 --- a/clang/include/clang/Sema/TypoCorrection.h +++ b/clang/include/clang/Sema/TypoCorrection.h @@ -282,7 +282,7 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr, + explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, NestedNameSpecifier *TypoNNS = nullptr) : Typo(Typo), TypoNNS(TypoNNS) {} @@ -319,7 +319,7 @@ class CorrectionCandidateCallback { /// this method. virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0; - void setTypoName(const IdentifierInfo *II) { Typo = II; } + void setTypoName(IdentifierInfo *II) { Typo = II; } void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } // Flags for context-dependent keywords. WantFunctionLikeCasts is only @@ -345,13 +345,13 @@ class CorrectionCandidateCallback { candidate.getCorrectionSpecifier() == TypoNNS; } - const IdentifierInfo *Typo; + IdentifierInfo *Typo; NestedNameSpecifier *TypoNNS; }; class DefaultFilterCCC final : public CorrectionCandidateCallback { public: - explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr, + explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr, NestedNameSpecifier *TypoNNS = nullptr) : CorrectionCandidateCallback(Typo, TypoNNS) {} @@ -365,10 +365,6 @@ class DefaultFilterCCC final : public CorrectionCandidateCallback { template <class C> class DeclFilterCCC final : public CorrectionCandidateCallback { public: - explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr, - NestedNameSpecifier *TypoNNS = nullptr) - : CorrectionCandidateCallback(Typo, TypoNNS) {} - bool ValidateCandidate(const TypoCorrection &candidate) override { return candidate.getCorrectionDeclAs<C>(); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index f1f335118f37a4..49d0dd218d6830 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -9003,10 +9003,6 @@ class AttrImporter { public: AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {} - // Useful for accessing the imported attribute. - template <typename T> T *castAttrAs() { return cast<T>(ToAttr); } - template <typename T> const T *castAttrAs() const { return cast<T>(ToAttr); } - // Create an "importer" for an attribute parameter. // Result of the 'value()' of that object is to be passed to the function // 'importAttr', in the order that is expected by the attribute class. @@ -9214,15 +9210,6 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) { From->args_size()); break; } - case attr::CountedBy: { - AI.cloneAttr(FromAttr); - const auto *CBA = cast<CountedByAttr>(FromAttr); - Expected<SourceRange> SR = Import(CBA->getCountedByFieldLoc()).get(); - if (!SR) - return SR.takeError(); - AI.castAttrAs<CountedByAttr>()->setCountedByFieldLoc(SR.get()); - break; - } default: { // The default branch works for attributes that have no arguments to import. diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index e4d7169752bc85..5e03f0223d311c 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -29,6 +29,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/PartialDiagnostic.h" @@ -410,79 +411,6 @@ bool Decl::isFileContextDecl() const { return DC && DC->isFileContext(); } -bool Decl::isFlexibleArrayMemberLike( - ASTContext &Ctx, const Decl *D, QualType Ty, - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, - bool IgnoreTemplateOrMacroSubstitution) { - // For compatibility with existing code, we treat arrays of length 0 or - // 1 as flexible array members. - const auto *CAT = Ctx.getAsConstantArrayType(Ty); - if (CAT) { - using FAMKind = LangOptions::StrictFlexArraysLevelKind; - - llvm::APInt Size = CAT->getSize(); - if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) - return false; - - // GCC extension, only allowed to represent a FAM. - if (Size.isZero()) - return true; - - if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) - return false; - - if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) - return false; - } else if (!Ctx.getAsIncompleteArrayType(Ty)) { - return false; - } - - if (const auto *OID = dyn_cast_if_present<ObjCIvarDecl>(D)) - return OID->getNextIvar() == nullptr; - - const auto *FD = dyn_cast_if_present<FieldDecl>(D); - if (!FD) - return false; - - if (CAT) { - // GCC treats an array memeber of a union as an FAM if the size is one or - // zero. - llvm::APInt Size = CAT->getSize(); - if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) - return true; - } - - // Don't consider sizes resulting from macro expansions or template argument - // substitution to form C89 tail-padded arrays. - if (IgnoreTemplateOrMacroSubstitution) { - TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); - while (TInfo) { - TypeLoc TL = TInfo->getTypeLoc(); - - // Look through typedefs. - if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) { - const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); - TInfo = TDL->getTypeSourceInfo(); - continue; - } - - if (auto CTL = TL.getAs<ConstantArrayTypeLoc>()) { - if (const Expr *SizeExpr = - dyn_cast_if_present<IntegerLiteral>(CTL.getSizeExpr()); - !SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; - } - - break; - } - } - - // Test that the field is the last in the structure. - RecordDecl::field_iterator FI( - DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); - return ++FI == FD->getParent()->field_end(); -} - TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (auto *TUD = dyn_cast<TranslationUnitDecl>(this)) return TUD; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index b125fc676da841..a90f92d07f86d2 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -205,22 +205,85 @@ bool Expr::isKnownToHaveBooleanValue(bool Semantic) const { } bool Expr::isFlexibleArrayMemberLike( - ASTContext &Ctx, + ASTContext &Context, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution) const { + + // For compatibility with existing code, we treat arrays of length 0 or + // 1 as flexible array members. + const auto *CAT = Context.getAsConstantArrayType(getType()); + if (CAT) { + llvm::APInt Size = CAT->getSize(); + + using FAMKind = LangOptions::StrictFlexArraysLevelKind; + + if (StrictFlexArraysLevel == FAMKind::IncompleteOnly) + return false; + + // GCC extension, only allowed to represent a FAM. + if (Size == 0) + return true; + + if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete && Size.uge(1)) + return false; + + if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete && Size.uge(2)) + return false; + } else if (!Context.getAsIncompleteArrayType(getType())) + return false; + const Expr *E = IgnoreParens(); - const Decl *D = nullptr; - if (const auto *ME = dyn_cast<MemberExpr>(E)) - D = ME->getMemberDecl(); - else if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) - D = DRE->getDecl(); + const NamedDecl *ND = nullptr; + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) + ND = DRE->getDecl(); + else if (const auto *ME = dyn_cast<MemberExpr>(E)) + ND = ME->getMemberDecl(); else if (const auto *IRE = dyn_cast<ObjCIvarRefExpr>(E)) - D = IRE->getDecl(); + return IRE->getDecl()->getNextIvar() == nullptr; + + if (!ND) + return false; - return Decl::isFlexibleArrayMemberLike(Ctx, D, E->getType(), - StrictFlexArraysLevel, - IgnoreTemplateOrMacroSubstitution); + // A flexible array member must be the last member in the class. + // FIXME: If the base type of the member expr is not FD->getParent(), + // this should not be treated as a flexible array member access. + if (const auto *FD = dyn_cast<FieldDecl>(ND)) { + // GCC treats an array memeber of a union as an FAM if the size is one or + // zero. + if (CAT) { + llvm::APInt Size = CAT->getSize(); + if (FD->getParent()->isUnion() && (Size.isZero() || Size.isOne())) + return true; + } + + // Don't consider sizes resulting from macro expansions or template argument + // substitution to form C89 tail-padded arrays. + if (IgnoreTemplateOrMacroSubstitution) { + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + while (TInfo) { + TypeLoc TL = TInfo->getTypeLoc(); + // Look through typedefs. + if (TypedefTypeLoc TTL = TL.getAsAdjusted<TypedefTypeLoc>()) { + const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); + TInfo = TDL->getTypeSourceInfo(); + continue; + } + if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) { + const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } + break; + } + } + + RecordDecl::field_iterator FI( + DeclContext::decl_iterator(const_cast<FieldDecl *>(FD))); + return ++FI == FD->getParent()->field_end(); + } + + return false; } const ValueDecl * diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4eb1686f095062..a29304c81928cc 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -25,7 +25,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/OSLog.h" -#include "clang/AST/OperationKinds.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" @@ -819,165 +818,6 @@ CodeGenFunction::evaluateOrEmitBuiltinObjectSize(const Expr *E, unsigned Type, return ConstantInt::get(ResType, ObjectSize, /*isSigned=*/true); } -llvm::Value * -CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType) { - // The code generated here calculates the size of a struct with a flexible - // array member that uses the counted_by attribute. There are two instances - // we handle: - // - // struct s { - // unsigned long flags; - // int count; - // int array[] __attribute__((counted_by(count))); - // } - // - // 1) bdos of the flexible array itself: - // - // __builtin_dynamic_object_size(p->array, 1) == - // p->count * sizeof(*p->array) - // - // 2) bdos of a pointer into the flexible array: - // - // __builtin_dynamic_object_size(&p->array[42], 1) == - // (p->count - 42) * sizeof(*p->array) - // - // 2) bdos of the whole struct, including the flexible array: - // - // __builtin_dynamic_object_size(p, 1) == - // max(sizeof(struct s), - // offsetof(struct s, array) + p->count * sizeof(*p->array)) - // - ASTContext &Ctx = getContext(); - const Expr *Base = E->IgnoreParenImpCasts(); - const Expr *Idx = nullptr; - - if (const auto *UO = dyn_cast<UnaryOperator>(Base); - UO && UO->getOpcode() == UO_AddrOf) { - Expr *SubExpr = UO->getSubExpr()->IgnoreParenImpCasts(); - if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(SubExpr)) { - Base = ASE->getBase()->IgnoreParenImpCasts(); - Idx = ASE->getIdx()->IgnoreParenImpCasts(); - - if (const auto *IL = dyn_cast<IntegerLiteral>(Idx)) { - int64_t Val = IL->getValue().getSExtValue(); - if (Val < 0) - // __bdos returns 0 for negative indexes into an array in a struct. - return getDefaultBuiltinObjectSizeResult(Type, ResType); - - if (Val == 0) - // The index is 0, so we don't need to take it into account. - Idx = nullptr; - } - } else { - // Potential pointer to another element in the struct. - Base = SubExpr; - } - } - - // Get the flexible array member Decl. - const ValueDecl *FAMDecl = nullptr; - if (const auto *ME = dyn_cast<MemberExpr>(Base)) { - // Check if \p Base is referencing the FAM itself. - if (const ValueDecl *MD = ME->getMemberDecl()) { - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - if (!Decl::isFlexibleArrayMemberLike( - Ctx, MD, MD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - return nullptr; - - FAMDecl = MD; - } - } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) { - // Check if we're pointing to the whole struct. - QualType Ty = DRE->getDecl()->getType(); - if (Ty->isPointerType()) - Ty = Ty->getPointeeType(); - - if (const auto *RD = Ty->getAsRecordDecl()) - // Don't use the outer lexical record because the FAM might be in a - // different RecordDecl. - FAMDecl = FindFlexibleArrayMemberField(Ctx, RD); - } - - if (!FAMDecl || !FAMDecl->hasAttr<CountedByAttr>()) - // No flexible array member found or it doesn't have the "counted_by" - // attribute. - return nullptr; - - const ValueDecl *CountedByFD = FindCountedByField(Base); - if (!CountedByFD) - // Can't find the field referenced by the "counted_by" attribute. - return nullptr; - - // Build a load of the counted_by field. - bool IsSigned = CountedByFD->getType()->isSignedIntegerType(); - const Expr *CountedByExpr = BuildCountedByFieldExpr(Base, CountedByFD); - Value *CountedByInst = EmitAnyExprToTemp(CountedByExpr).getScalarVal(); - llvm::Type *CountedByTy = CountedByInst->getType(); - - // Build a load of the index and subtract it from the count. - Value *IdxInst = nullptr; - if (Idx) { - bool IdxSigned = Idx->getType()->isSignedIntegerType(); - IdxInst = EmitAnyExprToTemp(Idx).getScalarVal(); - IdxInst = IdxSigned ? Builder.CreateSExtOrTrunc(IdxInst, CountedByTy) - : Builder.CreateZExtOrTrunc(IdxInst, CountedByTy); - - // We go ahead with the calculation here. If the index turns out to be - // negative, we'll catch it at the end. - CountedByInst = - Builder.CreateSub(CountedByInst, IdxInst, "", !IsSigned, IsSigned); - } - - // Calculate how large the flexible array member is in bytes. - const ArrayType *ArrayTy = Ctx.getAsArrayType(FAMDecl->getType()); - CharUnits Size = Ctx.getTypeSizeInChars(ArrayTy->getElementType()); - llvm::Constant *ElemSize = - llvm::ConstantInt::get(CountedByTy, Size.getQuantity(), IsSigned); - Value *FAMSize = - Builder.CreateMul(CountedByInst, ElemSize, "", !IsSigned, IsSigned); - FAMSize = IsSigned ? Builder.CreateSExtOrTrunc(FAMSize, ResType) - : Builder.CreateZExtOrTrunc(FAMSize, ResType); - Value *Res = FAMSize; - - if (isa<DeclRefExpr>(Base)) { - // The whole struct is specificed in the __bdos. - const RecordDecl *OuterRD = - CountedByFD->getDeclContext()->getOuterLexicalRecordContext(); - const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(OuterRD); - - // Get the offset of the FAM. - CharUnits Offset = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FAMDecl)); - llvm::Constant *FAMOffset = - ConstantInt::get(ResType, Offset.getQuantity(), IsSigned); - Value *OffsetAndFAMSize = - Builder.CreateAdd(FAMOffset, Res, "", !IsSigned, IsSigned); - - // Get the full size of the struct. - llvm::Constant *SizeofStruct = - ConstantInt::get(ResType, Layout.getSize().getQuantity(), IsSigned); - - // max(sizeof(struct s), - // offsetof(struct s, array) + p->count * sizeof(*p->array)) - Res = IsSigned - ? Builder.CreateBinaryIntrinsic(llvm::Intrinsic::smax, - OffsetAndFAMSize, SizeofStruct) - : Builder.CreateBinaryIntrinsic(llvm::Intrinsic::umax, - OffsetAndFAMSize, SizeofStruct); - } - - // A negative \p IdxInst or \p CountedByInst means that the index lands - // outside of the flexible array member. If that's the case, we want to - // return 0. - Value *Cmp = Builder.CreateIsNotNeg(CountedByInst); - if (IdxInst) - Cmp = Builder.CreateAnd(Builder.CreateIsNotNeg(IdxInst), Cmp); - - return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); -} - /// Returns a Value corresponding to the size of the given expression. /// This Value may be either of the following: /// - A llvm::Argument (if E is a param with the pass_object_size attribute on @@ -1010,13 +850,6 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, } } - if (IsDynamic) { - // Emit special code for a flexible array member with the "counted_by" - // attribute. - if (Value *V = emitFlexibleArrayMemberSize(E, Type, ResType)) - return V; - } - // LLVM can't handle Type=3 appropriately, and __builtin_object_size shouldn't // evaluate E for side-effects. In either case, we shouldn't lower to // @llvm.objectsize. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ed9aaa28c25733..3f277725d9e7fc 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -30,7 +30,6 @@ #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" @@ -926,27 +925,16 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, if (CE->getCastKind() == CK_ArrayToPointerDecay && !CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(), StrictFlexArraysLevel)) { - CodeGenFunction::SanitizerScope SanScope(&CGF); - IndexedType = CE->getSubExpr()->getType(); const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe(); if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) return CGF.Builder.getInt(CAT->getSize()); - - if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) + else if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) return CGF.getVLASize(VAT).NumElts; // Ignore pass_object_size here. It's not applicable on decayed pointers. } - - if (const ValueDecl *VD = CGF.FindCountedByField(Base)) { - IndexedType = Base->getType(); - const Expr *E = CGF.BuildCountedByFieldExpr(Base, VD); - return CGF.EmitAnyExprToTemp(E).getScalarVal(); - } } - CodeGenFunction::SanitizerScope SanScope(&CGF); - QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0}; if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) { IndexedType = Base->getType(); @@ -956,122 +944,13 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF, return nullptr; } -const Expr * -CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base, - const ValueDecl *CountedByVD) { - // Find the outer struct expr (i.e. p in p->a.b.c.d). - Expr *CountedByExpr = const_cast<Expr *>(Base)->IgnoreParenImpCasts(); - - // Work our way up the expression until we reach the DeclRefExpr. - while (!isa<DeclRefExpr>(CountedByExpr)) - if (const auto *ME = dyn_cast<MemberExpr>(CountedByExpr)) - CountedByExpr = ME->getBase()->IgnoreParenImpCasts(); - - // Add back an implicit cast to create the required pr-value. - CountedByExpr = ImplicitCastExpr::Create( - getContext(), CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr, - nullptr, VK_PRValue, FPOptionsOverride()); - - if (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountedByVD)) { - // The counted_by field is inside an anonymous struct / union. The - // IndirectFieldDecl has the correct order of FieldDecls to build this - // easily. (Yay!) - for (NamedDecl *ND : IFD->chain()) { - auto *VD = cast<ValueDecl>(ND); - CountedByExpr = - MemberExpr::CreateImplicit(getContext(), CountedByExpr, - CountedByExpr->getType()->isPointerType(), - VD, VD->getType(), VK_LValue, OK_Ordinary); - } - } else { - CountedByExpr = MemberExpr::CreateImplicit( - getContext(), const_cast<Expr *>(CountedByExpr), - CountedByExpr->getType()->isPointerType(), - const_cast<ValueDecl *>(CountedByVD), CountedByVD->getType(), VK_LValue, - OK_Ordinary); - } - - return CountedByExpr; -} - -const ValueDecl * -CodeGenFunction::FindFlexibleArrayMemberField(ASTContext &Ctx, - const RecordDecl *RD) { - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - - for (const Decl *D : RD->decls()) { - if (const auto *VD = dyn_cast<ValueDecl>(D); - VD && Decl::isFlexibleArrayMemberLike( - Ctx, VD, VD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - return VD; - - if (const auto *Record = dyn_cast<RecordDecl>(D)) - if (const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, Record)) - return VD; - } - - return nullptr; -} - -const ValueDecl *CodeGenFunction::FindCountedByField(const Expr *Base) { - ASTContext &Ctx = getContext(); - const RecordDecl *OuterRD = nullptr; - const FieldDecl *FD = nullptr; - - Base = Base->IgnoreParenImpCasts(); - - // Get the outer-most lexical RecordDecl. - if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) { - QualType Ty = DRE->getDecl()->getType(); - if (Ty->isPointerType()) - Ty = Ty->getPointeeType(); - - if (const auto *RD = Ty->getAsRecordDecl()) - OuterRD = RD->getOuterLexicalRecordContext(); - } else if (const auto *ME = dyn_cast<MemberExpr>(Base)) { - if (const ValueDecl *MD = ME->getMemberDecl()) { - OuterRD = MD->getDeclContext()->getOuterLexicalRecordContext(); - - const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - if (Decl::isFlexibleArrayMemberLike( - Ctx, MD, MD->getType(), StrictFlexArraysLevel, - /*IgnoreTemplateOrMacroSubstitution=*/true)) - // Base is referencing the FAM itself. - FD = dyn_cast<FieldDecl>(MD); - } - } - - if (!OuterRD) - return nullptr; - - if (!FD) { - const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, OuterRD); - FD = dyn_cast_if_present<FieldDecl>(VD); - if (!FD) - return nullptr; - } - - const auto *CBA = FD->getAttr<CountedByAttr>(); - if (!CBA) - return nullptr; - - DeclarationName DName(CBA->getCountedByField()); - DeclContext::lookup_result Lookup = OuterRD->lookup(DName); - - if (Lookup.empty()) - return nullptr; - - return dyn_cast<ValueDecl>(Lookup.front()); -} - void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed) { assert(SanOpts.has(SanitizerKind::ArrayBounds) && "should not be called unless adding bounds checks"); + SanitizerScope SanScope(this); + const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = getLangOpts().getStrictFlexArraysLevel(); @@ -1081,8 +960,6 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, if (!Bound) return; - SanitizerScope SanScope(this); - bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType(); llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned); llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 618e78809db408..751d8110b13dfd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3022,19 +3022,6 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitBoundsCheck(const Expr *E, const Expr *Base, llvm::Value *Index, QualType IndexType, bool Accessed); - // Find a struct's flexible array member. It may be embedded inside multiple - // sub-structs, but must still be the last field. - const ValueDecl *FindFlexibleArrayMemberField(ASTContext &Ctx, - const RecordDecl *RD); - - /// Find the FieldDecl specified in a FAM's "counted_by" attribute. Returns - /// \p nullptr if either the attribute or the field doesn't exist. - const ValueDecl *FindCountedByField(const Expr *Base); - - /// Build an expression accessing the "counted_by" field. - const Expr *BuildCountedByFieldExpr(const Expr *Base, - const ValueDecl *CountedByVD); - llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, @@ -4830,9 +4817,6 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmittedE, bool IsDynamic); - llvm::Value *emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, - llvm::IntegerType *ResType); - void emitZeroOrPatternForAutoVarInit(QualType type, const VarDecl &D, Address Loc); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index be6a136ef37bc4..edf44bbc52119b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19518,20 +19518,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, CDecl->setIvarRBraceLoc(RBrac); } } - - // Check the "counted_by" attribute to ensure that the count field exists in - // the struct. Make sure we're performing this check on the outer-most - // record. This is a C-only feature. - if (!getLangOpts().CPlusPlus && Record && - !isa<RecordDecl>(Record->getParent())) { - auto Pred = [](const Decl *D) { - if (const auto *FD = dyn_cast_if_present<FieldDecl>(D)) - return FD->hasAttr<CountedByAttr>(); - return false; - }; - if (const FieldDecl *FD = Record->findFieldIf(Pred)) - CheckCountedByAttr(S, FD); - } } /// Determine whether the given integral value is representable within diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5b29b05dee54b3..af8b90ecfed973 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8445,92 +8445,6 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL)); } -static void handleCountedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL << AANT_ArgumentIdentifier; - return; - } - - IdentifierLoc *IL = AL.getArgAsIdent(0); - CountedByAttr *CBA = - ::new (S.Context) CountedByAttr(S.Context, AL, IL->Ident); - CBA->setCountedByFieldLoc(IL->Loc); - D->addAttr(CBA); -} - -bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { - const auto *CBA = FD->getAttr<CountedByAttr>(); - const IdentifierInfo *FieldName = CBA->getCountedByField(); - DeclarationNameInfo NameInfo(FieldName, - CBA->getCountedByFieldLoc().getBegin()); - - LookupResult MemResult(*this, NameInfo, Sema::LookupMemberName); - LookupName(MemResult, S); - - if (MemResult.empty()) { - // The "counted_by" field needs to exist within the struct. - LookupResult OrdResult(*this, NameInfo, Sema::LookupOrdinaryName); - LookupName(OrdResult, S); - - if (!OrdResult.empty()) { - SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_must_be_in_structure) - << FieldName << SR; - - if (auto *ND = OrdResult.getAsSingle<NamedDecl>()) { - SR = ND->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << ND << SR; - } - return true; - } - - CXXScopeSpec SS; - DeclFilterCCC<FieldDecl> Filter(FieldName); - return DiagnoseEmptyLookup(S, SS, MemResult, Filter, nullptr, std::nullopt, - const_cast<DeclContext *>(FD->getDeclContext())); - } - - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; - - if (!Decl::isFlexibleArrayMemberLike(Context, FD, FD->getType(), - StrictFlexArraysLevel, true)) { - // The "counted_by" attribute must be on a flexible array member. - SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_attr_not_on_flexible_array_member) - << SR; - return true; - } - - if (const FieldDecl *Field = MemResult.getAsSingle<FieldDecl>()) { - if (Field->hasAttr<CountedByAttr>()) { - // The "counted_by" field can't point to the flexible array member. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), diag::err_counted_by_attr_refers_to_flexible_array) - << CBA->getCountedByField() << SR; - return true; - } - - if (!Field->getType()->isIntegerType() || - Field->getType()->isBooleanType()) { - // The "counted_by" field must have an integer type. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), - diag::err_flexible_array_counted_by_attr_field_not_integer) - << CBA->getCountedByField() << SR; - - SR = Field->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << Field << SR; - return true; - } - } - - return false; -} - static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef KindStr; @@ -9488,10 +9402,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleAvailableOnlyInDefaultEvalMethod(S, D, AL); break; - case ParsedAttr::AT_CountedBy: - handleCountedByAttr(S, D, AL); - break; - // Microsoft attributes: case ParsedAttr::AT_LayoutVersion: handleLayoutVersion(S, D, AL); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c7185d56cc9973..960f513d1111b2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2469,8 +2469,7 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, - ArrayRef<Expr *> Args, DeclContext *LookupCtx, - TypoExpr **Out) { + ArrayRef<Expr *> Args, TypoExpr **Out) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -2486,8 +2485,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - DeclContext *DC = - LookupCtx ? LookupCtx : (SS.isEmpty() ? CurContext : nullptr); + DeclContext *DC = SS.isEmpty() ? CurContext : nullptr; while (DC) { if (isa<CXXRecordDecl>(DC)) { LookupQualifiedName(R, DC); @@ -2530,12 +2528,12 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args, diagnostic, diagnostic_suggest); }, - nullptr, CTK_ErrorRecovery, LookupCtx); + nullptr, CTK_ErrorRecovery); if (*Out) return true; - } else if (S && (Corrected = - CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, - &SS, CCC, CTK_ErrorRecovery, LookupCtx))) { + } else if (S && + (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), + S, &SS, CCC, CTK_ErrorRecovery))) { std::string CorrectedStr(Corrected.getAsString(getLangOpts())); bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr; @@ -2825,7 +2823,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // a template name, but we happen to have always already looked up the name // before we get here if it must be a template name. if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator, nullptr, - std::nullopt, nullptr, &TE)) { + std::nullopt, &TE)) { if (TE && KeywordReplacement) { auto &State = getTypoExprState(TE); auto BestTC = State.Consumer->getNextCorrection(); diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c deleted file mode 100644 index 97226a24f5d62f..00000000000000 --- a/clang/test/CodeGen/attr-counted-by.c +++ /dev/null @@ -1,742 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 3 -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITH-ATTR %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -DCOUNTED_BY -O2 -Wall -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITH-ATTR %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fsanitize=array-bounds,object-size,local-bounds -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=SANITIZE-WITHOUT-ATTR %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -Wall -fstrict-flex-arrays=3 -emit-llvm -o - %s | FileCheck --check-prefix=NO-SANITIZE-WITHOUT-ATTR %s - -#if !__has_attribute(counted_by) -#error "has attribute broken" -#endif - -#ifdef COUNTED_BY -#define __counted_by(member) __attribute__((__counted_by__(member))) -#else -#define __counted_by(member) -#endif - -#define DECLARE_FLEX_ARRAY(TYPE, NAME) \ - struct { \ - struct { } __empty_ ## NAME; \ - TYPE NAME[]; \ - } - -#define DECLARE_BOUNDED_FLEX_ARRAY(COUNT_TYPE, COUNT, TYPE, NAME) \ - struct { \ - COUNT_TYPE COUNT; \ - TYPE NAME[] __counted_by(COUNT); \ - } - -#define DECLARE_FLEX_ARRAY_COUNTED_BY(TYPE, NAME, COUNTED_BY) \ - struct { \ - struct { } __empty_ ## NAME; \ - TYPE NAME[] __counted_by(COUNTED_BY); \ - } - -typedef long unsigned int size_t; - -struct annotated { - unsigned long flags; - int count; - int array[] __counted_by(count); -}; - -struct union_of_fams { - unsigned long flags; - union { - /* count member type intentionally mismatched to induce padding */ - DECLARE_BOUNDED_FLEX_ARRAY(int, count_bytes, unsigned char, bytes); - DECLARE_BOUNDED_FLEX_ARRAY(unsigned char, count_ints, unsigned char, ints); - DECLARE_FLEX_ARRAY(unsigned char, unsafe); - }; -}; - -struct anon_struct { - unsigned long flags; - size_t count; - DECLARE_FLEX_ARRAY_COUNTED_BY(int, array, count); -}; - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test1( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7:![0-9]+]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB2:[0-9]+]], i64 [[TMP4]]) #[[ATTR4:[0-9]+]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont7: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test1( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test1( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test1( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[VAL:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 [[VAL]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2:![0-9]+]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test1(struct annotated *p, int index, int val) { - p->array[index] = val; -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB4:[0-9]+]], i64 [[INDEX]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont12: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i32 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP3]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test2( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i32 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP1]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test2( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test2( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test2(struct annotated *p, size_t index) { - p->array[index] = __builtin_dynamic_object_size(p->array, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP1]], [[INDEX]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB5:[0-9]+]], i64 [[INDEX]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont12: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = shl nsw i32 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP3]], i32 4) -// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = add nuw i32 [[TMP4]], 12 -// SANITIZE-WITH-ATTR-NEXT: [[NARROW15:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[NARROW]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW15]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test3( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i32 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 4) -// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = add nuw i32 [[TMP2]], 12 -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP0]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW2:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[NARROW]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[NARROW2]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test3( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test3( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i64 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[INDEX]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test3(struct annotated *p, size_t index) { - // This test differs from 'test2' by checking bdos on the whole array and not - // just the FAM. - p->array[index] = __builtin_dynamic_object_size(p, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT13:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB6:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont13: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = shl i32 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], 244 -// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = and i32 [[TMP7]], 252 -// SANITIZE-WITH-ATTR-NEXT: [[CONV3:%.*]] = select i1 [[TMP5]], i32 [[TMP8]], i32 0 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV3]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = sext i32 [[ADD]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = icmp ult i64 [[TMP10]], [[TMP11]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP12]], label [[CONT34:%.*]], label [[HANDLER_OUT_OF_BOUNDS29:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds29: -// SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = zext i32 [[ADD]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB7:[0-9]+]], i64 [[TMP13]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont34: -// SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = icmp sgt i32 [[TMP9]], 3 -// SANITIZE-WITH-ATTR-NEXT: [[TMP15:%.*]] = shl i32 [[TMP9]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP16:%.*]] = add i32 [[TMP15]], 240 -// SANITIZE-WITH-ATTR-NEXT: [[TMP17:%.*]] = and i32 [[TMP16]], 252 -// SANITIZE-WITH-ATTR-NEXT: [[CONV20:%.*]] = select i1 [[TMP14]], i32 [[TMP17]], i32 0 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP10]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV20]], ptr [[ARRAYIDX32]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP18:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[ADD45:%.*]] = add nsw i32 [[INDEX]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP19:%.*]] = sext i32 [[ADD45]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP20:%.*]] = zext i32 [[TMP18]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP21:%.*]] = icmp ult i64 [[TMP19]], [[TMP20]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP21]], label [[CONT56:%.*]], label [[HANDLER_OUT_OF_BOUNDS51:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds51: -// SANITIZE-WITH-ATTR-NEXT: [[TMP22:%.*]] = zext i32 [[ADD45]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB8:[0-9]+]], i64 [[TMP22]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont56: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX54:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP19]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP23:%.*]] = sub nsw i32 [[TMP18]], [[FAM_IDX]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP24:%.*]] = or i32 [[TMP23]], [[FAM_IDX]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP24]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP25:%.*]] = shl i32 [[TMP23]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP26:%.*]] = and i32 [[TMP25]], 252 -// SANITIZE-WITH-ATTR-NEXT: [[CONV41:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP26]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV41]], ptr [[ARRAYIDX54]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test4( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = shl i32 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 244 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 252 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV1:%.*]] = select i1 [[TMP1]], i32 [[TMP4]], i32 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV1]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], 3 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = shl i32 [[TMP5]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = add i32 [[TMP7]], 240 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP9:%.*]] = and i32 [[TMP8]], 252 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV4:%.*]] = select i1 [[TMP6]], i32 [[TMP9]], i32 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM6:%.*]] = sext i32 [[ADD]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX7:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM6]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV4]], ptr [[ARRAYIDX7]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP10:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP11:%.*]] = sub nsw i32 [[TMP10]], [[FAM_IDX]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP12:%.*]] = or i32 [[TMP11]], [[FAM_IDX]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP12]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP13:%.*]] = shl i32 [[TMP11]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP14:%.*]] = and i32 [[TMP13]], 252 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV10:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP14]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ADD12:%.*]] = add nsw i32 [[INDEX]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM13:%.*]] = sext i32 [[ADD12]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM13]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV10]], ptr [[ARRAYIDX14]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM17:%.*]] = sext i32 [[ADD]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX18:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM17]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX18]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: [[ADD31:%.*]] = add nsw i32 [[INDEX]], 2 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM32:%.*]] = sext i32 [[ADD31]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM32]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX33]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test4( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]], i32 noundef [[FAM_IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX3]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD:%.*]] = add nsw i32 [[INDEX]], 1 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM9:%.*]] = sext i32 [[ADD]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX10:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM9]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX10]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ADD17:%.*]] = add nsw i32 [[INDEX]], 2 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM18:%.*]] = sext i32 [[ADD17]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX19:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM18]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 255, ptr [[ARRAYIDX19]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test4(struct annotated *p, int index, int fam_idx) { - // This tests calculating the size from a pointer inside the FAM. - p->array[index] = (unsigned char)__builtin_dynamic_object_size(&p->array[3], 1); - p->array[index + 1] = (unsigned char)__builtin_dynamic_object_size(&(p->array[4]), 1); - p->array[index + 2] = (unsigned char)__builtin_dynamic_object_size(&(p->array[fam_idx]), 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA8:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB9:[0-9]+]], i64 [[TMP3]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont12: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl nuw i64 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = tail call i64 @llvm.umax.i64(i64 [[TMP4]], i64 16) -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[TMP0]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP6]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test5( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA6:![0-9]+]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nuw i64 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.umax.i64(i64 [[TMP1]], i64 16) -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[TMP0]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP3]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test5( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test5(struct anon_struct *p, int index) { - p->array[index] = __builtin_dynamic_object_size(p, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA8]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = icmp ugt i64 [[TMP0]], [[TMP1]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP2]], label [[CONT12:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB10:[0-9]+]], i64 [[TMP3]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont12: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[TMP0]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP0]] to i32 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = shl i32 [[DOTTR]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]] -// SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test6( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i64, ptr [[COUNT]], align 8, !tbaa [[TBAA6]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i64 [[TMP0]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTTR:%.*]] = trunc i64 [[TMP0]] to i32 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl i32 [[DOTTR]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP1]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT]], ptr [[P]], i64 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test6( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAY:%.*]] = getelementptr inbounds [[STRUCT_ANON_STRUCT:%.*]], ptr [[P]], i64 1 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[ARRAY]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 -1, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test6(struct anon_struct *p, int index) { - p->array[index] = __builtin_dynamic_object_size(p->array, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 255 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ugt i32 [[TMP2]], [[INDEX]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT23:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB12:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont23: -// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[TMP5]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP1]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12) -// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = trunc i32 [[TMP6]] to i8 -// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = add i8 [[TMP7]], 4 -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP8]] -// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10:![0-9]+]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test7( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8:![0-9]+]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12) -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP1]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP4]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test7( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6:![0-9]+]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test7(struct union_of_fams *p, int index) { - p->ints[index] = __builtin_dynamic_object_size(p, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP3]], [[TMP2]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB13:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont24: -// SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[TMP3]] -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = tail call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0) -// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test8( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i8, ptr [[TMP0]], align 8, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i8 @llvm.smax.i8(i8 [[TMP1]], i8 0) -// NO-SANITIZE-WITH-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[NARROW]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test8( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[INTS:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 9 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[INTS]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test8(struct union_of_fams *p, int index) { - p->ints[index] = __builtin_dynamic_object_size(p->ints, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB14:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont24: -// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[TMP2]] -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP1]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[TMP6:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12) -// SANITIZE-WITH-ATTR-NEXT: [[TMP7:%.*]] = trunc i32 [[TMP6]] to i8 -// SANITIZE-WITH-ATTR-NEXT: [[TMP8:%.*]] = add i8 [[TMP7]], 4 -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP8]] -// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test9( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 12) -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[TMP1]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i32 [[TMP2]] to i8 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i8 0, i8 [[TMP4]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test9( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test9(struct union_of_fams *p, int index) { - p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = zext i32 [[TMP1]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP2]], [[TMP3]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP4]], label [[CONT24:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP5:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB15:[0-9]+]], i64 [[TMP5]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont24: -// SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[TMP2]] -// SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0) -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 -// SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA10]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test10( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_UNION_OF_FAMS:%.*]], ptr [[P]], i64 0, i32 1 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 8, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[NARROW:%.*]] = tail call i32 @llvm.smax.i32(i32 [[TMP1]], i32 0) -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = trunc i32 [[NARROW]] to i8 -// NO-SANITIZE-WITH-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i8 [[CONV]], ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA8]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test10( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BYTES:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 12 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i8], ptr [[BYTES]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i8 -1, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA6]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test10(struct union_of_fams *p, int index) { - p->bytes[index] = (unsigned char)__builtin_dynamic_object_size(p->bytes, 1); -} - -// SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11( -// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 1 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[COUNT]], align 8, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = zext i32 [[TMP0]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: br i1 [[TMP3]], label [[CONT7:%.*]], label [[HANDLER_OUT_OF_BOUNDS:%.*]], !prof [[PROF7]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: handler.out_of_bounds: -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = zext i32 [[INDEX]] to i64, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: tail call void @__ubsan_handle_out_of_bounds_abort(ptr nonnull @[[GLOB16:[0-9]+]], i64 [[TMP4]]) #[[ATTR4]], !nosanitize [[META6]] -// SANITIZE-WITH-ATTR-NEXT: unreachable, !nosanitize [[META6]] -// SANITIZE-WITH-ATTR: cont7: -// SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED]], ptr [[P]], i64 0, i32 2, i64 [[TMP1]] -// SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITH-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local void @test11( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret void -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local void @test11( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr nocapture noundef writeonly [[P:%.*]], i32 noundef [[INDEX:%.*]]) local_unnamed_addr #[[ATTR0]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[INDEX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ANNOTATED:%.*]], ptr [[P]], i64 0, i32 2, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 4, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret void -// -void test11(struct annotated *p, int index) { - p->array[index] = __builtin_dynamic_object_size(&p->count, 1); -} diff --git a/clang/test/CodeGen/bounds-checking.c b/clang/test/CodeGen/bounds-checking.c index 8100e30d0650ad..636d4f289e2478 100644 --- a/clang/test/CodeGen/bounds-checking.c +++ b/clang/test/CodeGen/bounds-checking.c @@ -69,6 +69,7 @@ int f7(union U *u, int i) { return u->c[i]; } + char B[10]; char B2[10]; // CHECK-LABEL: @f8 @@ -81,12 +82,3 @@ void f8(int i, int k) { // NOOPTARRAY: call void @llvm.ubsantrap(i8 4) B2[k] = '\0'; } - -// See commit 9a954c6 that caused a SEGFAULT in this code. -struct S { - __builtin_va_list ap; -} *s; -// CHECK-LABEL: @f9 -struct S *f9(int i) { - return &s[i]; -} diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index bdfda430eea86c..7b0cda0bca078d 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -61,7 +61,6 @@ // CHECK-NEXT: CoroOnlyDestroyWhenComplete (SubjectMatchRule_record) // CHECK-NEXT: CoroReturnType (SubjectMatchRule_record) // CHECK-NEXT: CoroWrapper (SubjectMatchRule_function) -// CHECK-NEXT: CountedBy (SubjectMatchRule_field) // CHECK-NEXT: DLLExport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: DLLImport (SubjectMatchRule_function, SubjectMatchRule_variable, SubjectMatchRule_record, SubjectMatchRule_objc_interface) // CHECK-NEXT: Destructor (SubjectMatchRule_function) diff --git a/clang/test/Sema/attr-counted-by.c b/clang/test/Sema/attr-counted-by.c deleted file mode 100644 index ab3b6e6d710b50..00000000000000 --- a/clang/test/Sema/attr-counted-by.c +++ /dev/null @@ -1,55 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -#define __counted_by(f) __attribute__((counted_by(f))) - -struct bar; - -struct not_found { - int count; - struct bar *fam[] __counted_by(bork); // expected-error {{use of undeclared identifier 'bork'}} -}; - -struct not_found_suggest { - int bork; // expected-note {{'bork' declared here}} - struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'; did you mean 'bork'?}} -}; - -int global; // expected-note {{'global' declared here}} - -struct found_outside_of_struct { - int bork; - struct bar *fam[] __counted_by(global); // expected-error {{field 'global' in 'counted_by' not inside structure}} -}; - -struct self_referrential { - int bork; - struct bar *self[] __counted_by(self); // expected-error {{'counted_by' cannot refer to the flexible array 'self'}} -}; - -struct non_int_count { - double dbl_count; // expected-note {{field 'dbl_count' declared here}} - struct bar *fam[] __counted_by(dbl_count); // expected-error {{field 'dbl_count' in 'counted_by' must be a non-boolean integer type}} -}; - -struct array_of_ints_count { - int integers[2]; // expected-note {{field 'integers' declared here}} - struct bar *fam[] __counted_by(integers); // expected-error {{field 'integers' in 'counted_by' must be a non-boolean integer type}} -}; - -struct not_a_fam { - int count; - struct bar *non_fam __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} -}; - -struct not_a_c99_fam { - int count; - struct bar *non_c99_fam[0] __counted_by(count); // expected-error {{'counted_by' only applies to C99 flexible array members}} -}; - -struct annotated_with_anon_struct { - unsigned long flags; - struct { - unsigned char count; // expected-note {{'count' declared here}} - int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'; did you mean 'count'?}} - }; -}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits