Skip to content

Commit 6447abe

Browse files
committed
Revert "[BoundsSafety] Allow 'counted_by' attribute on pointers in structs in C (#90786)"
Memory leak: https://lab.llvm.org/buildbot/#/builders/5/builds/43403 Issue #92687 This reverts commit 0ec3b97.
1 parent ed9007d commit 6447abe

21 files changed

+148
-1117
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,7 @@ New Compiler Flags
317317

318318
- ``-fexperimental-late-parse-attributes`` enables an experimental feature to
319319
allow late parsing certain attributes in specific contexts where they would
320-
not normally be late parsed. Currently this allows late parsing the
321-
`counted_by` attribute in C. See `Attribute Changes in Clang`_.
320+
not normally be late parsed.
322321

323322
- ``-fseparate-named-sections`` uses separate unique sections for global
324323
symbols in named special sections (i.e. symbols annotated with
@@ -407,24 +406,6 @@ Attribute Changes in Clang
407406
- The ``clspv_libclc_builtin`` attribute has been added to allow clspv
408407
(`OpenCL-C to Vulkan SPIR-V compiler <https://github.com/google/clspv>`_) to identify functions coming from libclc
409408
(`OpenCL-C builtin library <https://libclc.llvm.org>`_).
410-
- The ``counted_by`` attribute is now allowed on pointers that are members of a
411-
struct in C.
412-
413-
- The ``counted_by`` attribute can now be late parsed in C when
414-
``-fexperimental-late-parse-attributes`` is passed but only when attribute is
415-
used in the declaration attribute position. This allows using the
416-
attribute on existing code where it previously impossible to do so without
417-
re-ordering struct field declarations would break ABI as shown below.
418-
419-
.. code-block:: c
420-
421-
struct BufferTy {
422-
/* Refering to `count` requires late parsing */
423-
char* buffer __counted_by(count);
424-
/* Swapping `buffer` and `count` to avoid late parsing would break ABI */
425-
size_t count;
426-
};
427-
428409

429410
Improvements to Clang's diagnostics
430411
-----------------------------------

clang/include/clang/AST/Type.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2515,7 +2515,6 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
25152515
bool isRecordType() const;
25162516
bool isClassType() const;
25172517
bool isStructureType() const;
2518-
bool isStructureTypeWithFlexibleArrayMember() const;
25192518
bool isObjCBoxableRecordType() const;
25202519
bool isInterfaceType() const;
25212520
bool isStructureOrClassType() const;

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,8 +2229,7 @@ def TypeNullUnspecified : TypeAttr {
22292229
def CountedBy : DeclOrTypeAttr {
22302230
let Spellings = [Clang<"counted_by">];
22312231
let Subjects = SubjectList<[Field], ErrorDiag>;
2232-
let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel", 1>];
2233-
let LateParsed = LateAttrParseExperimentalExt;
2232+
let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel">];
22342233
let ParseArgumentsAsUnevaluated = 1;
22352234
let Documentation = [CountedByDocs];
22362235
let LangOpts = [COnly];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6533,10 +6533,8 @@ def warn_superclass_variable_sized_type_not_at_end : Warning<
65336533

65346534
def err_flexible_array_count_not_in_same_struct : Error<
65356535
"'counted_by' field %0 isn't within the same struct as the flexible array">;
6536-
def err_counted_by_attr_not_on_ptr_or_flexible_array_member : Error<
6537-
"'counted_by' only applies to pointers or C99 flexible array members">;
6538-
def err_counted_by_attr_on_array_not_flexible_array_member : Error<
6539-
"'counted_by' on arrays only applies to C99 flexible array members">;
6536+
def err_counted_by_attr_not_on_flexible_array_member : Error<
6537+
"'counted_by' only applies to C99 flexible array members">;
65406538
def err_counted_by_attr_refer_to_itself : Error<
65416539
"'counted_by' cannot refer to the flexible array member %0">;
65426540
def err_counted_by_must_be_in_structure : Error<
@@ -6551,17 +6549,6 @@ def err_counted_by_attr_refer_to_union : Error<
65516549
"'counted_by' argument cannot refer to a union member">;
65526550
def note_flexible_array_counted_by_attr_field : Note<
65536551
"field %0 declared here">;
6554-
def err_counted_by_attr_pointee_unknown_size : Error<
6555-
"'counted_by' cannot be applied to %select{"
6556-
"a pointer with pointee|" // pointer
6557-
"an array with element}0" // array
6558-
" of unknown size because %1 is %select{"
6559-
"an incomplete type|" // CountedByInvalidPointeeTypeKind::INCOMPLETE
6560-
"a sizeless type|" // CountedByInvalidPointeeTypeKind::SIZELESS
6561-
"a function type|" // CountedByInvalidPointeeTypeKind::FUNCTION
6562-
// CountedByInvalidPointeeTypeKind::FLEXIBLE_ARRAY_MEMBER
6563-
"a struct type with a flexible array member"
6564-
"}2">;
65656552

65666553
let CategoryName = "ARC Semantic Issue" in {
65676554

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,8 +1645,6 @@ class Parser : public CodeCompletionHandler {
16451645
bool EnterScope, bool OnDefinition);
16461646
void ParseLexedAttribute(LateParsedAttribute &LA,
16471647
bool EnterScope, bool OnDefinition);
1648-
void ParseLexedCAttribute(LateParsedAttribute &LA,
1649-
ParsedAttributes *OutAttrs = nullptr);
16501648
void ParseLexedMethodDeclarations(ParsingClass &Class);
16511649
void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
16521650
void ParseLexedMethodDefs(ParsingClass &Class);
@@ -2533,8 +2531,7 @@ class Parser : public CodeCompletionHandler {
25332531

25342532
void ParseStructDeclaration(
25352533
ParsingDeclSpec &DS,
2536-
llvm::function_ref<Decl *(ParsingFieldDeclarator &)> FieldsCallback,
2537-
LateParsedAttrList *LateFieldAttrs = nullptr);
2534+
llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback);
25382535

25392536
DeclGroupPtrTy ParseTopLevelStmtDecl();
25402537

@@ -3112,8 +3109,6 @@ class Parser : public CodeCompletionHandler {
31123109
SourceLocation ScopeLoc,
31133110
ParsedAttr::Form Form);
31143111

3115-
void DistributeCLateParsedAttrs(Decl *Dcl, LateParsedAttrList *LateAttrs);
3116-
31173112
void ParseBoundsAttribute(IdentifierInfo &AttrName,
31183113
SourceLocation AttrNameLoc, ParsedAttributes &Attrs,
31193114
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11396,8 +11396,7 @@ class Sema final : public SemaBase {
1139611396
QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns,
1139711397
SourceLocation AttrLoc);
1139811398

11399-
QualType BuildCountAttributedArrayOrPointerType(QualType WrappedTy,
11400-
Expr *CountExpr);
11399+
QualType BuildCountAttributedArrayType(QualType WrappedTy, Expr *CountExpr);
1140111400

1140211401
QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
1140311402
SourceLocation AttrLoc);

clang/lib/AST/Type.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -632,16 +632,6 @@ bool Type::isStructureType() const {
632632
return false;
633633
}
634634

635-
bool Type::isStructureTypeWithFlexibleArrayMember() const {
636-
const auto *RT = getAs<RecordType>();
637-
if (!RT)
638-
return false;
639-
const auto *Decl = RT->getDecl();
640-
if (!Decl->isStruct())
641-
return false;
642-
return Decl->hasFlexibleArrayMember();
643-
}
644-
645635
bool Type::isObjCBoxableRecordType() const {
646636
if (const auto *RT = getAs<RecordType>())
647637
return RT->getDecl()->hasAttr<ObjCBoxableAttr>();

clang/lib/Parse/ParseDecl.cpp

Lines changed: 7 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,19 +3288,6 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,
32883288
}
32893289
}
32903290

3291-
void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
3292-
LateParsedAttrList *LateAttrs) {
3293-
assert(Dcl && "Dcl cannot be null");
3294-
3295-
if (!LateAttrs)
3296-
return;
3297-
3298-
for (auto *LateAttr : *LateAttrs) {
3299-
if (LateAttr->Decls.empty())
3300-
LateAttr->addDecl(Dcl);
3301-
}
3302-
}
3303-
33043291
/// Bounds attributes (e.g., counted_by):
33053292
/// AttrName '(' expression ')'
33063293
void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
@@ -4838,14 +4825,13 @@ static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS,
48384825
///
48394826
void Parser::ParseStructDeclaration(
48404827
ParsingDeclSpec &DS,
4841-
llvm::function_ref<Decl *(ParsingFieldDeclarator &)> FieldsCallback,
4842-
LateParsedAttrList *LateFieldAttrs) {
4828+
llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback) {
48434829

48444830
if (Tok.is(tok::kw___extension__)) {
48454831
// __extension__ silences extension warnings in the subexpression.
48464832
ExtensionRAIIObject O(Diags); // Use RAII to do this.
48474833
ConsumeToken();
4848-
return ParseStructDeclaration(DS, FieldsCallback, LateFieldAttrs);
4834+
return ParseStructDeclaration(DS, FieldsCallback);
48494835
}
48504836

48514837
// Parse leading attributes.
@@ -4910,12 +4896,10 @@ void Parser::ParseStructDeclaration(
49104896
}
49114897

49124898
// If attributes exist after the declarator, parse them.
4913-
MaybeParseGNUAttributes(DeclaratorInfo.D, LateFieldAttrs);
4899+
MaybeParseGNUAttributes(DeclaratorInfo.D);
49144900

49154901
// We're done with this declarator; invoke the callback.
4916-
Decl *Field = FieldsCallback(DeclaratorInfo);
4917-
if (Field)
4918-
DistributeCLateParsedAttrs(Field, LateFieldAttrs);
4902+
FieldsCallback(DeclaratorInfo);
49194903

49204904
// If we don't have a comma, it is either the end of the list (a ';')
49214905
// or an error, bail out.
@@ -4926,69 +4910,6 @@ void Parser::ParseStructDeclaration(
49264910
}
49274911
}
49284912

4929-
/// Finish parsing an attribute for which parsing was delayed.
4930-
/// This will be called at the end of parsing a class declaration
4931-
/// for each LateParsedAttribute. We consume the saved tokens and
4932-
/// create an attribute with the arguments filled in. We add this
4933-
/// to the Attribute list for the decl.
4934-
void Parser::ParseLexedCAttribute(LateParsedAttribute &LA,
4935-
ParsedAttributes *OutAttrs) {
4936-
// Create a fake EOF so that attribute parsing won't go off the end of the
4937-
// attribute.
4938-
Token AttrEnd;
4939-
AttrEnd.startToken();
4940-
AttrEnd.setKind(tok::eof);
4941-
AttrEnd.setLocation(Tok.getLocation());
4942-
AttrEnd.setEofData(LA.Toks.data());
4943-
LA.Toks.push_back(AttrEnd);
4944-
4945-
// Append the current token at the end of the new token stream so that it
4946-
// doesn't get lost.
4947-
LA.Toks.push_back(Tok);
4948-
PP.EnterTokenStream(LA.Toks, /*DisableMacroExpansion=*/true,
4949-
/*IsReinject=*/true);
4950-
// Drop the current token and bring the first cached one. It's the same token
4951-
// as when we entered this function.
4952-
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
4953-
4954-
ParsedAttributes Attrs(AttrFactory);
4955-
4956-
assert(LA.Decls.size() <= 1 &&
4957-
"late field attribute expects to have at most one declaration.");
4958-
4959-
// Dispatch based on the attribute and parse it
4960-
const AttributeCommonInfo::Form ParsedForm = ParsedAttr::Form::GNU();
4961-
IdentifierInfo *ScopeName = nullptr;
4962-
const ParsedAttr::Kind AttrKind =
4963-
ParsedAttr::getParsedKind(&LA.AttrName, /*ScopeName=*/ScopeName,
4964-
/*SyntaxUsed=*/ParsedForm.getSyntax());
4965-
switch (AttrKind) {
4966-
case ParsedAttr::Kind::AT_CountedBy:
4967-
ParseBoundsAttribute(LA.AttrName, LA.AttrNameLoc, Attrs,
4968-
/*ScopeName=*/ScopeName, SourceLocation(),
4969-
/*Form=*/ParsedForm);
4970-
break;
4971-
default:
4972-
llvm_unreachable("Unhandled late parsed attribute");
4973-
}
4974-
4975-
for (auto *D : LA.Decls)
4976-
Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs);
4977-
4978-
// Due to a parsing error, we either went over the cached tokens or
4979-
// there are still cached tokens left, so we skip the leftover tokens.
4980-
while (Tok.isNot(tok::eof))
4981-
ConsumeAnyToken();
4982-
4983-
// Consume the fake EOF token if it's there
4984-
if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
4985-
ConsumeAnyToken();
4986-
4987-
if (OutAttrs) {
4988-
OutAttrs->takeAllFrom(Attrs);
4989-
}
4990-
}
4991-
49924913
/// ParseStructUnionBody
49934914
/// struct-contents:
49944915
/// struct-declaration-list
@@ -5012,11 +4933,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
50124933
ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
50134934
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
50144935

5015-
// `LateAttrParseExperimentalExtOnly=true` requests that only attributes
5016-
// marked with `LateAttrParseExperimentalExt` are late parsed.
5017-
LateParsedAttrList LateFieldAttrs(/*PSoon=*/false,
5018-
/*LateAttrParseExperimentalExtOnly=*/true);
5019-
50204936
// While we still have something to read, read the declarations in the struct.
50214937
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
50224938
Tok.isNot(tok::eof)) {
@@ -5067,19 +4983,18 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
50674983
}
50684984

