Skip to content

Commit 6da23b6

Browse files
authored
[BoundsSafety] Add -fexperimental-bounds-safety CC1 and language option and use it to tweak counted_by's semantics (#92623)
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 fdfc491 commit 6da23b6

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,9 @@ BENIGN_LANGOPT(CheckNew, 1, 0, "Do not assume C++ operator new may not return NU
520520
BENIGN_LANGOPT(CheckConstexprFunctionBodies, 1, 1,
521521
"Emit diagnostics for a constexpr function body that can never "
522522
"be used in a constant expression.")
523+
524+
LANGOPT(BoundsSafety, 1, 0, "Bounds safety extension for C")
525+
523526
#undef LANGOPT
524527
#undef COMPATIBLE_LANGOPT
525528
#undef BENIGN_LANGOPT

clang/include/clang/Driver/Options.td

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

1914+
defm bounds_safety : BoolFOption<
1915+
"experimental-bounds-safety",
1916+
LangOpts<"BoundsSafety">, DefaultFalse,
1917+
PosFlag<SetTrue, [], [CC1Option], "Enable">,
1918+
NegFlag<SetFalse, [], [CC1Option], "Disable">,
1919+
BothFlags<[], [CC1Option],
1920+
" experimental bounds safety extension for C">>;
1921+
19141922
defm addrsig : BoolFOption<"addrsig",
19151923
CodeGenOpts<"Addrsig">, DefaultFalse,
19161924
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Emit">,

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5948,7 +5948,7 @@ CheckCountedByAttrOnField(Sema &S, FieldDecl *FD, Expr *E,
59485948
} else if (PointeeTy->isFunctionType()) {
59495949
InvalidTypeKind = CountedByInvalidPointeeTypeKind::FUNCTION;
59505950
} else if (PointeeTy->isStructureTypeWithFlexibleArrayMember()) {
5951-
if (FieldTy->isArrayType()) {
5951+
if (FieldTy->isArrayType() && !S.getLangOpts().BoundsSafety) {
59525952
// This is a workaround for the Linux kernel that has already adopted
59535953
// `counted_by` on a FAM where the pointee is a struct with a FAM. This
59545954
// 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)