llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Yeoul Na (rapidsna)

<details>
<summary>Changes</summary>

Previously, late parsing only supported attributes in declaration position and 
could not resolve references to member declarations that appeared later in the 
struct. Additionally, the compiler incorrectly accepted `counted_by` on nested 
pointer types, which should be rejected. Instead, these attributes were 
incorrectly attached to the outermost pointer type because they were being 
treated as GNU-style declaration attributes rather than type attributes.

This commit adds a vector of `LateParsedAttribute *` to `DeclaratorChunk`, 
similar to how `ParsedAttr` is attached to `DeclaratorChunk`. Since DeclSpec 
doesn't see the definition of `LateParsedAttribute`, it is treated as an opaque 
pointer type. When the late-attribute is actually parsed, it is now correctly 
attached to the appropriate nested type level, enabling references to members 
declared later when the late-parsed attribute is in type position, and 
rejection of invalid nested pointer cases.

Issue #<!-- -->166411

---

Patch is 77.84 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/166491.diff


23 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) 
- (modified) clang/include/clang/Parse/Parser.h (+19-12) 
- (modified) clang/include/clang/Sema/DeclSpec.h (+7-1) 
- (modified) clang/include/clang/Sema/Sema.h (+6-4) 
- (modified) clang/lib/Parse/ParseDecl.cpp (+59-22) 
- (modified) clang/lib/Sema/SemaBoundsSafety.cpp (+8-2) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+4-2) 
- (modified) clang/lib/Sema/SemaDeclAttr.cpp (+23-9) 
- (modified) clang/test/AST/attr-counted-by-or-null-struct-ptrs.c (-23) 
- (modified) clang/test/AST/attr-counted-by-struct-ptrs.c (-26) 
- (modified) clang/test/AST/attr-sized-by-or-null-struct-ptrs.c (-24) 
- (modified) clang/test/AST/attr-sized-by-struct-ptrs.c (-24) 
- (added) clang/test/Sema/attr-bounds-safety-function-ptr-param.c (+173) 
- (modified) clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c (+7-42) 
- (modified) clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c 
(+7-42) 
- (modified) 
clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c
 (+15-18) 
- (modified) clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c (+2-6) 
- (modified) 
clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c 
(+15-17) 
- (modified) clang/test/Sema/attr-counted-by-struct-ptrs.c (+2-6) 
- (modified) clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c (+6-33) 
- (modified) clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c 
(+8-38) 
- (modified) clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c (+2-6) 
- (modified) clang/test/Sema/attr-sized-by-struct-ptrs.c (+2-4) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fa509536bf021..98b470a525d11 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7012,6 +7012,9 @@ def err_builtin_counted_by_ref_invalid_use : Error<
   "value returned by '__builtin_counted_by_ref' cannot be used in "
   "%select{an array subscript|a binary}0 expression">;
 
+def err_counted_by_on_nested_pointer : Error<
+  "'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' 
attribute on nested pointer type is not allowed">;
+
 let CategoryName = "ARC Semantic Issue" in {
 
 // ARC-mode diagnostics.
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index dad8efd0f017f..8f7c921fb2b1d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1161,10 +1161,11 @@ class Parser : public CodeCompletionHandler {
     IdentifierInfo *MacroII = nullptr;
     SourceLocation AttrNameLoc;
     SmallVector<Decl *, 2> Decls;
+    unsigned NestedTypeLevel;
 
     explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name,
-                                 SourceLocation Loc)
-        : Self(P), AttrName(Name), AttrNameLoc(Loc) {}
+                                 SourceLocation Loc, unsigned Level = 0)
+        : Self(P), AttrName(Name), AttrNameLoc(Loc), NestedTypeLevel(Level) {}
 
     void ParseLexedAttributes() override;
 
@@ -1889,10 +1890,12 @@ class Parser : public CodeCompletionHandler {
       DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext,
       LateParsedAttrList *LateAttrs = nullptr);
 
-  void ParseSpecifierQualifierList(
-      DeclSpec &DS, AccessSpecifier AS = AS_none,
-      DeclSpecContext DSC = DeclSpecContext::DSC_normal) {
-    ParseSpecifierQualifierList(DS, getImplicitTypenameContext(DSC), AS, DSC);
+  void
+  ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none,
+                              DeclSpecContext DSC = 
DeclSpecContext::DSC_normal,
+                              LateParsedAttrList *LateAttrs = nullptr) {
+    ParseSpecifierQualifierList(DS, getImplicitTypenameContext(DSC), AS, DSC,
+                                LateAttrs);
   }
 
   /// ParseSpecifierQualifierList
