void created this revision.
void added reviewers: kees, nickdesaulniers.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
void requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
A very simplisitc implementation of an "element_count" attribute. It's
used for flexible array members to indicate a field in the parent
structure contains the overall element count of the FAM:
struct foo {
size_t num_fam_elements;
// ...
struct bar *fam[] __attribute__((element_count(num_fam_elements)));
};
struct foo *foo_alloc(size_t num_elements) {
struct foo *f = malloc(sizeof(struct foo) + num_elements *
sizeof(struct bar *));
f->num_fam_elements = num_elements;
return f;
}
$ clang -fsanitize=array-bounds -fstrict-flex-arrays=3 ...
As mentioned, this is for simplistic versions of a structure with a FAM.
Future additions will include supporting, FAMs and counts in
sub-structures.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D148381
Files:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/lib/AST/ASTImporter.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/Sema/SemaDeclAttr.cpp
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8238,6 +8238,12 @@
D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL));
}
+static void handleElementCountAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ // TODO: Probably needs more processing here. See Sema::AddAlignValueAttr.
+ IdentifierInfo *Name = AL.getArgAsIdent(0)->Ident;
+ D->addAttr(::new (S.Context) ElementCountAttr(S.Context, AL, Name));
+}
+
static void handleFunctionReturnThunksAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
StringRef KindStr;
@@ -9142,6 +9148,9 @@
case ParsedAttr::AT_FunctionReturnThunks:
handleFunctionReturnThunksAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ElementCount:
+ handleElementCountAttr(S, D, AL);
+ break;
// Microsoft attributes:
case ParsedAttr::AT_LayoutVersion:
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -946,6 +946,30 @@
return CGF.getVLASize(VAT).NumElts;
// Ignore pass_object_size here. It's not applicable on decayed pointers.
}
+
+ if (auto *ME = dyn_cast<MemberExpr>(CE->getSubExpr())) {
+ if (ME->isFlexibleArrayMemberLike(CGF.getContext(),
+ StrictFlexArraysLevel, true)) {
+ if (auto *MD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
+ if (auto ECA = MD->getAttr<ElementCountAttr>()) {
+ RecordDecl *RD = MD->getParent();
+ IdentifierInfo *CountField = ECA->getElementCountField();
+
+ for (FieldDecl *FD : RD->fields()) {
+ if (FD->getName() != CountField->getName())
+ continue;
+
+ auto *Mem = MemberExpr::CreateImplicit(
+ CGF.getContext(), const_cast<Expr*>(ME->getBase()), true, FD,
+ FD->getType(), VK_LValue, OK_Ordinary);
+
+ IndexedType = Base->getType();
+ return CGF.EmitAnyExprToTemp(Mem).getScalarVal();
+ }
+ }
+ }
+ }
+ }
}
QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0};
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -8979,6 +8979,11 @@
From->args_size());
break;
}
+ case attr::ElementCount: {
+ const auto *From = cast<ElementCountAttr>(FromAttr);
+ AI.importAttr(From, From->getElementCountField());
+ break;
+ }
default: {
// The default branch works for attributes that have no arguments to import.
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -6950,3 +6950,10 @@
its underlying representation to be a WebAssembly ``funcref``.
}];
}
+
+def ElementCountDocs : Documentation {
+ let Category = DocCatField;
+ let Content = [{
+Clang supports the ``__element_count__`` attribute for flexible array members.
+ }];
+}
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -4158,3 +4158,11 @@
let Subjects = SubjectList<[Record]>;
let Documentation = [ReadOnlyPlacementDocs];
}
+
+def ElementCount : InheritableAttr {
+ let Spellings = [Clang<"element_count">];
+ let Subjects = SubjectList<[Field]>;
+ let Args = [IdentifierArgument<"ElementCountField">];
+ let Documentation = [ElementCountDocs];
+ let LangOpts = [COnly];
+}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits