llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Pengxiang Huang (Pengxiang-Huang) <details> <summary>Changes</summary> Implements for: #<!-- -->186914 Move the call to `ActOnFields()` before `ParseLexedCAttributeList()` in ParseStructUnionBody for reordering so that the struct type is complete when late-parsed attributes like counted_by get evaluated. This is a prerequisite for supporting sizeof/offsetof expressions in counted_by evaluation. Update the heuristic for `GetEnclosingNamedOrTopAnonRecord`. Remove the `isCompleteDefinition()` condition since it will always return true under the new ordering. The `GetEnclosingNamedOrTopAnonRecord` intend to treat the unnamed and anonymous struct permissively. Add one test to verify the new ordering still make sure the function of unnamed and anonymous struct works normally. --- Full diff: https://github.com/llvm/llvm-project/pull/187166.diff 3 Files Affected: - (modified) clang/lib/Parse/ParseDecl.cpp (+3-3) - (modified) clang/lib/Sema/SemaBoundsSafety.cpp (+1-2) - (added) clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs-anon.c (+65) ``````````diff diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 72935f427b7f8..fe281f156e988 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4989,13 +4989,13 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs, &LateFieldAttrs); - // Late parse field attributes if necessary. - ParseLexedCAttributeList(LateFieldAttrs, /*EnterScope=*/false); - SmallVector<Decl *, 32> FieldDecls(TagDecl->fields()); Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, T.getOpenLocation(), T.getCloseLocation(), attrs); + + // Late parse field attributes if necessary. + ParseLexedCAttributeList(LateFieldAttrs, /*EnterScope=*/false); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp index 8c8e37d321938..faf352b3a366f 100644 --- a/clang/lib/Sema/SemaBoundsSafety.cpp +++ b/clang/lib/Sema/SemaBoundsSafety.cpp @@ -32,8 +32,7 @@ static const RecordDecl *GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD) { // However, the struct may not be fully processed yet to determine // whether it's anonymous or not. In that case, this function treats it as // an anonymous struct and tries to find a named parent. - while (RD && (RD->isAnonymousStructOrUnion() || - (!RD->isCompleteDefinition() && RD->getName().empty()))) { + while (RD && (RD->isAnonymousStructOrUnion() || RD->getName().empty())) { const auto *Parent = dyn_cast<RecordDecl>(RD->getParent()); if (!Parent) break; diff --git a/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs-anon.c b/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs-anon.c new file mode 100644 index 0000000000000..8b74f46b064f5 --- /dev/null +++ b/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs-anon.c @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s + +// Test that counted_by works correctly with late parsing when ActOnFields +// is called before late-parsed attributes are evaluated. This allows offset +// expressions in counted_by to be evaluated. + +#define __counted_by(f) __attribute__((counted_by(f))) + +struct size_known { + int field; +}; + +//============================================================================== +// Verify anonymous struct handling works corrctly under currect ordering. +// GetEnclosingNamedOrTopAnonRecord must correctly walk through anonymous +// structs when the struct is already marked complete. +//============================================================================== + +// count in outer struct, buf in anonymous struct +struct on_pointer_anon_buf { + int count; + struct { + struct size_known *buf __counted_by(count); + }; +}; + +// both count and buf in anonymous struct +struct on_pointer_anon_both { + struct { + int count; + struct size_known *buf __counted_by(count); + }; +}; + +// nested anonymous structs +struct on_pointer_nested_anon { + int count; + struct { + struct { + struct size_known *buf __counted_by(count); + }; + }; +}; + +//============================================================================== +// Verify non-anonymous unnamed structs correctly reject counted_by if it +// reference fields in the outer struct. +//============================================================================== + +// count in outer, buf in non-anonymous unnamed struct — should reject +struct on_pointer_named_inner { + int count; // expected-note{{'count' declared here}} + struct { + // expected-error@+1{{'counted_by' field 'count' isn't within the same struct as the annotated pointer}} + struct size_known *buf __counted_by(count); + } inner; +}; + +// both in non-anonymous unnamed struct — should accept +struct on_pointer_named_inner_both { + struct { + int count; + struct size_known *buf __counted_by(count); + } inner; +}; `````````` </details> https://github.com/llvm/llvm-project/pull/187166 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