@@ -1903,10 +1906,12 @@ class Parser : public CodeCompletionHandler {
   /// [GNU]    attributes     specifier-qualifier-list[opt]
   /// \endverbatim
   ///
-  void ParseSpecifierQualifierList(
-      DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename,
-      AccessSpecifier AS = AS_none,
-      DeclSpecContext DSC = DeclSpecContext::DSC_normal);
+  void
+  ParseSpecifierQualifierList(DeclSpec &DS,
+                              ImplicitTypenameContext AllowImplicitTypename,
+                              AccessSpecifier AS = AS_none,
+                              DeclSpecContext DSC = 
DeclSpecContext::DSC_normal,
+                              LateParsedAttrList *LateAttrs = nullptr);
 
   /// ParseEnumSpecifier
   /// \verbatim
@@ -2444,7 +2449,8 @@ class Parser : public CodeCompletionHandler {
                                  SourceLocation ScopeLoc,
                                  ParsedAttr::Form Form);
 
-  void DistributeCLateParsedAttrs(Decl *Dcl, LateParsedAttrList *LateAttrs);
+  void DistributeCLateParsedAttrs(Declarator &D, Decl *Dcl,
+                                  LateParsedAttrList *LateAttrs);
 
   /// Bounds attributes (e.g., counted_by):
   /// \verbatim
@@ -2610,7 +2616,8 @@ class Parser : public CodeCompletionHandler {
   void ParseTypeQualifierListOpt(
       DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed,
       bool AtomicOrPtrauthAllowed = true, bool IdentifierRequired = false,
-      llvm::function_ref<void()> CodeCompletionHandler = {});
+      llvm::function_ref<void()> CodeCompletionHandler = {},
+      LateParsedAttrList *LateAttrs = nullptr);
 
   /// ParseDirectDeclarator
   /// \verbatim
diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 43a48c92fc305..9f633dd71c3f6 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1238,6 +1238,9 @@ struct DeclaratorChunk {
 
   ParsedAttributesView AttrList;
 
+  using LateAttrListTy = SmallVector<void *, 1>;
+  LateAttrListTy LateAttrList;
+
   struct PointerTypeInfo {
     /// The type qualifiers: const/volatile/restrict/unaligned/atomic.
     LLVM_PREFERRED_TYPE(DeclSpec::TQ)
@@ -2325,13 +2328,16 @@ class Declarator {
   /// This function takes attrs by R-Value reference because it takes ownership
   /// of those attributes from the parameter.
   void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs,
-                   SourceLocation EndLoc) {
+                   SourceLocation EndLoc,
+                   const DeclaratorChunk::LateAttrListTy &LateAttrs = {}) {
     DeclTypeInfo.push_back(TI);
     DeclTypeInfo.back().getAttrs().prepend(attrs.begin(), attrs.end());
     getAttributePool().takeAllFrom(attrs.getPool());
 
     if (!EndLoc.isInvalid())
       SetRangeEnd(EndLoc);
+
+    DeclTypeInfo.back().LateAttrList.assign(LateAttrs);
   }
 
   /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c67ed99b1f49e..becadbb1a39d6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2457,8 +2457,8 @@ class Sema final : public SemaBase {
   /// `counted_by_or_null` attribute.
   ///
   /// \returns false iff semantically valid.
-  bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
-                                 bool OrNull);
+  bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, unsigned Level,
+                                 bool CountInBytes, bool OrNull);
 
   /// Perform Bounds Safety Semantic checks for assigning to a `__counted_by` 
or
   /// `__counted_by_or_null` pointer type \param LHSTy.
@@ -4198,7 +4198,8 @@ class Sema final : public SemaBase {
 
   /// ActOnFinishDelayedAttribute - Invoked when we have finished parsing an
   /// attribute for which parsing is delayed.
-  void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs);
+  void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs,
+                                   unsigned NestedTypeLevel = 0);
 
   /// Diagnose any unused parameters in the given sequence of
   /// ParmVarDecl pointers.
@@ -5071,7 +5072,8 @@ class Sema final : public SemaBase {
   void ProcessDeclAttributeList(Scope *S, Decl *D,
                                 const ParsedAttributesView &AttrList,
                                 const ProcessDeclAttributeOptions &Options =
-                                    ProcessDeclAttributeOptions());
+                                    ProcessDeclAttributeOptions(),
+                                unsigned NestedTypeLevel = 0);
 
   /// Annotation attributes are the only attributes allowed after an access
   /// specifier.
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7e4a164e34eda..514f6daf44e2f 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1943,7 +1943,11 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
 
   ParsedTemplateInfo TemplateInfo;
   DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);