50694985
if (!Tok.is(tok::at)) {
5070-
auto CFieldCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
4986+
auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
50714987
// Install the declarator into the current TagDecl.
50724988
Decl *Field =
50734989
Actions.ActOnField(getCurScope(), TagDecl,
50744990
FD.D.getDeclSpec().getSourceRange().getBegin(),
50754991
FD.D, FD.BitfieldSize);
50764992
FD.complete(Field);
5077-
return Field;
50784993
};
50794994

50804995
// Parse all the comma separated declarators.
50814996
ParsingDeclSpec DS(*this);
5082-
ParseStructDeclaration(DS, CFieldCallback, &LateFieldAttrs);
4997+
ParseStructDeclaration(DS, CFieldCallback);
50834998
} else { // Handle @defs
50844999
ConsumeToken();
50855000
if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
@@ -5120,12 +5035,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
51205035

51215036
ParsedAttributes attrs(AttrFactory);
51225037
// If attributes exist after struct contents, parse them.
5123-
MaybeParseGNUAttributes(attrs, &LateFieldAttrs);
5124-
5125-
// Late parse field attributes if necessary.
5126-
assert(!getLangOpts().CPlusPlus);
5127-
for (auto *LateAttr : LateFieldAttrs)
5128-
ParseLexedCAttribute(*LateAttr);
5038+
MaybeParseGNUAttributes(attrs);
51295039

51305040
SmallVector<Decl *, 32> FieldDecls(TagDecl->fields());
51315041

clang/lib/Parse/ParseObjc.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -780,16 +780,16 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
780780
}
781781

