Skip to content

Commit ef46dd5

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 cef6387 commit ef46dd5

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
@@ -1871,6 +1871,14 @@ def fapinotes_swift_version : Joined<["-"], "fapinotes-swift-version=">,
18711871
MetaVarName<"<version>">,
18721872
HelpText<"Specify the Swift version to use when filtering API notes">;
18731873

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

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8695,7 +8695,7 @@ static bool CheckCountedByAttrOnField(
86958695
} else if (PointeeTy->isFunctionType()) {
86968696
InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION;
86978697
} else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) {
8698-
if (FieldTy->isArrayType()) {
8698+
if (FieldTy->isArrayType() && !S.getLangOpts().BoundsSafety) {
86998699
// This is a workaround for the Linux kernel that has already adopted
87008700
// `counted_by` on a FAM where the pointee is a struct with a FAM. This
87018701
// 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)