Skip to content

Commit ffe5280

Browse files
committed
[BoundsSafety] Add -fexperimental-bounds-safety CC1 and language option and use it to tweak counted_by's semantics
This adds the `-fexperimental-bounds-safety` cc1 and corresponding language option. This language option enables "-fbounds-safety" which is a bounds-safety extension for C that is being incrementally upstreamed. This cc1 flag is not exposed as a driver flag yet because most of the implementation isn't upstream yet. The language option is used to make a small semantic change to how the `counted_by` attribute is treated. Without `-fexperimental-bounds-safety` the attribute is allowed (but emits a warning) on a flexible array member where the element type is a struct with a flexible array member. With the flag this situation is an error. E.g. ``` struct has_unannotated_FAM { int count; char buffer[]; }; struct buffer_of_structs_with_unnannotated_FAM { int count; // Forbidden with `-fexperimental-bounds-safety` struct has_unannotated_FAM Arr[] __counted_by(count); }; ``` rdar://125400392
1 parent 41c057b commit ffe5280

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,8 @@ COMPATIBLE_LANGOPT(IncrementalExtensions, 1, 0, " True if we want to process sta
504504

505505
BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NULL")
506506

507+
LANGOPT(BoundsSafety, 1, 0, "Bounds safety extension for C")
508+
507509
#undef LANGOPT
508510
#undef COMPATIBLE_LANGOPT
509511
#undef BENIGN_LANGOPT

clang/include/clang/Driver/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,14 @@ def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
18721872
MetaVarName<"<version>">,
18731873
HelpText<"Specify the Swift version to use when filtering API notes">;
18741874

1875+
defm bounds_safety : BoolFOption<
1876+
"experimental-bounds-safety",
1877+
LangOpts<"BoundsSafety">, DefaultFalse,
1878+
PosFlag<SetTrue, [], [CC1Option], "Enable">,
1879+
NegFlag<SetFalse, [], [CC1Option], "Disable">,
1880+
BothFlags<[], [CC1Option],
1881+
" experimental bounds safety extension for C">>;
1882+
18751883
defm addrsig : BoolFOption<"addrsig",
18761884
CodeGenOpts<"Addrsig">, DefaultFalse,
18771885
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8725,7 +8725,7 @@ static bool CheckCountedByAttrOnField(
87258725
} else if (PointeeTy->isFunctionType()) {
87268726
InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION;
87278727
} else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) {
8728-
if (FieldTy->isArrayType()) {
8728+
if (FieldTy->isArrayType() && !S.getLangOpts().BoundsSafety) {
87298729
// This is a workaround for the Linux kernel that has already adopted
87308730
// `counted_by` on a FAM where the pointee is a struct with a FAM. This
87318731
// should be an error because computing the bounds of the array cannot be
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 -fsyntax-only -fexperimental-bounds-safety -verify %s
2+
//
3+
// This is a portion of the `attr-counted-by-vla.c` test but is checked
4+
// under the semantics of `-fexperimental-bounds-safety` which has different
5+
// behavior.
6+
7+
#define __counted_by(f) __attribute__((counted_by(f)))
8+
9+
struct has_unannotated_VLA {
10+
int count;
11+
char buffer[];
12+
};
13+
14+
struct has_annotated_VLA {
15+
int count;
16+
char buffer[] __counted_by(count);
17+
};
18+
19+
struct buffer_of_structs_with_unnannotated_vla {
20+
int count;
21+
// expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_unannotated_VLA' is a struct type with a flexible array member}}
22+
struct has_unannotated_VLA Arr[] __counted_by(count);
23+
};
24+
25+
26+
struct buffer_of_structs_with_annotated_vla {
27+
int count;
28+
// expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'struct has_annotated_VLA' is a struct type with a flexible array member}}
29+
struct has_annotated_VLA Arr[] __counted_by(count);
30+
};
31+
32+
struct buffer_of_const_structs_with_annotated_vla {
33+
int count;
34+
// Make sure the `const` qualifier is printed when printing the element type.
35+
// expected-error@+1{{'counted_by' cannot be applied to an array with element of unknown size because 'const struct has_annotated_VLA' is a struct type with a flexible array member}}
36+
const struct has_annotated_VLA Arr[] __counted_by(count);
37+
};

0 commit comments

Comments
 (0)