782782
bool addedToDeclSpec = false;
783-
auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
783+
auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
784784
if (FD.D.getIdentifier() == nullptr) {
785785
Diag(AtLoc, diag::err_objc_property_requires_field_name)
786786
<< FD.D.getSourceRange();
787-
return nullptr;
787+
return;
788788
}
789789
if (FD.BitfieldSize) {
790790
Diag(AtLoc, diag::err_objc_property_bitfield)
791791
<< FD.D.getSourceRange();
792-
return nullptr;
792+
return;
793793
}
794794

795795
// Map a nullability property attribute to a context-sensitive keyword
@@ -818,7 +818,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
818818
MethodImplKind);
819819

820820
FD.complete(Property);
821-
return Property;
822821
};
823822

824823
// Parse all the comma separated declarators.
@@ -2014,7 +2013,7 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl,
20142013
continue;
20152014
}
20162015

2017-
auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {
2016+
auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
20182017
assert(getObjCDeclContext() == interfaceDecl &&
20192018
"Ivar should have interfaceDecl as its decl context");
20202019
// Install the declarator into the interface decl.
@@ -2025,7 +2024,6 @@ void Parser::ParseObjCClassInstanceVariables(ObjCContainerDecl *interfaceDecl,
20252024
if (Field)
20262025
AllIvarDecls.push_back(Field);
20272026
FD.complete(Field);
2028-
return Field;
20292027
};
20302028

20312029
// Parse all the comma separated declarators.

0 commit comments

Comments
 (0)