-  ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext);
+  // FIXME: Why is PSoon true?
+  LateParsedAttrList BoundsSafetyLateAttrs(
+      /*PSoon=*/true, /*LateAttrParseExperimentalExtOnly=*/true);
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext,
+                             &BoundsSafetyLateAttrs);
 
   // If we had a free-standing type definition with a missing semicolon, we
   // may get this far before the problem becomes obvious.
@@ -2725,12 +2729,12 @@ Decl 
*Parser::ParseDeclarationAfterDeclaratorAndAttributes(
 
 void Parser::ParseSpecifierQualifierList(
     DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename,
-    AccessSpecifier AS, DeclSpecContext DSC) {
+    AccessSpecifier AS, DeclSpecContext DSC, LateParsedAttrList *LateAttrs) {
   ParsedTemplateInfo TemplateInfo;
   /// specifier-qualifier-list is a subset of declaration-specifiers.  Just
   /// parse declaration-specifiers and complain about extra stuff.
   /// TODO: diagnose attribute-specifiers and alignment-specifiers.
-  ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, nullptr,
+  ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, LateAttrs,
                              AllowImplicitTypename);
 
   // Validate declspec for type-name.
@@ -3136,15 +3140,37 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes 
&Attrs,
   }
 }
 
-void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
+void Parser::DistributeCLateParsedAttrs(Declarator &D, Decl *Dcl,
                                         LateParsedAttrList *LateAttrs) {
   if (!LateAttrs)
     return;
 
+  unsigned NestedLevel = 0;
+  for (unsigned i = 0; i < D.getNumTypeObjects(); ++i) {
+    DeclaratorChunk &DC = D.getTypeObject(i);
+
+    switch (DC.Kind) {
+    case DeclaratorChunk::Pointer:
+    case DeclaratorChunk::Array:
+      break;
+    default:
+      continue;
+    }
+
+    // Extract `LateParsedAttribute *` from `DeclaratorChunk`.
+    for (auto *OpaqueLA : DC.LateAttrList) {
+      auto *LA = static_cast<LateParsedAttribute *>(OpaqueLA);
+      LA->NestedTypeLevel = NestedLevel;
+      LateAttrs->push_back(LA);
+    }
+    NestedLevel++;
+  }
+
+  // Attach `Decl *` to each `LateParsedAttribute *`.
   if (Dcl) {
-    for (auto *LateAttr : *LateAttrs) {
-      if (LateAttr->Decls.empty())
-        LateAttr->addDecl(Dcl);
+    for (auto *LA : *LateAttrs) {
+      if (LA->Decls.empty())
+        LA->addDecl(Dcl);
     }
   }
 }
@@ -3217,12 +3243,6 @@ void Parser::ParseBoundsAttribute(IdentifierInfo 
&AttrName,
   ArgExprs.push_back(ArgExpr.get());
   Parens.consumeClose();
 
-  ASTContext &Ctx = Actions.getASTContext();
-
-  ArgExprs.push_back(IntegerLiteral::Create(
-      Ctx, llvm::APInt(Ctx.getTypeSize(Ctx.getSizeType()), 0),
-      Ctx.getSizeType(), SourceLocation()));
-
   Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),
                AttributeScopeInfo(), ArgExprs.data(), ArgExprs.size(), Form);
 }
@@ -4706,7 +4726,8 @@ void Parser::ParseStructDeclaration(
   MaybeParseCXX11Attributes(Attrs);
 
   // Parse the common specifier-qualifiers-list piece.
-  ParseSpecifierQualifierList(DS);
+  ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_normal,
+                              LateFieldAttrs);
 
   // If there are no declarators, this is a free-standing declaration
   // specifier. Let the actions module cope with it.
@@ -4768,7 +4789,7 @@ void Parser::ParseStructDeclaration(
     // We're done with this declarator;  invoke the callback.
     Decl *Field = FieldsCallback(DeclaratorInfo);
     if (Field)
-      DistributeCLateParsedAttrs(Field, LateFieldAttrs);
+      DistributeCLateParsedAttrs(DeclaratorInfo.D, Field, LateFieldAttrs);
 
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
@@ -4825,7 +4846,8 @@ void Parser::ParseLexedCAttribute(LateParsedAttribute 
&LA, bool EnterScope,
                         SourceLocation(), ParsedAttr::Form::GNU(), nullptr);
 
   for (auto *D : LA.Decls)
-    Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs);
+    Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs,
+                                        LA.NestedTypeLevel);
 
   // Due to a parsing error, we either went over the cached tokens or
   // there are still cached tokens left, so we skip the leftover tokens.
@@ -6124,7 +6146,8 @@ bool Parser::isConstructorDeclarator(bool IsUnqualified, 
bool DeductionGuide,
 
 void Parser::ParseTypeQualifierListOpt(
     DeclSpec &DS, unsigned AttrReqs, bool AtomicOrPtrauthAllowed,
-    bool IdentifierRequired, llvm::function_ref<void()> CodeCompletionHandler) 
{
+    bool IdentifierRequired, llvm::function_ref<void()> CodeCompletionHandler,
+    LateParsedAttrList *LateAttrs) {
   if ((AttrReqs & AR_CXX11AttributesParsed) &&
       isAllowedCXX11AttributeSpecifier()) {
     ParsedAttributes Attrs(AttrFactory);
@@ -6266,7 +6289,9 @@ void Parser::ParseTypeQualifierListOpt(
       // recovery is graceful.
       if (AttrReqs & AR_GNUAttributesParsed ||
           AttrReqs & AR_GNUAttributesParsedAndRejected) {
-        ParseGNUAttributes(DS.getAttributes());
+
+        assert(!LateAttrs || LateAttrs->lateAttrParseExperimentalExtOnly());
+        ParseGNUAttributes(DS.getAttributes(), LateAttrs);
         continue; // do *not* consume the next token!
       }
       // otherwise, FALL THROUGH!
@@ -6447,21 +6472,33 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
                     ((D.getContext() != DeclaratorContext::CXXNew)
                          ? AR_GNUAttributesParsed
                          : AR_GNUAttributesParsedAndRejected);
+    LateParsedAttrList LateAttrs(/*PSoon=*/true,
+                                 /*LateAttrParseExperimentalExtOnly=*/true);
     ParseTypeQualifierListOpt(DS, Reqs, /*AtomicOrPtrauthAllowed=*/true,
-                              !D.mayOmitIdentifier());
+                              !D.mayOmitIdentifier(), {}, &LateAttrs);
     D.ExtendWithDeclSpec(DS);
 
     // Recursively parse the declarator.
     Actions.runWithSufficientStackSpace(
         D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); 
});
-    if (Kind == tok::star)
+    if (Kind == tok::star) {
+      DeclaratorChunk::LateAttrListTy OpaqueLateAttrList;
+      if (getLangOpts().ExperimentalLateParseAttributes && !LateAttrs.empty()) 
{
+        if (!D.isFunctionDeclarator()) {
+          for (auto LA : LateAttrs) {
+            OpaqueLateAttrList.push_back(LA);
+          }
+        }
+        LateAttrs.clear();
+      }
       // Remember that we parsed a pointer type, and remember the type-quals.
       D.AddTypeInfo(DeclaratorChunk::getPointer(
                         DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),
                         DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),
                         DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),
-                    std::move(DS.getAttributes()), SourceLocation());
-    else
+                    std::move(DS.getAttributes()), SourceLocation(),
+                    OpaqueLateAttrList);
+    } else
       // Remember that we parsed a Block type, and remember the type-quals.
       D.AddTypeInfo(
           DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),
diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp 
b/clang/lib/Sema/SemaBoundsSafety.cpp
index 39ab13653f5fe..8411eec7dfb3f 100644
--- a/clang/lib/Sema/SemaBoundsSafety.cpp
+++ b/clang/lib/Sema/SemaBoundsSafety.cpp
@@ -50,8 +50,8 @@ enum class CountedByInvalidPointeeTypeKind {
   VALID,
 };
 
-bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
-                                     bool OrNull) {
+bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, unsigned Level,
+                                     bool CountInBytes, bool OrNull) {
   // Check the context the attribute is used in
 
   unsigned Kind = getCountAttrKind(CountInBytes, OrNull);
@@ -62,6 +62,12 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, 
bool CountInBytes,
     return true;
   }
 
+  if (Level != 0) {
+    Diag(FD->getBeginLoc(), diag::err_counted_by_on_nested_pointer)
+        << Kind << FD->getSourceRange();
+    return true;
+  }
+
   const auto FieldTy = FD->getType();
   if (FieldTy->isArrayType() && (CountInBytes || OrNull)) {
     Diag(FD->getBeginLoc(),
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fc3aabf5741ca..85e75d4e4b91a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16873,11 +16873,13 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt 
*Body, bool IsInstantiation,
 /// When we finish delayed parsing of an attribute, we must attach it to the
 /// relevant Decl.
 void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
-                                       ParsedAttributes &Attrs) {
+                                       ParsedAttributes &Attrs,
+                                       unsigned NestedTypeLevel) {
   // Always attach attributes to the underlying decl.
   if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
     D = TD->getTemplatedDecl();
-  ProcessDeclAttributeList(S, D, Attrs);
+  ProcessDeclAttributeList(S, D, Attrs, ProcessDeclAttributeOptions(),
+                           NestedTypeLevel);
   ProcessAPINotes(D);
 
   if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a9e7b44ac9d73..2369180713ffb 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6546,7 +6546,8 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, 
const ParsedAttr &AL) {
   D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL));
 }
 
-static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL,
+                                     unsigned Level) {
   auto *FD = dyn_cast<FieldDecl>(D);
   assert(FD);
 
@@ -6577,7 +6578,7 @@ static void handleCountedByAttrField(Sema &S, Decl *D, 
const ParsedAttr &AL) {
     llvm_unreachable("unexpected counted_by family attribute");
   }
 
-  if (S.CheckCountedByAttrOnField(FD, CountExpr, CountInBytes, OrNull))
+  if (S.CheckCountedByAttrOnField(FD, CountExpr, Level, CountInBytes, OrNull))
     return;
 
   QualType CAT = S.BuildCountAttributedArrayOrPointerType(
@@ -6951,7 +6952,8 @@ static bool MustDelayAttributeArguments(const ParsedAttr 
&AL) {
 /// silently ignore it if a GNU attribute.
 static void
 ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
-                     const Sema::ProcessDeclAttributeOptions &Options) {
+                     const Sema::ProcessDeclAttributeOptions &Options,
+                     unsigned NestedTypeLevel = 0) {
   if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
     return;
 
@@ -7578,7 +7580,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 
const ParsedAttr &AL,
   case ParsedAttr::AT_CountedByOrNull:
   case ParsedAttr::AT_SizedBy:
   case ParsedAttr::AT_SizedByOrNull:
-    handleCountedByAttrField(S, D, AL);
+    handleCountedByAttrField(S, D, AL, NestedTypeLevel);
     break;
 
   // Microsoft attributes:
@@ -7855,14 +7857,15 @@ static bool isKernelDecl(Decl *D) {
          D->hasAttr<CUDAGlobalAttr>();
 }
 
-void Sema::ProcessDeclAttributeList(
-    Scope *S, Decl *D, const ParsedAttributesView &AttrList,
-    const ProcessDeclAttributeOptions &Options) {
+void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
+                                    const ParsedAttributesView &AttrList,
+                                    const ProcessDeclAttributeOptions &Options,
+                                    unsigned NestedTypeLevel) {
   if (AttrList.empty())
     return;
 
   for (const ParsedAttr &AL : AttrList)
-    ProcessDeclAttribute(*this, S, D, AL, Options);
+    ProcessDeclAttribute(*this, S, D, AL, Options, NestedTypeLevel);
 
   // FIXME: We should be able to handle these cases in TableGen.
   // GCC accepts
@@ -8171,11 +8174,22 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, 
const Declarator &PD) {
   // position to the decl itself.  This handles cases like:
   //   int *__attr__(x)** D;
   // when X is a decl attribute.
+  unsigned NestedTypeLevel = 0;
   for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) {
     ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(),
                              ProcessDeclAttributeOptions()
                                  .WithIncludeCXX11Attributes(false)
-                                 .WithIgnoreTypeAttributes(true));
+                                 .WithIgnoreTypeAttributes(true),
+                             NestedTypeLevel);
+
+    switch (PD.getTypeObject(i).Kind) {
+    case DeclaratorChunk::Pointer:
+    case ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/166491
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to