llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang <details> <summary>Changes</summary> This reverts commit 9a954c693573281407f6ee3f4eb1b16cc545033d, which causes clang crashes when compiling with `-fsanitize=bounds`. See https://github.com/llvm/llvm-project/commit/9a954c693573281407f6ee3f4eb1b16cc545033d#commitcomment-129529574 for details. --- Patch is 48.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/68603.diff 18 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (-5) - (modified) clang/include/clang/AST/Decl.h (-24) - (modified) clang/include/clang/AST/DeclBase.h (-10) - (modified) clang/include/clang/Basic/Attr.td (-18) - (modified) clang/include/clang/Basic/AttrDocs.td (-66) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (-15) - (modified) clang/include/clang/Sema/Sema.h (-2) - (modified) clang/lib/AST/ASTImporter.cpp (-13) - (modified) clang/lib/AST/DeclBase.cpp (+1-75) - (modified) clang/lib/AST/Expr.cpp (+73-10) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (-51) - (modified) clang/lib/CodeGen/CGExpr.cpp (+3-61) - (modified) clang/lib/CodeGen/CodeGenFunction.h (-6) - (modified) clang/lib/Sema/SemaDecl.cpp (-12) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (-132) - (removed) clang/test/CodeGen/attr-counted-by.c (-227) - (modified) clang/test/Misc/pragma-attribute-supported-attributes-list.test (-1) - (removed) clang/test/Sema/attr-counted-by.c (-42) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 078d697d8465242..d85db6f795c5274 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -139,11 +139,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. C23 Feature Support ^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 7f076cc77ea82cb..02e30e24c8be470 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4302,30 +4302,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 d383e46e22e16f4..12137387b676a7d 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -18,7 +18,6 @@ #include "clang/AST/DeclarationName.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" @@ -478,15 +477,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 5c9eb7b8a981037..7a6ec77ae84b15a 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4246,21 +4246,3 @@ def AvailableOnlyInDefaultEvalMethod : InheritableAttr { let Subjects = SubjectList<[TypedefName], ErrorDiag>; 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; } - }]; -} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 9f9991bdae36155..8d928dcc146b254 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -7275,69 +7275,3 @@ relative ordering of values is important. For example: 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. */ - } - - }]; -} diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b211680a0e9b6e9..c1a6e3831127e56 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6389,21 +6389,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 flexible array members">; -def err_flexible_array_counted_by_attr_field_not_found : Error< - "field %0 in 'counted_by' not found">; -def err_flexible_array_counted_by_attr_field_not_found_suggest : Error< - "field %0 in 'counted_by' not found; did you mean %1?">; -def err_flexible_array_counted_by_attr_field_not_found_in_struct : Error< - "field %0 in 'counted_by' is not found in struct">; -def err_flexible_array_counted_by_attr_refers_to_self : Error< - "field %0 in 'counted_by' cannot refer to the flexible array">; -def err_flexible_array_counted_by_attr_field_not_integer : Error< - "field %0 in 'counted_by' is not 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 1c88855a73970d3..2ebd21090ae4e11 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4795,8 +4795,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. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 3adbabdb7fb878a..72e70427161bb0e 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8978,10 +8978,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. @@ -9188,15 +9184,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 4823d70aa7e4954..3804f1a5b49d3cd 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,81 +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(); - FAMKind StrictFlexArraysLevel = - Ctx.getLangOpts().getStrictFlexArraysLevel(); - - 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>()) { - const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); - if (!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 5d3b510df1ef9b3..4bfc4f082cd6a69 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 bf984861bccb5cc..3f68aa2c953c74b 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -853,57 +853,6 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, } } - if (IsDynamic) { - LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = - getLangOpts().getStrictFlexArraysLevel(); - const Expr *Base = E->IgnoreParenImpCasts(); - - if (FieldDecl *FD = FindCountedByField(Base, StrictFlexArraysLevel)) { - const auto *ME = dyn_cast<MemberExpr>(Base); - llvm::Value *ObjectSize = nullptr; - - if (!ME) { - const auto *DRE = dyn_cast<DeclRefExpr>(Base); - ValueDecl *VD = nullptr; - - ObjectSize = ConstantInt::get( - ResType, - getContext().getTypeSize(DRE->getType()->getPointeeType()) / 8, - true); - - if (auto *RD = DRE->getType()->getPointeeType()->getAsRecordDecl()) - VD = RD->getLastField(); - - Expr *ICE = ImplicitCastExpr::Create( - getContext(), DRE->getType(), CK_LValueToRValue, - const_cast<Expr *>(cast<Expr>(DRE)), nullptr, VK_PRValue, - FPOptionsOverride()); - ME = MemberExpr::CreateImplicit(getContext(), ICE, true, VD, - VD->getType(), VK_LValue, OK_Ordinary); - } - - // At this point, we know that \p ME is a flexible array member. - const auto *ArrayTy = getContext().getAsArrayType(ME->getType()); - unsigned Size = getContext().getTypeSize(ArrayTy->getElementType()); - - llvm::Value *CountField = - EmitAnyExprToTemp(MemberExpr::CreateImplicit( - getContext(), const_cast<Expr *>(ME->getBase()), - ME->isArrow(), FD, FD->getType(), VK_LValue, - OK_Ordinary)) - .getScalarVal(); - - llvm::Value *Mul = Builder.CreateMul( - CountField, llvm::ConstantInt::get(CountField->getType(), Size / 8)); - Mul = Builder.CreateZExtOrTrunc(Mul, ResType); - - if (ObjectSize) - return Builder.CreateAdd(ObjectSize, Mul); - - return Mul; - } - } - // 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 54a1d300a9ac738..1b6a2c1fc49967c 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" @@ -932,31 +931,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 po... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/68603 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits