[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/bwendling closed https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/nickdesaulniers approved this pull request. https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
bwendling wrote: @nickdesaulniers and @alexfh Any comments? :-) https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
@@ -282,7 +282,7 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, + explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr, AaronBallman wrote: Improved const correctness -- I love it!! :-) (If the review takes a while, feel free to land the const correctness changes as an NFC commit.) https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/AaronBallman approved this pull request. LGTM! Thank you for the cleanup on the diagnostics, too. :-) https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/68750 >From b7b0c40542589e9c54c21140dbb5b163dd8ffc7b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 4 Oct 2023 17:55:49 -0700 Subject: [PATCH 1/4] [Clang] Implement the 'counted_by' attribute The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 --- 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| 15 ++ clang/include/clang/Sema/Sema.h | 2 + clang/lib/AST/ASTImporter.cpp | 13 + clang/lib/AST/DeclBase.cpp| 77 +- clang/lib/AST/Expr.cpp| 83 +-- clang/lib/CodeGen/CGBuiltin.cpp | 51 clang/lib/CodeGen/CGExpr.cpp | 64 - clang/lib/CodeGen/CodeGenFunction.h | 6 + clang/lib/Sema/SemaDecl.cpp | 12 + clang/lib/Sema/SemaDeclAttr.cpp | 132 ++ clang/test/CodeGen/attr-counted-by.c | 227 ++ clang/test/CodeGen/bounds-checking.c | 10 +- ...a-attribute-supported-attributes-list.test | 1 + clang/test/Sema/attr-counted-by.c | 42 19 files changed, 780 insertions(+), 78 deletions(-) create mode 100644 clang/test/CodeGen/attr-counted-by.c create mode 100644 clang/test/Sema/attr-counted-by.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d918967e7f0b02..1eebf5ea6b3e382 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,11 @@ 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 02e30e24c8be470..7f076cc77ea82cb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4302,6 +4302,30 @@ 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(this)->getLastField(); + } + + template + const FieldDecl *findFieldIf(Functor &Pred) const { +for (const Decl *D : decls()) { + if (const auto *FD = dyn_cast(D); FD && Pred(FD)) +return FD; + + if (const auto *RD = dyn_cast(D)) +if (const FieldDecl *FD = RD->findF
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
bwendling wrote: @AaronBallman I just added a patch that modifies the diagnostics to be more in line with what you wanted. PTAL. https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/68750 >From b7b0c40542589e9c54c21140dbb5b163dd8ffc7b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 4 Oct 2023 17:55:49 -0700 Subject: [PATCH 1/3] [Clang] Implement the 'counted_by' attribute The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 --- 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| 15 ++ clang/include/clang/Sema/Sema.h | 2 + clang/lib/AST/ASTImporter.cpp | 13 + clang/lib/AST/DeclBase.cpp| 77 +- clang/lib/AST/Expr.cpp| 83 +-- clang/lib/CodeGen/CGBuiltin.cpp | 51 clang/lib/CodeGen/CGExpr.cpp | 64 - clang/lib/CodeGen/CodeGenFunction.h | 6 + clang/lib/Sema/SemaDecl.cpp | 12 + clang/lib/Sema/SemaDeclAttr.cpp | 132 ++ clang/test/CodeGen/attr-counted-by.c | 227 ++ clang/test/CodeGen/bounds-checking.c | 10 +- ...a-attribute-supported-attributes-list.test | 1 + clang/test/Sema/attr-counted-by.c | 42 19 files changed, 780 insertions(+), 78 deletions(-) create mode 100644 clang/test/CodeGen/attr-counted-by.c create mode 100644 clang/test/Sema/attr-counted-by.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d918967e7f0b02..1eebf5ea6b3e382 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,11 @@ 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 02e30e24c8be470..7f076cc77ea82cb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4302,6 +4302,30 @@ 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(this)->getLastField(); + } + + template + const FieldDecl *findFieldIf(Functor &Pred) const { +for (const Decl *D : decls()) { + if (const auto *FD = dyn_cast(D); FD && Pred(FD)) +return FD; + + if (const auto *RD = dyn_cast(D)) +if (const FieldDecl *FD = RD->findF
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/oskarwirga commented: I've reviewed the admittedly limited sections I'm familiar with and LGTM! This is great work :) https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/bwendling updated https://github.com/llvm/llvm-project/pull/68750 >From b7b0c40542589e9c54c21140dbb5b163dd8ffc7b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 4 Oct 2023 17:55:49 -0700 Subject: [PATCH 1/2] [Clang] Implement the 'counted_by' attribute The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 --- 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| 15 ++ clang/include/clang/Sema/Sema.h | 2 + clang/lib/AST/ASTImporter.cpp | 13 + clang/lib/AST/DeclBase.cpp| 77 +- clang/lib/AST/Expr.cpp| 83 +-- clang/lib/CodeGen/CGBuiltin.cpp | 51 clang/lib/CodeGen/CGExpr.cpp | 64 - clang/lib/CodeGen/CodeGenFunction.h | 6 + clang/lib/Sema/SemaDecl.cpp | 12 + clang/lib/Sema/SemaDeclAttr.cpp | 132 ++ clang/test/CodeGen/attr-counted-by.c | 227 ++ clang/test/CodeGen/bounds-checking.c | 10 +- ...a-attribute-supported-attributes-list.test | 1 + clang/test/Sema/attr-counted-by.c | 42 19 files changed, 780 insertions(+), 78 deletions(-) create mode 100644 clang/test/CodeGen/attr-counted-by.c create mode 100644 clang/test/Sema/attr-counted-by.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d918967e7f0b02..1eebf5ea6b3e382 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,11 @@ 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 02e30e24c8be470..7f076cc77ea82cb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4302,6 +4302,30 @@ 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(this)->getLastField(); + } + + template + const FieldDecl *findFieldIf(Functor &Pred) const { +for (const Decl *D : decls()) { + if (const auto *FD = dyn_cast(D); FD && Pred(FD)) +return FD; + + if (const auto *RD = dyn_cast(D)) +if (const FieldDecl *FD = RD->findF
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 3a6cc52fe3501b2b7b3aabdff305a18122c9e0db b7b0c40542589e9c54c21140dbb5b163dd8ffc7b -- clang/test/CodeGen/attr-counted-by.c clang/test/Sema/attr-counted-by.c clang/include/clang/AST/Decl.h clang/include/clang/AST/DeclBase.h clang/include/clang/Sema/Sema.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/DeclBase.cpp clang/lib/AST/Expr.cpp clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CodeGenFunction.h clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/CodeGen/bounds-checking.c `` View the diff from clang-format here. ``diff diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 47e072ace072..934f7271b03e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -8457,8 +8457,7 @@ bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { 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) +Diag(SR.getBegin(), diag::err_counted_by_attr_not_on_flexible_array_member) << SR; return true; } @@ -8466,14 +8465,12 @@ bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { if (Field->hasAttr()) { // The "counted_by" field can't point to the flexible array member. SourceRange SR = CBA->getCountedByFieldLoc(); -Diag(SR.getBegin(), - diag::err_flexible_array_counted_by_attr_refers_to_self) +Diag(SR.getBegin(), diag::err_flexible_array_counted_by_attr_refers_to_self) << CBA->getCountedByField() << SR; return true; } - if (!Field->getType()->isIntegerType() || - Field->getType()->isBooleanType()) { + if (!Field->getType()->isIntegerType() || Field->getType()->isBooleanType()) { // The "counted_by" field must have an integer type. SourceRange SR = Field->getLocation(); Diag(SR.getBegin(), `` https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
bwendling wrote: And @AaronBallman, I haven't forgotten my promise to change the diagnostics. I've been on vacation, and it's become trickier to get them to work the other way than I had first thought. The change is coming soon though. https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
bwendling wrote: This is identical to the original change (9a954c693573281407f6ee3f4eb1b16cc545033d), but with a fix for the issue @alexfh discovered (https://github.com/llvm/llvm-project/commit/9a954c693573281407f6ee3f4eb1b16cc545033d#commitcomment-129529574). The change is on lines 473-475 of clang/lib/AST/DeclBase.cpp: using `dyn_cast_if_present` instead of just `dyn_cast`. Also added the testcase to `clang/test/CodeGen/bounds-checking.c`. https://github.com/llvm/llvm-project/pull/68750 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
llvmbot wrote: @llvm/pr-subscribers-clang-codegen Author: Bill Wendling (bwendling) Changes The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 --- Patch is 49.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/68750.diff 19 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 (+76-1) - (modified) clang/lib/AST/Expr.cpp (+10-73) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+51) - (modified) clang/lib/CodeGen/CGExpr.cpp (+61-3) - (modified) clang/lib/CodeGen/CodeGenFunction.h (+6) - (modified) clang/lib/Sema/SemaDecl.cpp (+12) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+132) - (added) clang/test/CodeGen/attr-counted-by.c (+227) - (modified) clang/test/CodeGen/bounds-checking.c (+9-1) - (modified) clang/test/Misc/pragma-attribute-supported-attributes-list.test (+1) - (added) clang/test/Sema/attr-counted-by.c (+42) ``diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d918967e7f0b02..1eebf5ea6b3e382 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -157,6 +157,11 @@ 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 02e30e24c8be470..7f076cc77ea82cb 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4302,6 +4302,30 @@ 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(this)->getLastField(); + } + + template + const FieldDecl *findFieldIf(Functor &Pred) const { +for (const Decl *D : decls()) { + if (const auto *FD = dyn_cast(D); FD && Pred(FD)) +return FD; + + if (const auto *RD = dyn_cast(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/c
[clang] [Clang] Implement the 'counted_by' attribute (PR #68750)
https://github.com/bwendling created https://github.com/llvm/llvm-project/pull/68750 The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 >From b7b0c40542589e9c54c21140dbb5b163dd8ffc7b Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 4 Oct 2023 17:55:49 -0700 Subject: [PATCH] [Clang] Implement the 'counted_by' attribute The 'counted_by' attribute is used on flexible array members. The argument for the attribute is the name of the 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. This example specifies the that the flexible array member 'array' has the number of elements allocated for it in 'count': struct bar; struct foo { size_t count; /* ... */ struct bar *array[] __attribute__((counted_by(count))); }; This establishes a relationship between 'array' and 'count', specifically that '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, the allocated array erroneously has fewer elements than what's specified by 'p->count'. This would result in an out-of-bounds access not not being detected: 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 + 42; } The next example updates 'p->count', breaking the relationship requirement that 'p->array' must have at least 'p->count' number of elements available: 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 + 42; } void use_foo(int index) { p->count += 42; p->array[index] = 0; /* The sanitizer cannot properly check this access */ } Reviewed By: nickdesaulniers, aaron.ballman Differential Revision: https://reviews.llvm.org/D148381 --- 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| 15 ++ clang/include/clang/Sema/Sema.h | 2 + clang/lib/AST/ASTImporter.cpp | 13 + clang/lib/AST/DeclBase.cpp| 77 +- clang/lib/AST/Expr.cpp| 83 +-- clang/lib/CodeGen/CGBuiltin.cpp | 51 clang/lib/CodeGen/CGExpr.cpp | 64 - clang/lib/CodeGen/CodeGenFunction.h | 6 + clang/lib/Sema/SemaDecl.cpp | 12 + clang/lib/Sema/SemaDeclAttr.cpp | 132 ++ clang/test/CodeGen/attr-counted-by.c | 227 ++ clang/test/CodeGen/bounds-checking.c