From 40b1970e7ca7c2e30f5abf72944d86a29aa8c546 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Thu, 15 Aug 2024 16:33:04 -0700 Subject: [PATCH] [Cherry-pick][BoundsSafety][Sema] Allow counted_by and counted_by_or_null on pointers where the pointee type is incomplete but potentially completable --- This is a cherry-pick of the change in https://github.com/llvm/llvm-project/pull/106321. It is being cherry-pick now so that the merge conflict is handled upfront to minimize the work when the conflict from the upstream change reaches the automerger. Conflicts: clang/include/clang/AST/Type.h clang/include/clang/Sema/Sema.h clang/lib/AST/Type.cpp clang/lib/Sema/SemaBoundsSafety.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaInit.cpp --- Previously using the `counted_by` or `counted_by_or_null` attribute on a pointer with an incomplete pointee type was forbidden. Unfortunately this prevented a situation like the following from being allowed. Header file: ``` struct EltTy; // Incomplete type struct Buffer { size_t count; struct EltTy* __counted_by(count) buffer; // error before this patch }; ``` Implementation file: ``` struct EltTy { // definition }; void allocBuffer(struct Buffer* b) { b->buffer = malloc(sizeof(EltTy)* b->count); } ``` To allow code like the above but still enforce that the pointee type size is known in locations where `-fbounds-safety` needs to emit bounds checks the following scheme is used. * For incomplete pointee types that can never be completed (e.g. `void`) these are treated as error where the attribute is written (just like before this patch). * For incomplete pointee types that might be completable later on (struct, union, and enum forward declarations) in the translation unit, writing the attribute on the incomplete pointee type is allowed on the FieldDecl declaration but "uses" of the declared pointer are forbidden if at the point of "use" the pointee type is still incomplete. For this patch a "use" of a FieldDecl covers: * Explicit and Implicit initialization (note see **Tentative Definition Initialization** for an exception to this) * Assignment * Conversion to an lvalue (e.g. for use in an expression) In the swift lang fork of Clang the `counted_by` and `counted_by_or_null` attribute are allowed in many more contexts. That isn't the case for upstream Clang so the "use" checks for the attribute on VarDecl, ParamVarDecl, and function return type have been omitted from this patch because they can't be tested. However, the `BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy` and `BoundsSafetyCheckUseOfCountAttrPtrWithIncompletePointeeTy` functions retain the ability to emit diagnostics for these other contexts to avoid unnecessary divergence between upstream Clang and Apple's internal fork. Support for checking "uses" will be upstreamed when upstream Clang allows the `counted_by` and `counted_by_or_null` attribute in additional contexts. This patch has a few limitations: ** 1. Tentative Defition Initialization ** This patch currently allows something like: ``` struct IncompleteTy; struct Buffer { int count; struct IncompleteTy* __counted_by(count) buf; }; // Tentative definition struct Buffer GlobalBuf; ``` The Tentative definition in this example becomes an actual definition whose initialization **should be checked** but it currently isn't. Addressing this problem will be done in a subseqent patch. ** 2. When the incomplete pointee type is a typedef diagnostics are slightly misleading ** For this situation: ``` struct IncompleteTy; typedef struct IncompleteTy Incomplete_t; struct Buffer { int count; struct IncompleteTy* __counted_by(count) buf; }; void use(struct Buffer b) { b.buf = 0x0; } ``` This code emits `note: forward declaration of 'Incomplete_t' (aka 'struct IncompleteTy')` but the location is on the `struct IncompleteTy;` forward declaration. This is misleading because `Incomplete_t` isn't actually forward declared there (instead the underlying type is). This could be resolved by additional diagnostics that walk the chain of typedefs and explain each step of the walk. However, that would be very verbose and didn't seem like a direction worth pursuing. rdar://133600117 --- clang/include/clang/AST/Type.h | 10 +- .../clang/Basic/DiagnosticSemaKinds.td | 27 +- clang/include/clang/Sema/Sema.h | 40 +- clang/lib/AST/Type.cpp | 40 +- clang/lib/Sema/SemaBoundsSafety.cpp | 333 ++++----- clang/lib/Sema/SemaDeclAttr.cpp | 4 +- clang/lib/Sema/SemaExpr.cpp | 12 +- clang/lib/Sema/SemaInit.cpp | 32 +- ...nted_by_type_incomplete_completable_enum.c | 6 +- ...ed_by_type_incomplete_completable_struct.c | 702 +++++++++--------- ...ype_incomplete_completable_struct_blocks.c | 26 +- ...mplete_completable_struct_tentative_defs.c | 74 +- ...ounted_by_type_unknown_completable_union.c | 6 +- ...urce-location-for-counted-attribute-type.c | 32 +- .../attr-counted-by-late-parsed-struct-ptrs.c | 5 +- .../Sema/attr-counted-by-or-null-last-field.c | 4 +- ...unted-by-or-null-late-parsed-struct-ptrs.c | 5 +- ...ruct-ptrs-completable-incomplete-pointee.c | 631 ++++++++++++++++ .../attr-counted-by-or-null-struct-ptrs.c | 12 +- ...ruct-ptrs-completable-incomplete-pointee.c | 630 ++++++++++++++++ clang/test/Sema/attr-counted-by-struct-ptrs.c | 12 +- clang/test/Sema/attr-counted-by-vla.c | 3 +- 22 files changed, 1945 insertions(+), 701 deletions(-) create mode 100644 clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c create mode 100644 clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 99a0d204861e0..5ef12b8ece422 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2479,6 +2479,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isIncompleteOrSizelessType() const { return isIncompleteType() || isSizelessType() || isFunctionType(); } + /* TO_UPSTREAM(BoundsSafety) OFF*/ /// \returns True if the type is incomplete and it is also a type that /// cannot be completed by a later type definition. @@ -2495,11 +2496,10 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { /// // This decl has type 'char[]' which is incomplete and cannot be later /// // completed by another by another type declaration. /// extern char foo[]; - /// // This decl how has complete type 'char[5]'. + /// // This decl now has complete type 'char[5]'. /// char foo[5]; // foo has a complete type /// \endcode - bool isIncompletableIncompleteType() const; - /* TO_UPSTREAM(BoundsSafety) OFF*/ + bool isAlwaysIncompleteType() const; /// Determine whether this type is an object type. bool isObjectType() const { @@ -3690,9 +3690,7 @@ class CountAttributedType final return T->getTypeClass() == CountAttributed; } - /* TO_UPSTREAM(BoundsSafety) ON*/ - StringRef GetAttributeName(bool WithMacroPrefix) const; - /* TO_UPSTREAM(BoundsSafety) OFF*/ + StringRef getAttributeName(bool WithMacroPrefix) const; }; /* TO_UPSTREAM(BoundsSafety) ON */ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b30f330ecb2c1..7da0fb6b854f4 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6790,6 +6790,30 @@ def err_counted_by_attr_pointee_unknown_size : Error< "%select{|. This will be an error in a future compiler version}3" "" "}2">; +def err_counted_by_on_incomplete_type_on_assign : Error < + "cannot %select{" + "assign to %select{object|'%1'}2 with|" // AA_Assigning, + "pass argument to %select{parameter|parameter '%1'}2 with|" // AA_Passing, + "return|" // AA_Returning, + "convert to|" // AA_Converting (UNUSED) + "%select{|implicitly }3initialize %select{object|'%1'}2 with|" // AA_Initializing, + "pass argument to parameter with|" // AA_Sending (UNUSED) + "cast to|" // AA_Casting (UNUSED) + "pass argument to parameter with" // AA_Passing_CFAudited (UNUSED) + "}0 '%5' attributed type %4 because the pointee type %6 is incomplete">; + +def err_counted_by_on_incomplete_type_on_use : Error < + "cannot %select{" + "use '%1' with '%4' attributed|" // Generic expr + "call '%1' with '%4' attributed return" // CallExpr + "}0 type %2 because the pointee type %3 is incomplete">; + +def note_counted_by_consider_completing_pointee_ty : Note< + "consider providing a complete definition for %0">; + +def note_counted_by_consider_using_sized_by : Note< + "consider using '__sized_by%select{|_or_null}0' instead of " + "'__counted_by%select{|_or_null}0'">; def warn_counted_by_attr_elt_type_unknown_size : Warning, @@ -12895,8 +12919,7 @@ def err_bounds_safety_counted_by_on_incomplete_type_on_func_def : Error< " '%3'" // named parameter "}2 with" "}1 type %4 on a function definition because the pointee type %5 is " - "incomplete; consider providing a complete definition for %5 before the " - "function body or using the '__sized_by%select{|_or_null}6' attribute" + "incomplete" >; def err_bounds_safety_counted_by_on_incomplete_type_on_var_decl : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e8ea9e7c93976..20769de41c6f5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2263,7 +2263,6 @@ class Sema final : public SemaBase { bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, bool OrNull); - /* TO_UPSTREAM(BoundsSafety) ON*/ /// Perform Bounds Safety Semantic checks for assigning to a `__counted_by` or /// `__counted_by_or_null` pointer type \param LHSTy. /// @@ -2285,28 +2284,6 @@ class Sema final : public SemaBase { SourceLocation Loc, const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName); - /// Perform Checks for assigning to a `__counted_by` or - /// `__counted_by_or_null` pointer type \param LHSTy where the pointee type - /// is incomplete which is invalid. - /// - /// \param LHSTy The type being assigned to. Checks will only be performed if - /// the type is a `counted_by` or `counted_by_or_null ` pointer. - /// \param RHSExpr The expression being assigned from. - /// \param Action The type assignment being performed - /// \param Loc The SourceLocation to use for error diagnostics - /// \param Assignee The ValueDecl being assigned. This is used to compute - /// the name of the assignee. If the assignee isn't known this can - /// be set to nullptr. - /// \param ShowFullyQualifiedAssigneeName If set to true when using \p - /// Assignee to compute the name of the assignee use the fully - /// qualified name, otherwise use the unqualified name. - /// - /// \returns True iff no diagnostic where emitted, false otherwise. - bool BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy( - QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, - SourceLocation Loc, const ValueDecl *Assignee, - bool ShowFullyQualifiedAssigneeName); - /// Perform Bounds Safety Semantic checks for initializing a Bounds Safety /// pointer. /// @@ -2323,6 +2300,15 @@ class Sema final : public SemaBase { AssignmentAction Action, QualType LHSType, Expr *RHSExpr); + /// Perform Bounds Safety semantic checks for uses of invalid uses counted_by + /// or counted_by_or_null pointers in \param E. + /// + /// \param E the expression to check + /// + /// \returns True iff no diagnostic where emitted, false otherwise. + bool BoundsSafetyCheckUseOfCountAttrPtr(const Expr *E); + + /* TO_UPSTREAM(BoundsSafety) ON*/ /// Perform Bounds Safety semantic checks on function parameters on a function /// definition. This only performs checks that can be made by looking at /// \param PVD in isolation (i.e. not looking at other parameters in the @@ -2351,14 +2337,6 @@ class Sema final : public SemaBase { /// \returns True iff no diagnostic where emitted, false otherwise. bool BoundsSafetyCheckReturnTyForFunctionDef(FunctionDecl *FD); - /// Perform Bounds Safety semantic checks for uses of invalid uses counted_by - /// or counted_by_or_null pointers in \param E. - /// - /// \param E the expression to check - /// - /// \returns True iff no diagnostic where emitted, false otherwise. - bool BoundsSafetyCheckUseOfCountAttrPtr(Expr *E); - /// Perform Bounds Safety semantic checks on variable declaration \param VD. /// /// \param VD The VarDecl to check diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index e4dfd989ab2e7..5aaf444110d53 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2591,6 +2591,22 @@ bool Type::isIncompleteType(NamedDecl **Def) const { } } +bool Type::isAlwaysIncompleteType() const { + if (!isIncompleteType()) + return false; + + // Forward declarations of structs, classes, enums, and unions could be later + // completed in a compilation unit by providing a type definition. + if (getAsTagDecl()) + return false; + + // Other types are incompletable. + // + // E.g. `char[]` and `void`. The type is incomplete and no future + // type declarations can make the type complete. + return true; +} + bool Type::isSizelessBuiltinType() const { if (isSizelessVectorType()) return true; @@ -2708,22 +2724,6 @@ bool Type::isSizeMeaningless() const { return true; return false; } - -bool Type::isIncompletableIncompleteType() const { - if (!isIncompleteType()) - return false; - - // Forward declarations of structs, classes, enums, and unions could be later - // completed in a compilation unit by providing a definition. - if (isStructureOrClassType() || isEnumeralType() || isUnionType()) - return false; - - // Other types are incompletable. - // - // E.g. `char[]` and `void`. The type is incomplete and no future - // type declarations can make the type complete. - return true; -} /* TO_UPSTREAM(BoundsSafety) OFF*/ QualType Type::getSizelessVectorEltType(const ASTContext &Ctx) const { @@ -4072,8 +4072,11 @@ CountAttributedType::CountAttributedType( DeclSlot[i] = CoupledDecls[i]; } -/* TO_UPSTREAM(BoundsSafety) ON*/ -StringRef CountAttributedType::GetAttributeName(bool WithMacroPrefix) const { +StringRef CountAttributedType::getAttributeName(bool WithMacroPrefix) const { +// TODO: This method isn't really ideal because it doesn't return the spelling +// of the attribute that was used in the user's code. This method is used for +// diagnostics so the fact it doesn't use the spelling of the attribute in +// the user's code could be confusing (#113585). #define ENUMERATE_ATTRS(PREFIX) \ do { \ if (isCountInBytes()) { \ @@ -4094,6 +4097,7 @@ StringRef CountAttributedType::GetAttributeName(bool WithMacroPrefix) const { #undef ENUMERATE_ATTRS } +/* TO_UPSTREAM(BoundsSafety) ON*/ DynamicRangePointerType::DynamicRangePointerType( QualType PointerTy, QualType CanPointerTy, Expr *StartPtr, Expr *EndPtr, ArrayRef StartPtrDecls, diff --git a/clang/lib/Sema/SemaBoundsSafety.cpp b/clang/lib/Sema/SemaBoundsSafety.cpp index 403829cd723bb..b343cc8e3ba44 100644 --- a/clang/lib/Sema/SemaBoundsSafety.cpp +++ b/clang/lib/Sema/SemaBoundsSafety.cpp @@ -154,7 +154,36 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, // only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable // when `FieldTy->isArrayType()`. bool ShouldWarn = false; - if (PointeeTy->isIncompleteType() && !CountInBytes) { + if (PointeeTy->isAlwaysIncompleteType() && !CountInBytes) { + // In general using `counted_by` or `counted_by_or_null` on + // pointers where the pointee is an incomplete type are problematic. This is + // because it isn't possible to compute the pointer's bounds without knowing + // the pointee type size. At the same time it is common to forward declare + // types in header files. + // + // E.g.: + // + // struct Handle; + // struct Wrapper { + // size_t size; + // struct Handle* __counted_by(count) handles; + // } + // + // To allow the above code pattern but still prevent the pointee type from + // being incomplete in places where bounds checks are needed the following + // scheme is used: + // + // * When the pointee type might not always be an incomplete type (i.e. + // a type that is currently incomplete but might be completed later + // on in the translation unit) the attribute is allowed by this method + // but later uses of the FieldDecl are checked that the pointee type + // is complete see `BoundsSafetyCheckAssignmentToCountAttrPtr`, + // `BoundsSafetyCheckInitialization`, and + // `BoundsSafetyCheckUseOfCountAttrPtr` + // + // * When the pointee type is always an incomplete type (e.g. + // `void`) the attribute is disallowed by this method because we know the + // type can never be completed so there's no reason to allow it. InvalidTypeKind = CountedByInvalidPointeeTypeKind::INCOMPLETE; } else if (PointeeTy->isSizelessType()) { InvalidTypeKind = CountedByInvalidPointeeTypeKind::SIZELESS; @@ -313,7 +342,7 @@ static SourceRange SourceRangeFor(const CountAttributedType *CATy, Sema &S) { // Special case: When the character is part of a macro the Token we get // is the whole macro name (e.g. `__counted_by`). if (LastAttrCharToken.getRawIdentifier() != - CATy->GetAttributeName(/*WithMacroPrefix=*/true)) + CATy->getAttributeName(/*WithMacroPrefix=*/true)) return Fallback; // Found the beginning of the `__counted_by` macro @@ -344,7 +373,7 @@ static SourceRange SourceRangeFor(const CountAttributedType *CATy, Sema &S) { // +1 is for `(` const ssize_t NonAffixedSkipCount = - CATy->GetAttributeName(/*WithMacroPrefix=*/false).size() + 1; + CATy->getAttributeName(/*WithMacroPrefix=*/false).size() + 1; auto MaybeNonAffixedBeginToken = FetchIdentifierTokenFromOffset(-NonAffixedSkipCount); if (!MaybeNonAffixedBeginToken) @@ -352,7 +381,7 @@ static SourceRange SourceRangeFor(const CountAttributedType *CATy, Sema &S) { auto NonAffixedBeginToken = MaybeNonAffixedBeginToken.value(); if (NonAffixedBeginToken.getRawIdentifier() == - CATy->GetAttributeName(/*WithMacroPrefix=*/false)) { + CATy->getAttributeName(/*WithMacroPrefix=*/false)) { // Found the beginning of the `counted_by`-like attribute auto SL = NonAffixedBeginToken.getLocation(); @@ -371,13 +400,13 @@ static SourceRange SourceRangeFor(const CountAttributedType *CATy, Sema &S) { // | | // ---------------- std::string AffixedTokenStr = - (llvm::Twine("__") + CATy->GetAttributeName(/*WithMacroPrefix=*/false) + + (llvm::Twine("__") + CATy->getAttributeName(/*WithMacroPrefix=*/false) + llvm::Twine("__")) .str(); // +1 is for `(` // +4 is for the 4 `_` characters const ssize_t AffixedSkipCount = - CATy->GetAttributeName(/*WithMacroPrefix=*/false).size() + 1 + 4; + CATy->getAttributeName(/*WithMacroPrefix=*/false).size() + 1 + 4; auto MaybeAffixedBeginToken = FetchIdentifierTokenFromOffset(-AffixedSkipCount); if (!MaybeAffixedBeginToken) @@ -396,90 +425,99 @@ static SourceRange SourceRangeFor(const CountAttributedType *CATy, Sema &S) { return SourceRange(SL, MaybeRParenTok->getLocation()); } +/* TO_UPSTREAM(BoundsSafety) OFF*/ static void EmitIncompleteCountedByPointeeNotes(Sema &S, const CountAttributedType *CATy, - NamedDecl *IncompleteTyDecl, - bool NoteAttrLocation = true) { + NamedDecl *IncompleteTyDecl) { assert(IncompleteTyDecl == nullptr || isa(IncompleteTyDecl)); - if (NoteAttrLocation) { - // Note where the attribute is declared - auto AttrSrcRange = SourceRangeFor(CATy, S); - S.Diag(AttrSrcRange.getBegin(), diag::note_named_attribute) - << CATy->GetAttributeName(/*WithMacroPrefix=*/true) << AttrSrcRange; + if (IncompleteTyDecl) { + // Suggest completing the pointee type if its a named typed (i.e. + // IncompleteTyDecl isn't nullptr). Suggest this first as it is more likely + // to be the correct fix. + // + // Note the `IncompleteTyDecl` type is the underlying type which might not + // be the same as `CATy->getPointeeType()` which could be a typedef. + // + // The diagnostic printed will be at the location of the underlying type but + // the diagnostic text will print the type of `CATy->getPointeeType()` which + // could be a typedef name rather than the underlying type. This is ok + // though because the diagnostic will print the underlying type name too. + S.Diag(IncompleteTyDecl->getBeginLoc(), + diag::note_counted_by_consider_completing_pointee_ty) + << CATy->getPointeeType(); } - if (!IncompleteTyDecl) - return; - - // If there's an associated forward declaration display it to emphasize - // why the type is incomplete (all we have is a forward declaration). - - // Note the `IncompleteTyDecl` type is the underlying type which might not - // be the same as `CATy->getPointeeType()` which could be a typedef. + // Suggest using __sized_by(_or_null) instead of __counted_by(_or_null) as + // __sized_by(_or_null) doesn't have the complete type restriction. // - // The diagnostic printed will be at the location of the underlying type but - // the diagnostic text will print the type of `CATy->getPointeeType()` which - // could be a typedef name rather than the underlying type. This is ok - // though because the diagnostic will print the underlying type name too. - // E.g: + // We use the source range of the expression on the CountAttributedType as an + // approximation for the source range of the attribute. This isn't quite right + // but isn't easy to fix right now. // - // `forward declaration of 'Incomplete_Struct_t' - // (aka 'struct IncompleteStructTy')` + // TODO: Implement logic to find the relevant TypeLoc for the attribute and + // get the SourceRange from that (#113582). // - // If this ends up being confusing we could emit a second diagnostic (one - // explaining where the typedef is) but that seems overly verbose. + // TODO: We should emit a fix-it here. - S.Diag(IncompleteTyDecl->getBeginLoc(), diag::note_forward_declaration) - << CATy->getPointeeType(); + /* TO_UPSTREAM(BoundsSafety) ON*/ + // TODO: Upstream probably won't accept `SourceRangeFor` so we should consider + // removing it and its related tests. + // SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange(); + SourceRange AttrSrcRange = SourceRangeFor(CATy, S); + /* TO_UPSTREAM(BoundsSafety) OFF*/ + S.Diag(AttrSrcRange.getBegin(), diag::note_counted_by_consider_using_sized_by) + << CATy->isOrNull() << AttrSrcRange; } -static bool -HasCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND, - const CountAttributedType **CATyOut, - QualType *PointeeTyOut) { +static std::tuple +GetCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND) { auto *CATy = Ty->getAs(); - if (!CATy) - return false; - // Incomplete pointee type is only a problem for // counted_by/counted_by_or_null - if (CATy->isCountInBytes()) - return false; + if (!CATy || CATy->isCountInBytes()) + return {}; auto PointeeTy = CATy->getPointeeType(); - if (PointeeTy.isNull()) - return false; // Reachable? + if (PointeeTy.isNull()) { + // Reachable if `CountAttributedType` wraps an IncompleteArrayType + return {}; + } if (!PointeeTy->isIncompleteType(ND)) - return false; + return {}; - if (CATyOut) - *CATyOut = CATy; - if (PointeeTyOut) - *PointeeTyOut = PointeeTy; - return true; + return {CATy, PointeeTy}; } -bool Sema::BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy( - QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, SourceLocation Loc, - const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName) { +/// Perform Checks for assigning to a `__counted_by` or +/// `__counted_by_or_null` pointer type \param LHSTy where the pointee type +/// is incomplete which is invalid. +/// +/// \param S The Sema instance. +/// \param LHSTy The type being assigned to. Checks will only be performed if +/// the type is a `counted_by` or `counted_by_or_null ` pointer. +/// \param RHSExpr The expression being assigned from. +/// \param Action The type assignment being performed +/// \param Loc The SourceLocation to use for error diagnostics +/// \param Assignee The ValueDecl being assigned. This is used to compute +/// the name of the assignee. If the assignee isn't known this can +/// be set to nullptr. +/// \param ShowFullyQualifiedAssigneeName If set to true when using \p +/// Assignee to compute the name of the assignee use the fully +/// qualified name, otherwise use the unqualified name. +/// +/// \returns True iff no diagnostic where emitted, false otherwise. +static bool CheckAssignmentToCountAttrPtrWithIncompletePointeeTy( + Sema &S, QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, + SourceLocation Loc, const ValueDecl *Assignee, + bool ShowFullyQualifiedAssigneeName) { NamedDecl *IncompleteTyDecl = nullptr; - const CountAttributedType *CATy = nullptr; - QualType PointeeTy; - if (!HasCountedByAttrOnIncompletePointee(LHSTy, &IncompleteTyDecl, &CATy, - &PointeeTy)) + auto [CATy, PointeeTy] = + GetCountedByAttrOnIncompletePointee(LHSTy, &IncompleteTyDecl); + if (!CATy) return true; - assert(CATy && !CATy->isCountInBytes() && !PointeeTy.isNull()); - - // It's not expected that the diagnostic be emitted in these cases. - // It's not necessarily a problem but we should catch when this starts - // to happen. - assert(Action != AssignmentAction::Converting && - Action != AssignmentAction::Sending && - Action != AssignmentAction::Casting && - Action != AssignmentAction::Passing_CFAudited); std::string AssigneeStr; if (Assignee) { @@ -489,123 +527,90 @@ bool Sema::BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy( AssigneeStr = Assignee->getNameAsString(); } } - { - auto D = - Diag(Loc, - diag::err_bounds_safety_counted_by_on_incomplete_type_on_assign) - << /*0*/ (int)Action << /*1*/ AssigneeStr - << /*2*/ (AssigneeStr.size() > 0) - << /*3*/ isa(RHSExpr) << /*4*/ LHSTy - << /*5*/ CATy->GetAttributeName(/*WithMacroPrefix=*/true) - << /*6*/ PointeeTy << /*7*/ CATy->isOrNull(); - - if (RHSExpr->getSourceRange().isValid()) - D << RHSExpr->getSourceRange(); - } - EmitIncompleteCountedByPointeeNotes(*this, CATy, IncompleteTyDecl); + S.Diag(Loc, diag::err_counted_by_on_incomplete_type_on_assign) + << static_cast(Action) << AssigneeStr << (AssigneeStr.size() > 0) + << isa(RHSExpr) << LHSTy + << CATy->getAttributeName(/*WithMacroPrefix=*/true) << PointeeTy + << CATy->isOrNull() << RHSExpr->getSourceRange(); + + EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl); return false; // check failed } bool Sema::BoundsSafetyCheckAssignmentToCountAttrPtr( QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, SourceLocation Loc, const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName) { - if (!getLangOpts().hasBoundsSafety()) - return true; - - return BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy( - LHSTy, RHSExpr, Action, Loc, Assignee, ShowFullyQualifiedAssigneeName); + return CheckAssignmentToCountAttrPtrWithIncompletePointeeTy( + *this, LHSTy, RHSExpr, Action, Loc, Assignee, + ShowFullyQualifiedAssigneeName); } bool Sema::BoundsSafetyCheckInitialization(const InitializedEntity &Entity, const InitializationKind &Kind, AssignmentAction Action, QualType LHSType, Expr *RHSExpr) { - if (!getLangOpts().hasBoundsSafety()) - return true; - - bool ChecksPassed = true; auto SL = Kind.getLocation(); // Note: We don't call `BoundsSafetyCheckAssignmentToCountAttrPtr` here - // because we need conditionalize what is checked. - - // counted_by/counted_by_or_null on incomplete pointee type check. - // - // We skip Variable initializers because we should have already complained - // about those variables in `Sema::BoundsSafetyCheckVarDecl()`. + // because we need conditionalize what is checked. In downstream + // Clang `counted_by` is supported on variable definitions and in that + // implementation an error diagnostic will be emitted on the variable + // definition if the pointee is an incomplete type. To avoid warning about the + // same problem twice (once when the variable is defined, once when Sema + // checks the initializer) we skip checking the initializer if it's a + // variable. if (Action == AssignmentAction::Initializing && Entity.getKind() != InitializedEntity::EK_Variable) { - if (!BoundsSafetyCheckAssignmentToCountAttrPtrWithIncompletePointeeTy( - LHSType, RHSExpr, Action, SL, + if (!CheckAssignmentToCountAttrPtrWithIncompletePointeeTy( + *this, LHSType, RHSExpr, Action, SL, dyn_cast_or_null(Entity.getDecl()), /*ShowFullQualifiedAssigneeName=*/true)) { - - ChecksPassed = false; - - // It's not necessarily bad if this assert fails but we should catch - // if this happens. - assert(Entity.getKind() == InitializedEntity::EK_Member); + return false; } } - return ChecksPassed; + return true; } -static bool BoundsSafetyCheckUseOfCountAttrPtrWithIncompletePointeeTy(Sema &S, - Expr *E) { +bool Sema::BoundsSafetyCheckUseOfCountAttrPtr(const Expr *E) { QualType T = E->getType(); - assert(T->isPointerType()); + if (!T->isPointerType()) + return true; + + NamedDecl *IncompleteTyDecl = nullptr; + auto [CATy, PointeeTy] = + GetCountedByAttrOnIncompletePointee(T, &IncompleteTyDecl); + if (!CATy) + return true; // Generate a string for the diagnostic that describes the "use". // The string is specialized for direct calls to produce a better // diagnostic. - StringRef DirectCallFn; - std::string UseStr; + SmallString<64> UseStr; + bool IsDirectCall = false; if (const auto *CE = dyn_cast(E->IgnoreParens())) { if (const auto *FD = CE->getDirectCallee()) { - DirectCallFn = FD->getName(); + UseStr = FD->getName(); + IsDirectCall = true; } } - int SelectExprKind = DirectCallFn.size() > 0 ? 1 : 0; - if (SelectExprKind) { - UseStr = DirectCallFn; - } else { - llvm::raw_string_ostream SS(UseStr); - E->printPretty(SS, nullptr, PrintingPolicy(S.getPrintingPolicy())); - } - assert(UseStr.size() > 0); - const CountAttributedType *CATy = nullptr; - QualType PointeeTy; - NamedDecl *IncompleteTyDecl = nullptr; - if (!HasCountedByAttrOnIncompletePointee(T, &IncompleteTyDecl, &CATy, - &PointeeTy)) - return true; - assert(CATy && !CATy->isCountInBytes() && !PointeeTy.isNull()); + if (!IsDirectCall) { + llvm::raw_svector_ostream SS(UseStr); + E->printPretty(SS, nullptr, getPrintingPolicy()); + } - S.Diag(E->getBeginLoc(), - diag::err_bounds_safety_counted_by_on_incomplete_type_on_use) - << /*0*/ SelectExprKind << /*1*/ UseStr << /*2*/ T << /*3*/ PointeeTy - << /*4*/ CATy->GetAttributeName(/*WithMacroPrefix=*/true) - << /*5*/ CATy->isOrNull() << E->getSourceRange(); + Diag(E->getBeginLoc(), diag::err_counted_by_on_incomplete_type_on_use) + << IsDirectCall << UseStr << T << PointeeTy + << CATy->getAttributeName(/*WithMacroPrefix=*/true) << CATy->isOrNull() + << E->getSourceRange(); - EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl); + EmitIncompleteCountedByPointeeNotes(*this, CATy, IncompleteTyDecl); return false; } -bool Sema::BoundsSafetyCheckUseOfCountAttrPtr(Expr *E) { - if (!getLangOpts().hasBoundsSafety()) - return true; - - QualType T = E->getType(); - if (!T->isPointerType()) - return true; - - return BoundsSafetyCheckUseOfCountAttrPtrWithIncompletePointeeTy(*this, E); -} - bool Sema::BoundsSafetyCheckResolvedCall(FunctionDecl *FDecl, CallExpr *Call, const FunctionProtoType *ProtoType) { if (!getLangOpts().hasBoundsSafety()) @@ -655,13 +660,11 @@ bool Sema::BoundsSafetyCheckResolvedCall(FunctionDecl *FDecl, CallExpr *Call, static bool BoundsSafetyCheckFunctionParamOrCountAttrWithIncompletePointeeTy( Sema &S, QualType Ty, const ParmVarDecl *ParamDecl) { - const CountAttributedType *CATy = nullptr; - QualType PointeeTy; NamedDecl *IncompleteTyDecl = nullptr; - if (!HasCountedByAttrOnIncompletePointee(Ty, &IncompleteTyDecl, &CATy, - &PointeeTy)) + auto [CATy, PointeeTy] = + GetCountedByAttrOnIncompletePointee(Ty, &IncompleteTyDecl); + if (!CATy) return true; - // Emit Diagnostic StringRef ParamName; if (ParamDecl) @@ -670,13 +673,11 @@ static bool BoundsSafetyCheckFunctionParamOrCountAttrWithIncompletePointeeTy( auto SR = SourceRangeFor(CATy, S); S.Diag(SR.getBegin(), diag::err_bounds_safety_counted_by_on_incomplete_type_on_func_def) - << /*0*/ CATy->GetAttributeName(/*WithMacroPrefix*/ true) + << /*0*/ CATy->getAttributeName(/*WithMacroPrefix*/ true) << /*1*/ (ParamDecl ? 1 : 0) << /*2*/ (ParamName.size() > 0) - << /*3*/ ParamName << /*4*/ Ty << /*5*/ PointeeTy - << /*6*/ CATy->isOrNull() << SR; + << /*3*/ ParamName << /*4*/ Ty << /*5*/ PointeeTy << SR; - EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl, - /*NoteAttrLocation=*/false); + EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl); return false; } @@ -699,24 +700,22 @@ bool Sema::BoundsSafetyCheckReturnTyForFunctionDef(FunctionDecl *FD) { static bool BoundsSafetyCheckVarDeclCountAttrPtrWithIncompletePointeeTy(Sema &S, const VarDecl *VD) { - const CountAttributedType *CATy = nullptr; - QualType PointeeTy; NamedDecl *IncompleteTyDecl = nullptr; - if (!HasCountedByAttrOnIncompletePointee(VD->getType(), &IncompleteTyDecl, - &CATy, &PointeeTy)) + auto [CATy, PointeeTy] = + GetCountedByAttrOnIncompletePointee(VD->getType(), &IncompleteTyDecl); + if (!CATy) return true; SourceRange SR = SourceRangeFor(CATy, S); S.Diag(SR.getBegin(), diag::err_bounds_safety_counted_by_on_incomplete_type_on_var_decl) - << /*0*/ CATy->GetAttributeName(/*WithMacroPrefix=*/true) + << /*0*/ CATy->getAttributeName(/*WithMacroPrefix=*/true) << /*1*/ (VD->isThisDeclarationADefinition() == VarDecl::TentativeDefinition) << /*2*/ VD->getName() << /*3*/ VD->getType() << /*4*/ PointeeTy << /*5*/ CATy->isOrNull() << SR; - EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl, - /*NoteAttrLocation=*/false); + EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl); return false; } @@ -755,12 +754,12 @@ bool Sema::BoundsSafetyCheckCountAttributedTypeHasConstantCountForAssignmentOp( unsigned DiagID = 0; if (IsUnaryOp) { SelectOp = std::get(OpInfo); - DiagID = - diag::warn_bounds_safety_count_attr_pointer_unary_arithmetic_constant_count; + DiagID = diag:: + warn_bounds_safety_count_attr_pointer_unary_arithmetic_constant_count; } else { // Binary operator - DiagID = - diag::warn_bounds_safety_count_attr_pointer_binary_assign_constant_count; + DiagID = diag:: + warn_bounds_safety_count_attr_pointer_binary_assign_constant_count; switch (std::get(OpInfo)) { case BO_AddAssign: // += SelectOp = 1; @@ -783,13 +782,13 @@ bool Sema::BoundsSafetyCheckCountAttributedTypeHasConstantCountForAssignmentOp( // Count is constant Diag(Operand->getExprLoc(), DiagID) << /*0*/ SelectOp << - /*1*/ CATTy->GetAttributeName(/*WithMacroPrefix=*/true) << + /*1*/ CATTy->getAttributeName(/*WithMacroPrefix=*/true) << /*2*/ (CATTy->isCountInBytes() ? 1 : 0) << /*3*/ 0 /* integer constant count*/ << /*4*/ Result.Val.getAsString(getASTContext(), CATTy->getCountExpr()->getType()); Diag(CATTy->getCountExpr()->getExprLoc(), diag::note_named_attribute) - << CATTy->GetAttributeName(/*WithMacroPrefix=*/true); + << CATTy->getAttributeName(/*WithMacroPrefix=*/true); return false; } if (const auto *DRE = @@ -801,18 +800,16 @@ bool Sema::BoundsSafetyCheckCountAttributedTypeHasConstantCountForAssignmentOp( Diag(Operand->getExprLoc(), DiagID) << /*0*/ SelectOp << - /*1*/ CATTy->GetAttributeName(/*WithMacroPrefix=*/true) << + /*1*/ CATTy->getAttributeName(/*WithMacroPrefix=*/true) << /*2*/ (CATTy->isCountInBytes() ? 1 : 0) << /*3*/ 1 /* const qualified declref*/ << /*4*/ VD; Diag(CATTy->getCountExpr()->getExprLoc(), diag::note_named_attribute) - << CATTy->GetAttributeName(/*WithMacroPrefix=*/true); + << CATTy->getAttributeName(/*WithMacroPrefix=*/true); return false; } } - return true; } -/* TO_UPSTREAM(BoundsSafety) OFF*/ } // namespace clang diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 2fb0f70a6c880..8baff1e4957de 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6194,8 +6194,8 @@ class ConstructCountAttributedType : // see `HasCountedByAttrOnIncompletePointee()`. This allows the counted_by // attribute to be used on code that prefers to keep its pointees // incomplete until they need to be used. - if (PointeeTy->isIncompletableIncompleteType() || - PointeeTy->isFunctionType() || PointeeTy->isSizelessType() || + if (PointeeTy->isAlwaysIncompleteType() || PointeeTy->isFunctionType() || + PointeeTy->isSizelessType() || PointeeTy->isStructureTypeWithFlexibleArrayMember()) { // Use unspecified pointer attributes for diagnostic purposes. QualType Unsp = S.Context.getBoundsSafetyPointerType( diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 43bd1d12971d6..0be5dad33624a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1086,6 +1086,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E, if (!Count.get()) return ExprError(); + // FIXME: Hoist this out of if-else blocks if (!BoundsSafetyCheckUseOfCountAttrPtr(Res.get())) return ExprError(); @@ -1140,6 +1141,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E, Res = MaterializeSequenceExpr::Create(Context, Res.get(), OpaqueValues, true); } return Res; + } else { + if (!BoundsSafetyCheckUseOfCountAttrPtr(Res.get())) + return ExprError(); } /* TO_UPSTREAM(BoundsSafety) OFF*/ @@ -16841,7 +16845,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : CompoundType; -/* TO_UPSTREAM(BoundsSafety) ON*/ + /* TO_UPSTREAM(BoundsSafety) ON*/ if (getLangOpts().BoundsSafety) { auto *RecordTy = RHSType->getAs(); if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) { @@ -16853,8 +16857,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, // recovery by continuing as if this worked } } + /* TO_UPSTREAM(BoundsSafety) OFF */ - if (getLangOpts().hasBoundsSafety() && RHS.isUsable()) { + if (RHS.isUsable()) { // Even if this check fails don't return early to allow the best // possible error recovery and to allow any subsequent diagnostics to // work. @@ -16868,11 +16873,10 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, ShowFullyQualifiedAssigneeName = true; } - (void)BoundsSafetyCheckAssignmentToCountAttrPtr( + BoundsSafetyCheckAssignmentToCountAttrPtr( LHSType, RHS.get(), AssignmentAction::Assigning, Loc, Assignee, ShowFullyQualifiedAssigneeName); } -/* TO_UPSTREAM(BoundsSafety) OFF */ // OpenCL v1.2 s6.1.1.1 p2: // The half data type can only be used to declare a pointer to a buffer that diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 251d878f3743e..2f9273f09dd9d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8610,17 +8610,12 @@ ExprResult InitializationSequence::Perform(Sema &S, Kind.getRange().getEnd()); } else { CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type); - /* TO_UPSTREAM(BoundsSafety) ON*/ - // Note the return value isn't used to return early - // to preserve the AST as best as possible even though an error - // might have occurred. For struct initialization it also allows - // all field assignments to be checked rather than bailing on the - // first error. + // Note the return value isn't used to return a ExprError() when + // initialization fails . For struct initialization allows all field + // assignments to be checked rather than bailing on the first error. S.BoundsSafetyCheckInitialization(Entity, Kind, AssignmentAction::Initializing, - /*LHSType=*/Step->Type, - /*RHSExpr=*/CurInit.get()); - /* TO_UPSTREAM(BoundsSafety) OFF*/ + Step->Type, CurInit.get()); } break; } @@ -8721,6 +8716,13 @@ ExprResult InitializationSequence::Perform(Sema &S, } } + // Note the return value isn't used to return a ExprError() when + // initialization fails. For struct initialization this allows all field + // assignments to be checked rather than bailing on the first error. + S.BoundsSafetyCheckInitialization(Entity, Kind, + getAssignmentAction(Entity, true), + Step->Type, InitialCurInit.get()); + bool Complained; ValueDecl *Assignee = nullptr; /* TO_UPSTREAM(BoundsSafety) ON*/ @@ -8730,18 +8732,6 @@ ExprResult InitializationSequence::Perform(Sema &S, Assignee = Entity.getDecl(); } - // Note the return value isn't used to return early so that additional - // diagnostics can be emitted and to preserve the AST as best as possible - // even though an error might have occurred. For struct initialization it - // also allows all field assignments to be checked rather than bailing on - // the first error. - (void)S.BoundsSafetyCheckInitialization( - Entity, Kind, /*Action=*/getAssignmentAction(Entity, true), - /*LHSType=*/Step->Type, /*RHSExpr=*/InitialCurInit.get()); - - /* TO_UPSTREAM(BoundsSafety) OFF*/ - - /* TO_UPSTREAM(BoundsSafety) ON*/ // Upstream doesn't have `Assignee`. if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), Step->Type, SourceType, diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_enum.c b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_enum.c index 85d75ebf41a95..b56f461c9eb60 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_enum.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_enum.c @@ -5,15 +5,15 @@ // Test incomplete enums extern int external_enum_len; -typedef enum incomplete_enum incomplete_enum_t; // expected-note 2{{forward declaration of 'enum incomplete_enum'}} +typedef enum incomplete_enum incomplete_enum_t; // expected-note 2{{consider providing a complete definition for 'enum incomplete_enum'}} extern incomplete_enum_t* __counted_by(external_enum_len) incompleteEnumPtr; // OK extern enum incomplete_enum* __counted_by(external_enum_len) incompleteEnumPtr2; // OK int global_enum_len; // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBEnumPtrImplicitInit' with type 'enum incomplete_enum *__single __counted_by(global_enum_len)' (aka 'enum incomplete_enum *__single') because the pointee type 'enum incomplete_enum' is incomplete; consider providing a complete definition for 'enum incomplete_enum' before this definition or using the '__sized_by' attribute}} -enum incomplete_enum* __counted_by(global_enum_len) GlobalCBEnumPtrImplicitInit; +enum incomplete_enum* __counted_by(global_enum_len) GlobalCBEnumPtrImplicitInit; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONEnumPtrImplicitInit' with type 'enum incomplete_enum *__single __counted_by_or_null(global_enum_len)' (aka 'enum incomplete_enum *__single') because the pointee type 'enum incomplete_enum' is incomplete; consider providing a complete definition for 'enum incomplete_enum' before this definition or using the '__sized_by_or_null' attribute}} -enum incomplete_enum* __counted_by_or_null(global_enum_len) GlobalCBONEnumPtrImplicitInit; +enum incomplete_enum* __counted_by_or_null(global_enum_len) GlobalCBONEnumPtrImplicitInit; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // Unions are handled like structs for the diagnostics so the testing for structs diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c index 66904566d2ad0..4076f36f1f48b 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct.c @@ -12,8 +12,8 @@ // the typedef. This seems like the right behavior because the typedef isn't the // forward declaration, `struct IncompleteStructTy` is. // -// expected-note@+1 62{{forward declaration of 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy')}} -struct IncompleteStructTy; // expected-note 153{{forward declaration of 'struct IncompleteStructTy'}} +// expected-note@+1 62{{consider providing a complete definition for 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy')}} +struct IncompleteStructTy; // expected-note 153{{consider providing a complete definition for 'struct IncompleteStructTy'}} typedef struct IncompleteStructTy Incomplete_Struct_t; @@ -29,10 +29,10 @@ void no_consume_ok( // Using the attribute on parameters on a function **definition** is not allowed. void no_consume_ok( - // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(size) cb, - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(size) cbon, + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size) cb, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size) cbon, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int size) { } @@ -43,12 +43,12 @@ void no_consume_ok_unnamed_param( int size); // OK void no_consume_ok_unnamed_param( - // expected-error@+2{{cannot apply '__counted_by' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} + // expected-error@+2{{cannot apply '__counted_by' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} - struct IncompleteStructTy* __counted_by(size), - // expected-error@+2{{cannot apply '__counted_by_or_null' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} + struct IncompleteStructTy* __counted_by(size), // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+2{{cannot apply '__counted_by_or_null' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} - struct IncompleteStructTy* __counted_by_or_null(size), + struct IncompleteStructTy* __counted_by_or_null(size), // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int size) { } @@ -57,10 +57,10 @@ void consume_cb(struct IncompleteStructTy* __counted_by(size_cb), int size_cb); void consume_cbon(struct IncompleteStructTy* __counted_by_or_null(size_cbon), int size_cbon); void consume_param_read_write( - // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size_cb)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(size_cb) cb, - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size_cbon)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(size_cbon) cbon, + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'cb' with type 'struct IncompleteStructTy *__single __counted_by(size_cb)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size_cb) cb, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size_cbon)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size_cbon) cbon, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int size_cb, int size_cbon) { @@ -107,8 +107,8 @@ void no_consume_default_assign( // Attribute on parameters with nested attributes //------------------------------------------------------------------------------ void consume_param_nested( - struct IncompleteStructTy* __counted_by(size1)* cb, // expected-note 3{{__counted_by attribute is here}} - struct IncompleteStructTy* __counted_by_or_null(size2)* cbon, // expected-note 3{{__counted_by_or_null attribute is here}} + struct IncompleteStructTy* __counted_by(size1)* cb, // expected-note 3{{consider using '__sized_by' instead of '__counted_by'}} + struct IncompleteStructTy* __counted_by_or_null(size2)* cbon, // expected-note 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int size1, int size2) { // Surprisingly `&cb[0]` doesn't count as a use. @@ -117,13 +117,13 @@ void consume_param_nested( // expected-error@+1{{pointer with '__counted_by' cannot be pointed to by any other variable; exception is when the variable is passed as a compatible argument to a function}} local = cb; - // expected-error@+1{{cannot assign to object that has type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to object with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} *cb = 0x0; size1 = 0; - // expected-error@+1{{cannot use 'cb[0]' with type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'cb[0]' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} void* read_cb = cb[0]; - // expected-error@+1{{cannot use '*cb' with type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use '*cb' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_cb(*cb, size1); // expected-error@+1{{not allowed to change out parameter with dependent count}} @@ -134,13 +134,13 @@ void consume_param_nested( // expected-error@+1{{pointer with '__counted_by_or_null' cannot be pointed to by any other variable; exception is when the variable is passed as a compatible argument to a function}} local = cbon; - // expected-error@+1{{cannot assign to object that has type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to object with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} *cbon = 0x0; size2 = 0; - // expected-error@+1{{cannot use 'cbon[0]' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'cbon[0]' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} void* read_cbon = cbon[0]; - // expected-error@+1{{cannot use '*cbon' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use '*cbon' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size2)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_cbon(*cbon, size2); // expected-error@+1{{not allowed to change out parameter with dependent count}} @@ -151,42 +151,42 @@ void consume_param_nested( // Attribute on return type of called function //------------------------------------------------------------------------------ -// expected-note@+1{{__counted_by attribute is here}} +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} struct IncompleteStructTy* __counted_by(size) ret_cb_IncompleteStructTy(int size); // OK -// expected-note@+1{{__counted_by attribute is here}} +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} Incomplete_Struct_t* __counted_by(size) ret_cb_IncompleteStructTy_typedef(int size); // OK -// expected-note@+1{{__counted_by_or_null attribute is here}} +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} struct IncompleteStructTy* __counted_by_or_null(size) ret_cbon_IncompleteStructTy(int size); // OK -// expected-note@+1{{__counted_by_or_null attribute is here}} +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} Incomplete_Struct_t* __counted_by_or_null(size) ret_cbon_IncompleteStructTy_typedef(int size); // OK -// expected-note@+1{{__counted_by attribute is here}} +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} struct IncompleteStructTy* __counted_by(1) ret_cb_IncompleteStructTy_const_count_one(void); // OK -// expected-note@+1{{__counted_by attribute is here}} +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} Incomplete_Struct_t* __counted_by(1) ret_cb_IncompleteStructTy_typedef_const_count_one(void); // OK -// expected-note@+1{{__counted_by_or_null attribute is here}} +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} struct IncompleteStructTy* __counted_by_or_null(1) ret_cbon_IncompleteStructTy_const_count_one(void); // OK -// expected-note@+1{{__counted_by_or_null attribute is here}} +// expected-note@+1{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} Incomplete_Struct_t* __counted_by_or_null(1) ret_cbon_IncompleteStructTy_typedef_const_count_one(void); // OK void call_fn_returns_incomplete_pointee(void) { int size = 0; - // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy' with return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy' with '__counted_by' attributed return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} ret_cb_IncompleteStructTy(size); - // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef' with return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef' with '__counted_by' attributed return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} ret_cb_IncompleteStructTy_typedef(size); - // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy' with return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy' with '__counted_by_or_null' attributed return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} ret_cbon_IncompleteStructTy(size); - // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef' with return type 'Incomplete_Struct_t *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef' with '__counted_by_or_null' attributed return type 'Incomplete_Struct_t *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} ret_cbon_IncompleteStructTy_typedef(size); - // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_const_count_one' with return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_const_count_one' with '__counted_by' attributed return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} ret_cb_IncompleteStructTy_const_count_one(); - // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef_const_count_one' with return type 'Incomplete_Struct_t *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot call 'ret_cb_IncompleteStructTy_typedef_const_count_one' with '__counted_by' attributed return type 'Incomplete_Struct_t *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} ret_cb_IncompleteStructTy_typedef_const_count_one(); - // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_const_count_one' with return type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_const_count_one' with '__counted_by_or_null' attributed return type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} ret_cbon_IncompleteStructTy_const_count_one(); - // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef_const_count_one' with return type 'Incomplete_Struct_t *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot call 'ret_cbon_IncompleteStructTy_typedef_const_count_one' with '__counted_by_or_null' attributed return type 'Incomplete_Struct_t *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} ret_cbon_IncompleteStructTy_typedef_const_count_one(); } @@ -194,115 +194,115 @@ void call_fn_returns_incomplete_pointee(void) { // Attribute on return type in function declaration //------------------------------------------------------------------------------ -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb(int size) { - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_missing_return(int size) { // missing return statement } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(size) +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon_missing_return(int size) { // missing return statement } -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) // expected-note 2{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 3{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_multiple_returns(int size) { if (size == 0) - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon_multiple_returns(int size) { if (size == 0) - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(1) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(1) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_const_count_1(int size) { // rs-error@+2{{returning null from a function with result type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 always fails}} - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_single_forge(int size) { // rs-warning@+2{{count value is not statically known: returning 'struct IncompleteStructTy *__single' from a function with result type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') is invalid for any count other than 0 or 1}} - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return __unsafe_forge_single(struct IncompleteStructTy*, 0x0); } -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_single_forge_bidi(int size) { - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x0, 4); } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon(int size) { // TODO: We should consider allowing this because the assignment of nullptr // means the type size isn't needed (rdar://129424354). - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon_single_forge(int size) { // rs-warning@+2{{count value is not statically known: returning 'struct IncompleteStructTy *__single' from a function with result type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') is invalid for any count other than 0 or 1 unless the pointer is null}} - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return __unsafe_forge_single(struct IncompleteStructTy*, 0x0); } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon_single_forge_bidi(int size) { - // expected-error@+1{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x0, 4); } // Test typedef as the incomplete pointee type -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before the function body or using the '__sized_by' attribute}} -Incomplete_Struct_t* __counted_by(size) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_typedef(int size) { - // expected-error@+1{{cannot return type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} return 0x0; } // Check Incomplete type diagnostic and bad conversion diagnostics both emitted on return -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(size) // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(size) // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} consume_param_and_return_cb_bad_conversion(int size) { - // expected-error@+2{{cannot return type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot return '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{non-pointer to safe pointer conversion is not allowed with -fbounds-safety; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable'}} return 0x1; } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribut}} -struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(size) // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} consume_param_and_return_cbon_bad_conversion(int size) { - // expected-error@+2{{cannot return type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{non-pointer to safe pointer conversion is not allowed with -fbounds-safety; use '__unsafe_forge_single' or '__unsafe_forge_bidi_indexable'}} return 0x1; } @@ -310,52 +310,52 @@ struct IncompleteStructTy* __counted_by_or_null(size) // expected-note{{__counte //------------------------------------------------------------------------------ // Pass Arguments to parameters with attribute. //------------------------------------------------------------------------------ -void consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{__counted_by attribute is here}} -void consume_incomplete_cb_unnamed(struct IncompleteStructTy* __counted_by(size), int size); // expected-note{{__counted_by attribute is here}} -typedef void consume_incomplete_cb_t(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{__counted_by attribute is here}} +void consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_incomplete_cb_unnamed(struct IncompleteStructTy* __counted_by(size), int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +typedef void consume_incomplete_cb_t(struct IncompleteStructTy* __counted_by(size) c, int size); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} void call_consume_incomplete_cb(consume_incomplete_cb_t indirect_call) { - // expected-error@+1{{cannot pass argument to parameter 'c' that has type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb_unnamed(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); } -void consume_incomplete_cb_const_count_1(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{__counted_by attribute is here}} -void consume_incomplete_cb_unnamed_const_count_1(struct IncompleteStructTy* __counted_by(1)); // expected-note{{__counted_by attribute is here}} -typedef void consume_incomplete_cb_const_count_1_t(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{__counted_by attribute is here}} +void consume_incomplete_cb_const_count_1(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_incomplete_cb_unnamed_const_count_1(struct IncompleteStructTy* __counted_by(1)); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +typedef void consume_incomplete_cb_const_count_1_t(struct IncompleteStructTy* __counted_by(1) c); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} void call_consume_incomplete_cb_const_count_1(consume_incomplete_cb_const_count_1_t indirect_call) { - // expected-error@+1{{cannot pass argument to parameter 'c' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb_const_count_1(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb_unnamed_const_count_1(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4)); } -void consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{__counted_by_or_null attribute is here}} -void consume_incomplete_cbon_unnamed(struct IncompleteStructTy* __counted_by_or_null(size), int size); // expected-note{{__counted_by_or_null attribute is here}} -typedef void consume_incomplete_cbon_t(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{__counted_by_or_null attribute is here}} +void consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +void consume_incomplete_cbon_unnamed(struct IncompleteStructTy* __counted_by_or_null(size), int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +typedef void consume_incomplete_cbon_t(struct IncompleteStructTy* __counted_by_or_null(size) c, int size); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void call_consume_incomplete_cbon(consume_incomplete_cbon_t indirect_call) { - // expected-error@+1{{cannot pass argument to parameter 'c' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot pass argument to parameter 'c' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cbon(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cbon_unnamed(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); - // expected-error@+1{{cannot pass argument to parameter that has type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot pass argument to parameter with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} indirect_call(__unsafe_forge_single(struct IncompleteStructTy*, 0x4), 1); } -// expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} -void wrap_consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, +// expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +void wrap_consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, // expected-note{{consider using '__sized_by' instead of '__counted_by'}} int size, consume_incomplete_cb_t indirect_call) { // TODO: We should consider allowing this case. rdar://132031085 // @@ -375,8 +375,8 @@ void wrap_consume_incomplete_cb(struct IncompleteStructTy* __counted_by(size) c, indirect_call(c, size); } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} -void wrap_consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'c' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} +void wrap_consume_incomplete_cbon(struct IncompleteStructTy* __counted_by_or_null(size) c, // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int size, consume_incomplete_cbon_t indirect_call) { // TODO: We should consider allowing this case. rdar://132031085 // @@ -473,8 +473,8 @@ struct BuffersCBTyNotUsed { struct BuffersCBTy { int count; int count_typedef; - struct IncompleteStructTy* __counted_by(count) buffer; // expected-note 21{{__counted_by attribute is here}} - Incomplete_Struct_t* __counted_by(count_typedef) buffer_typedef; // expected-note 21{{__counted_by attribute is here}} + struct IncompleteStructTy* __counted_by(count) buffer; // expected-note 21{{consider using '__sized_by' instead of '__counted_by'}} + Incomplete_Struct_t* __counted_by(count_typedef) buffer_typedef; // expected-note 21{{consider using '__sized_by' instead of '__counted_by'}} }; void side_effect(void); @@ -482,33 +482,33 @@ void side_effect(void); void AssignToBuffersCBTy(struct BuffersCBTy* b) { // Check that the diagnostic about missing assignment to the count also shows - // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') 'b->buffer' requires corresponding assignment to 'b->count'; add self assignment 'b->count = b->count' if the value has not changed}} b->buffer = 0x0; side_effect(); - // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot assign to 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-error@+1{{assignment to 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') 'b->buffer_typedef' requires corresponding assignment to 'b->count_typedef'; add self assignment 'b->count_typedef = b->count_typedef' if the value has not changed}} b->buffer_typedef = 0x0; // Diagnostic about missing assignment to count should not appear. side_effect(); b->count = 0; - // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} b->buffer = 0x0; side_effect(); - // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} b->buffer_typedef = 0x0; b->count_typedef = 0; } struct IncompleteStructTy* ReturnBufferCBTyMember(struct BuffersCBTy* b) { - // expected-error@+1{{cannot use 'b->buffer' with type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'b->buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return b->buffer; } Incomplete_Struct_t* ReturnBufferCBTyMemberTypeDef(struct BuffersCBTy* b) { - // expected-error@+1{{cannot use 'b->buffer_typedef' with type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'b->buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} return b->buffer_typedef; } @@ -520,39 +520,39 @@ struct BuffersCBONTyNotUsed { struct BuffersCBONTy { int count; int count_typedef; - struct IncompleteStructTy* __counted_by_or_null(count) buffer; // expected-note 21{{__counted_by_or_null attribute is here}} - Incomplete_Struct_t* __counted_by_or_null(count_typedef) buffer_typedef; // expected-note 21{{__counted_by_or_null attribute is here}} + struct IncompleteStructTy* __counted_by_or_null(count) buffer; // expected-note 21{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + Incomplete_Struct_t* __counted_by_or_null(count_typedef) buffer_typedef; // expected-note 21{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} }; void AssignToBuffersCBONTy(struct BuffersCBONTy* b) { // Check that the diagnostic about missing assignment to the count also shows - // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') 'b->buffer' requires corresponding assignment to 'b->count'; add self assignment 'b->count = b->count' if the value has not changed}} b->buffer = 0x0; side_effect(); - // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot assign to 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-error@+1{{assignment to 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') 'b->buffer_typedef' requires corresponding assignment to 'b->count_typedef'; add self assignment 'b->count_typedef = b->count_typedef' if the value has not changed}} b->buffer_typedef = 0x0; // Diagnostic about missing assignment to count should not appear. side_effect(); b->count = 0; - // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} b->buffer = 0x0; side_effect(); - // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} b->buffer_typedef = 0x0; b->count_typedef = 0; } struct IncompleteStructTy* ReturnBufferCBONTyMember(struct BuffersCBONTy* b) { - // expected-error@+1{{cannot use 'b->buffer' with type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'b->buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} return b->buffer; } Incomplete_Struct_t* ReturnBufferCBONTyMemberTypeDef(struct BuffersCBONTy* b) { - // expected-error@+1{{cannot use 'b->buffer_typedef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'b->buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} return b->buffer_typedef; } @@ -565,17 +565,17 @@ Incomplete_Struct_t* ReturnBufferCBONTyMemberTypeDef(struct BuffersCBONTy* b) { struct BufferCBNonZeroConstCountTy { int extra_field; - struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 4{{__counted_by attribute is here}} + struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 4{{consider using '__sized_by' instead of '__counted_by'}} }; struct BufferCBNonZeroConstCountFlippedFieldOrderTy { - struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 2{{__counted_by attribute is here}} + struct IncompleteStructTy* __counted_by(1) ptr; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} int extra_field; }; struct BufferCBNonZeroDynCountTy { unsigned int count; - struct IncompleteStructTy* __counted_by(count+1) ptr; // expected-note 5{{__counted_by attribute is here}} + struct IncompleteStructTy* __counted_by(count+1) ptr; // expected-note 5{{consider using '__sized_by' instead of '__counted_by'}} }; union BufferCBOrOther { @@ -588,17 +588,17 @@ void InitBuffersCBTy(int size) { struct BuffersCBTy desig_init_0 = { .count = size, .count_typedef = size, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0x0 }; struct BuffersCBTy desig_init_1 = { // .count and .count_typedef not explicitly initialized but are implicitly zero initialized - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0x0 }; @@ -607,61 +607,61 @@ void InitBuffersCBTy(int size) { .count_typedef = size, // .buffer and .buffer_typedef are not explicit initialized but are implicitly zero initialized }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy implicit_all_zero_init = {0}; // Implicit field init - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // non-designated initializer struct BuffersCBTy non_design_init_0 = { 0, 0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0x0 }; struct BuffersCBTy non_design_init_1 = { 0, 0 }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy desig_init_invalid_count = { .count = 1, - // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'desig_init_invalid_count.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} .buffer = 0x0 }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy desig_init_invalid_count_partial = { .count = 1 }; // expected-error@-1{{implicitly initializing 'desig_init_invalid_count_partial.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy non_desig_init_invalid_count = { 1, 0, - // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'non_desig_init_invalid_count.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0x0 }; struct BuffersCBTy non_desig_init_invalid_count_partial = {1}; // expected-error@-1{{implicitly initializing 'non_desig_init_invalid_count_partial.buffer' of type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-3{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // Cases where zero-init would create an invalid count struct BufferCBNonZeroConstCountTy design_init_const_count = { - // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'design_init_const_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} .ptr = 0x0, .extra_field = 0 @@ -672,27 +672,27 @@ void InitBuffersCBTy(int size) { .extra_field = 0x0 }; // expected-error@-1{{implicitly initializing 'design_init_const_count_partial_explicit.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} struct BufferCBNonZeroConstCountTy implicit_all_zero_init_const_count = {0}; // expected-error@-1{{implicitly initializing 'implicit_all_zero_init_const_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // When the ptr comes first it's seen as an explicit assignment when we write ` = {0}` so we get the incomplete pointee type error diagnostic - // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'implicit_all_zero_init_const_count_ptr_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} struct BufferCBNonZeroConstCountFlippedFieldOrderTy implicit_all_zero_init_const_count_ptr_init = {0}; struct BufferCBNonZeroDynCountTy design_init_non_zero_dyn_count = { .count = 0x0, - // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'design_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} .ptr = 0x0 }; struct BufferCBNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init = { // count is implicitly zero - // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'design_init_non_zero_dyn_count_partial_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} .ptr = 0x0 }; @@ -702,15 +702,15 @@ void InitBuffersCBTy(int size) { .count = 0x0 }; // expected-error@-1{{implicitly initializing 'design_init_non_zero_dyn_count_partial_init2.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} struct BufferCBNonZeroDynCountTy implicit_all_zero_init_non_zero_dyn_count = {0}; // expected-error@-1{{implicitly initializing 'implicit_all_zero_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} - // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@-2{{cannot implicitly initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} struct BufferCBNonZeroDynCountTy non_desig_init_non_zero_dyn_count = { 0, - // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroDynCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'non_desig_init_non_zero_dyn_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(count + 1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} 0 }; @@ -718,33 +718,33 @@ void InitBuffersCBTy(int size) { // Struct inside a union union BufferCBOrOther UnionDesignInitOther = {.other = 0x0 }; union BufferCBOrOther UnionZeroInit = {0}; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} union BufferCBOrOther UnionDesignInitBufZeroInitStructFields = {.buf = {0}}; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} union BufferCBOrOther UnionDesignInitBufDesignInitStructFields = {.buf = {.count = 0, .buffer = 0x0}}; - // expected-error@-1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@-1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} } struct BuffersCBTy GlobalBuffersCBTy_design_init = { .count = 0, .count_typedef = 0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0 }; struct BuffersCBTy GlobalBuffersCBTy_non_design_init = { 0, 0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} 0, - // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0 }; @@ -753,28 +753,28 @@ struct BuffersCBTy GlobalBuffersCBTy_design_init_partial = { .count_typedef = 0 // buffer and buffer_typedef are implicitly zero initialized }; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy GlobalBuffersCBTy_non_design_init_partial = { 0, 0, // buffer and buffer_typedef are implicitly zero initialized }; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBTy GlobalBuffersCBTy_all_zero_init = {0}; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBTy::buffer' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBTy::buffer_typedef' with '__counted_by' attributed type 'Incomplete_Struct_t *__single __counted_by(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} -// expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} +// expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'GlobalBuffersCBTy_implicit_all_zero_init_const_count_ptr_init.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} struct BufferCBNonZeroConstCountFlippedFieldOrderTy GlobalBuffersCBTy_implicit_all_zero_init_const_count_ptr_init = {0}; struct BufferCBNonZeroConstCountTy GlobalBuffersCBTy_const_non_zero_count = { - // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBNonZeroConstCountTy::ptr' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'GlobalBuffersCBTy_const_non_zero_count.ptr' of type 'struct IncompleteStructTy *__single __counted_by(1)' (aka 'struct IncompleteStructTy *__single') and count value of 1 with null always fails}} .ptr = 0x0 }; @@ -789,17 +789,17 @@ union BufferCBONOrOther { struct BufferCBONNonZeroConstCountTy { int extra_field; - struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 4{{__counted_by_or_null attribute is here}} + struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 4{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} }; struct BufferCBONNonZeroConstCountFlippedFieldOrderTy { - struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 2{{__counted_by_or_null attribute is here}} + struct IncompleteStructTy* __counted_by_or_null(1) ptr; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int extra_field; }; struct BufferCBONNonZeroDynCountTy { unsigned int count; - struct IncompleteStructTy* __counted_by_or_null(count+1) ptr; // expected-note 5{{__counted_by_or_null attribute is here}} + struct IncompleteStructTy* __counted_by_or_null(count+1) ptr; // expected-note 5{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} }; void InitBuffersCBONTy(int size) { @@ -808,18 +808,18 @@ void InitBuffersCBONTy(int size) { struct BuffersCBONTy desig_init_0 = { .count = size, .count_typedef = size, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0x0 }; // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy desig_init_1 = { // .count and .count_typedef not explicitly initialized but are implicitly zero initialized - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0x0 }; @@ -829,66 +829,66 @@ void InitBuffersCBONTy(int size) { .count_typedef = size, // .buffer and .buffer_typedef are not explicit initialized but are implicitly zero initialized }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy implicit_all_zero_init = {0}; // Implicit field init - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // non-designated initializer // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy non_design_init_0 = { 0, 0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0x0 }; // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy non_design_init_1 = { 0, 0 }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // TODO: Explicit and implicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy desig_init_invalid_count = { .count = 1, - // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // .buffer = 0x0 }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy desig_init_explicit_non_zero_count_partial = { .count = 1 }; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy non_desig_init_invalid_count = { 1, 0, - // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0x0 }; // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BuffersCBONTy non_desig_init_non_zerocount_partial = {1}; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // Cases where zero-init would create an invalid count // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroConstCountTy design_init_const_count = { - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // .ptr = 0x0, .extra_field = 0 @@ -899,22 +899,22 @@ void InitBuffersCBONTy(int size) { // .ptr is implicitly zero initialized .extra_field = 0x0 }; - // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroConstCountTy implicit_all_zero_init_const_count = {0}; - // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 // When the ptr comes first it's seen as an explicit assignment when we write ` = {0}` so we get the incomplete pointee type error diagnostic - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // struct BufferCBONNonZeroConstCountFlippedFieldOrderTy implicit_all_zero_init_const_count_ptr_init = {0}; // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroDynCountTy design_init_non_zero_dyn_count = { .count = 0x0, - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // .ptr = 0x0 }; @@ -922,7 +922,7 @@ void InitBuffersCBONTy(int size) { // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroDynCountTy design_init_non_zero_dyn_count_partial_init = { // count is implicitly zero - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // .ptr = 0x0 }; @@ -932,16 +932,16 @@ void InitBuffersCBONTy(int size) { // ptr is implicitly zero initialized .count = 0x0 }; - // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // TODO: Implicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroDynCountTy implicit_all_zero_init_non_zero_dyn_count = {0}; - // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // TODO: Explicit 0x0 initialization should be allowed. rdar://129424354 struct BufferCBONNonZeroDynCountTy non_desig_init_non_zero_dyn_count = { 0, - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroDynCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count + 1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // 0 }; @@ -949,16 +949,16 @@ void InitBuffersCBONTy(int size) { // Struct inside a union union BufferCBONOrOther UnionDesignInitOther = {.other = 0x0 }; union BufferCBONOrOther UnionZeroInit = {0}; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} union BufferCBONOrOther UnionDesignInitBufZeroInitStructFields = {.buf = {0}}; - // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} union BufferCBONOrOther UnionDesignInitBufDesignInitStructFields = {.buf = {.count = 0, .buffer = 0x0}}; - // expected-error@-1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} - // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@-1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + // expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} } // XXX @@ -966,18 +966,18 @@ void InitBuffersCBONTy(int size) { struct BuffersCBONTy GlobalBuffersCBONTy_design_init = { .count = 0, .count_typedef = 0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} .buffer = 0x0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} .buffer_typedef = 0 }; struct BuffersCBONTy GlobalBuffersCBONTy_non_design_init = { 0, 0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} 0, - // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} 0 }; @@ -986,28 +986,28 @@ struct BuffersCBONTy GlobalBuffersCBONTy_design_init_partial = { .count_typedef = 0 // buffer and buffer_typedef are implicitly zero initialized }; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBONTy GlobalBuffersCBONTy_non_design_init_partial = { 0, 0, // buffer and buffer_typedef are implicitly zero initialized }; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} struct BuffersCBONTy GlobalBuffersCBONTy_all_zero_init = {0}; -// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} -// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' that has type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'Incomplete_Struct_t' or using the '__sized_by_or_null' attribute}} +// expected-error@-1{{cannot implicitly initialize 'BuffersCBONTy::buffer' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +// expected-error@-2{{cannot implicitly initialize 'BuffersCBONTy::buffer_typedef' with '__counted_by_or_null' attributed type 'Incomplete_Struct_t *__single __counted_by_or_null(count_typedef)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} -// expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} +// expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountFlippedFieldOrderTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // struct BufferCBONNonZeroConstCountFlippedFieldOrderTy GlobalBuffersCBONTy_implicit_all_zero_init_const_count_ptr_init = {0}; struct BufferCBONNonZeroConstCountTy GlobalBuffersCBONTy_const_non_zero_count = { - // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot initialize 'BufferCBONNonZeroConstCountTy::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(1)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // .ptr = 0x0 }; @@ -1018,65 +1018,65 @@ struct BufferCBONNonZeroConstCountTy GlobalBuffersCBONTy_const_non_zero_count = void local_cb_init_and_assign(int s) { int size = s; - // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(size) local_init = 0x0; + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(size) local_init = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} local_init = 0x0; int implicit_size = s; - // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(implicit_size) implicit_init; + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(implicit_size) implicit_init; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} implicit_init = 0x0; } void local_cb_init_and_assign_constant_count(void) { // Check we also emit diagnostics about assigning nullptr to `__counted_by(X)` where X > 0 // - // expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} + // expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'local_init' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} - struct IncompleteStructTy* __counted_by(5) local_init = 0x0; + struct IncompleteStructTy* __counted_by(5) local_init = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} local_init = 0x0; // Diagnostic suppressed because the VarDecl is invalid // There should be no diagnostic about assigning nullptr // TODO: We should consider allowing this given that the type size isn't // really needed when the count is 0 (rdar://129424147). - // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(0) local_init_zero = 0x0; + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(0) local_init_zero = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} local_init_zero = 0x0; // Diagnostic suppressed because the VarDecl is invalid - // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} - struct IncompleteStructTy* __counted_by(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // Diagnostic suppressed because the VarDecl is invalid } void local_cbon_init_and_assign(int s) { int size = s; - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(size) local_init = 0x0; + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(size) local_init = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} local_init = 0x0; int implicit_size = s; - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(implicit_size) implicit_init; + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'implicit_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(implicit_size)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(implicit_size) implicit_init; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} implicit_init = 0x0; } void local_cbon_init_and_assign_constant_count(void) { // TODO: We should consider allowing this because the assignment of nullptr // means the type size isn't needed (rdar://129424354). - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(5) local_init = 0x0; + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(5) local_init = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} local_init = 0x0; // Diagnostic suppressed because the VarDecl is invalid // There should be no diagnostic about assigning nullptr // TODO: We should consider allowing this given that the type size isn't // really needed when the count is 0 (rdar://129424147). - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(0) local_init_zero = 0x0; + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init_zero' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(0) local_init_zero = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} local_init_zero = 0x0; // Diagnostic suppressed because the VarDecl is invalid - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteStructTy* __counted_by_or_null(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local_init2' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} + struct IncompleteStructTy* __counted_by_or_null(5) local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} local_init2 = __unsafe_forge_bidi_indexable(struct IncompleteStructTy*, 0x4, 4); // Diagnostic suppressed because the VarDecl is invalid } @@ -1086,41 +1086,41 @@ void local_cbon_init_and_assign_constant_count(void) { // NOTE: Tentative definitions are mostly tested in `counted_by_type_incomplete_completable_struct_tentative_defs.c`. extern int external_count; -// expected-note@+1 3{{__counted_by attribute is here}} +// expected-note@+1 3{{consider using '__sized_by' instead of '__counted_by'}} extern struct IncompleteStructTy* __counted_by(external_count) GlobalCBPtrToIncompleteTy; // OK extern Incomplete_Struct_t* __counted_by(external_count) GlobalCBPtrToIncompleteTyTypeDef; // OK void use_GlobalCBPtrToIncompleteTy(void) { - // expected-error@+2{{cannot assign to 'GlobalCBPtrToIncompleteTy' that has type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot assign to 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBPtrToIncompleteTy' requires corresponding assignment to 'external_count'; add self assignment 'external_count = external_count' if the value has not changed}} GlobalCBPtrToIncompleteTy = 0x0; - // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} GlobalCBPtrToIncompleteTy[0] = 0; - // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'GlobalCBPtrToIncompleteTy' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(external_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb(GlobalCBPtrToIncompleteTy, external_count); } static int global_count; -// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -static struct IncompleteStructTy* __counted_by(global_count) GlobalCBPtrImplicitInit; // expected-note 3{{__counted_by attribute is here}} -// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} -static Incomplete_Struct_t* __counted_by(global_count) GlobalCBPtrImplicitInitTypeDef; +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +static struct IncompleteStructTy* __counted_by(global_count) GlobalCBPtrImplicitInit; // expected-note 4{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +static Incomplete_Struct_t* __counted_by(global_count) GlobalCBPtrImplicitInitTypeDef; // expected-note {{consider using '__sized_by' instead of '__counted_by'}} void use_GlobalCBPtrImplicitInit(void) { - // expected-error@+2{{cannot assign to 'GlobalCBPtrImplicitInit' that has type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+2{{cannot assign to 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBPtrImplicitInit' requires corresponding assignment to 'global_count'; add self assignment 'global_count = global_count' if the value has not changed}} GlobalCBPtrImplicitInit = 0x0; - // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} GlobalCBPtrImplicitInit[0] = 0; - // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'GlobalCBPtrImplicitInit' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(global_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cb(GlobalCBPtrImplicitInit, global_count); } int global_count_non_static = 0; -// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(global_count_non_static) GlobalCBPtrExplicitInit = 0x0; -// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} -Incomplete_Struct_t* __counted_by(global_count_non_static) GlobalCBPtrExplicitInitTypeDef = 0x0; +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(global_count_non_static) GlobalCBPtrExplicitInit = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(global_count_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(global_count_non_static) GlobalCBPtrExplicitInitTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} void use_GlobalCBPtrExplicitInit(void) { // No diagnostics because the VarDecl is marked as invalid at this point @@ -1132,36 +1132,36 @@ void use_GlobalCBPtrExplicitInit(void) { // This is very unidiomatic C but it seems to be legal. // expected-warning@+1{{'extern' variable has an initializer}} extern int global_count_extern = 0; -// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribut}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 -extern struct IncompleteStructTy* __counted_by(global_count_extern) GlobalCBPtrExplicitInitExtern = 0x0; -// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} +extern struct IncompleteStructTy* __counted_by(global_count_extern) GlobalCBPtrExplicitInitExtern = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by(global_count_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 -extern Incomplete_Struct_t* __counted_by(global_count_extern) GlobalCBPtrExplicitInitTypeDefExtern = 0x0; +extern Incomplete_Struct_t* __counted_by(global_count_extern) GlobalCBPtrExplicitInitTypeDefExtern = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // TODO: We should consider allowing this given that the pointee type size isn't // really needed when the count is 0 (rdar://129424147) -// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCount; -// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} -Incomplete_Struct_t* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCountTypeDef; -// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCount = 0x0; -// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} -Incomplete_Struct_t* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCountTypeDef = 0x0; - -// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCount; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(0) GlobalCBPtrImplicitInitConstantZeroCountTypeDef; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCount = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by(0) GlobalCBPtrExplicitInitConstantZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + +// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{implicitly initializing 'GlobalCBPtrImplicitInitConstantNonZeroCount' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} -struct IncompleteStructTy* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCount; -// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} +struct IncompleteStructTy* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCount; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-error@+1{{implicitly initializing 'GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef' of type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} -Incomplete_Struct_t* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef; -// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} +Incomplete_Struct_t* __counted_by(5) GlobalCBPtrImplicitInitConstantNonZeroCountTypeDef; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{initializing 'GlobalCBPtrExplicitInitConstantNonZeroCount' of type 'struct IncompleteStructTy *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} -struct IncompleteStructTy* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCount = 0x0; -// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} +struct IncompleteStructTy* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCount = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +// expected-error@+2{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-error@+1{{initializing 'GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef' of type 'Incomplete_Struct_t *__single __counted_by(5)' (aka 'struct IncompleteStructTy *__single') and count value of 5 with null always fails}} -Incomplete_Struct_t* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; +Incomplete_Struct_t* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} //------------------------------------------------------------------------------ // Global __counted_by_or_null variables @@ -1170,47 +1170,47 @@ Incomplete_Struct_t* __counted_by(5) GlobalCBPtrExplicitInitConstantNonZeroCount extern int external_count_cbon; extern int external_count_cbon_typedef; -// expected-note@+1 3{{__counted_by_or_null attribute is here}} +// expected-note@+1 3{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} extern struct IncompleteStructTy* __counted_by_or_null(external_count_cbon) GlobalCBONPtrToIncompleteTy; // OK extern Incomplete_Struct_t* __counted_by_or_null(external_count_cbon_typedef) GlobalCBONPtrToIncompleteTyTypeDef; // OK void use_GlobalCBONPtrToIncompleteTy(void) { - // expected-error@+2{{cannot assign to 'GlobalCBONPtrToIncompleteTy' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot assign to 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBONPtrToIncompleteTy' requires corresponding assignment to 'external_count_cbon'; add self assignment 'external_count_cbon = external_count_cbon' if the value has not changed}} GlobalCBONPtrToIncompleteTy = 0x0; - // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} GlobalCBONPtrToIncompleteTy[0] = 0; - // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'GlobalCBONPtrToIncompleteTy' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(external_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cbon(GlobalCBONPtrToIncompleteTy, external_count); } static int global_count_cbon; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -static struct IncompleteStructTy* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInit; // expected-note 3{{__counted_by_or_null attribute is here}} -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -static Incomplete_Struct_t* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInitTypeDef; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +static struct IncompleteStructTy* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInit; // expected-note 4{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +static Incomplete_Struct_t* __counted_by_or_null(global_count_cbon) GlobalCBONPtrImplicitInitTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_GlobalCBONPtrImplicitInit(void) { - // expected-error@+2{{cannot assign to 'GlobalCBONPtrImplicitInit' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot assign to 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-error@+1{{assignment to 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') 'GlobalCBONPtrImplicitInit' requires corresponding assignment to 'global_count_cbon'; add self assignment 'global_count_cbon = global_count_cbon' if the value has not changed}} GlobalCBONPtrImplicitInit = 0x0; - // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} GlobalCBONPtrImplicitInit[0] = 0; - // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'GlobalCBONPtrImplicitInit' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_incomplete_cbon(GlobalCBONPtrImplicitInit, global_count_cbon); } int global_count_cbon_non_static = 0; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInit = 0x0; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInitTypeDef = 0x0; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInit' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInit = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_non_static)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_non_static) GlobalCBONPtrExplicitInitTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_GlobalCBONPtrExplicitInit(void) { // No diagnostics because the VarDecl is marked as invalid at this point @@ -1224,51 +1224,51 @@ void use_GlobalCBONPtrExplicitInit(void) { // This is very unidiomatic C but it seems to be legal. // expected-warning@+1{{'extern' variable has an initializer}} extern int global_count_cbon_extern = 0; -// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} +// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitExtern' with type 'struct IncompleteStructTy *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 -extern struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitExtern = 0x0; -// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribut}} +extern struct IncompleteStructTy* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitExtern = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+2{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitTypeDefExtern' with type 'Incomplete_Struct_t *__single __counted_by_or_null(global_count_cbon_extern)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} // expected-warning@+1 2{{'extern' variable has an initializer}} TODO: This shouldn't be emitted twice. rdar://133001618 -extern Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitTypeDefExtern = 0x0; +extern Incomplete_Struct_t* __counted_by_or_null(global_count_cbon_extern) GlobalCBONPtrExplicitInitTypeDefExtern = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // TODO: We should consider allowing this given that the pointee type size isn't // really needed when the count is 0 (rdar://129424147) -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribut}} -struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCount; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCountTypeDef; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCount = 0x0; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCountTypeDef = 0x0; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCount; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrImplicitInitConstantZeroCountTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCount = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(0) GlobalCBONPtrExplicitInitConstantZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // Unlike `__counted_by` assigning 0x0 (implicitly or explicitly) is allowed for `__counted_by_or_null` -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCount; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCount = 0x0; -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCount; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrImplicitInitConstantNonZeroCountTypeDef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCount' with type 'struct IncompleteStructTy *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} +struct IncompleteStructTy* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCount = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(5)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete}} +Incomplete_Struct_t* __counted_by_or_null(5) GlobalCBONPtrExplicitInitConstantNonZeroCountTypeDef = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} //------------------------------------------------------------------------------ // No explicit forward decl //------------------------------------------------------------------------------ -// expected-note@+1 2{{forward declaration of 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl')}} +// expected-note@+1 2{{consider providing a complete definition for 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl')}} typedef struct NoExplicitForwardDecl NoExplicitForwardDecl_t; -extern NoExplicitForwardDecl_t* __counted_by(0) NoExplicitForwardDeclGlobalCBPtr; // expected-note{{__counted_by attribute is here}} +extern NoExplicitForwardDecl_t* __counted_by(0) NoExplicitForwardDeclGlobalCBPtr; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} void consume_NoExplicitForwardDeclGlobalCBPtr(void) { - // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBPtr' that has type 'NoExplicitForwardDecl_t *__single __counted_by(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'NoExplicitForwardDecl_t' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBPtr' with '__counted_by' attributed type 'NoExplicitForwardDecl_t *__single __counted_by(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete}} NoExplicitForwardDeclGlobalCBPtr = 0x0; } -extern NoExplicitForwardDecl_t* __counted_by_or_null(0) NoExplicitForwardDeclGlobalCBONPtr; // expected-note{{__counted_by_or_null attribute is here}} +extern NoExplicitForwardDecl_t* __counted_by_or_null(0) NoExplicitForwardDeclGlobalCBONPtr; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void consume_NoExplicitForwardDeclGlobalCBONPtr(void) { - // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBONPtr' that has type 'NoExplicitForwardDecl_t *__single __counted_by_or_null(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'NoExplicitForwardDecl_t' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'NoExplicitForwardDeclGlobalCBONPtr' with '__counted_by_or_null' attributed type 'NoExplicitForwardDecl_t *__single __counted_by_or_null(0)' (aka 'struct NoExplicitForwardDecl *__single') because the pointee type 'NoExplicitForwardDecl_t' (aka 'struct NoExplicitForwardDecl') is incomplete}} NoExplicitForwardDeclGlobalCBONPtr = 0x0; } @@ -1322,84 +1322,84 @@ void explicit_cast_cbon_to_bidi(struct IncompleteStructTy* p) { // Completing the pointee type allows usage //------------------------------------------------------------------------------ -// expected-note@+1 20{{forward declaration of 'struct IncompleteLaterCompletedStructTy'}} +// expected-note@+1 20{{consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy'}} struct IncompleteLaterCompletedStructTy; // Confirm using the type is an error at this point -// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrExpectErr = 0x0; -struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrTentativeDefUseWillErr; // expected-note{{__counted_by attribute is here}} +// expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'GlobalCBPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrExpectErr = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) GlobalCBPtrTentativeDefUseWillErr; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrExpectErr = 0x0; -struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrTentativeDefUseWillErr; // expected-note{{__counted_by_or_null attribute is here}} +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'GlobalCBONPtrExpectErr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrExpectErr = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) GlobalCBONPtrTentativeDefUseWillErr; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} struct StructPtrIncompleteLaterCompleted { int count; - struct IncompleteLaterCompletedStructTy*__counted_by(count) ptr; // expected-note 2{{__counted_by attribute is here}} + struct IncompleteLaterCompletedStructTy*__counted_by(count) ptr; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} }; struct StructCBONPtrIncompleteLaterCompleted { int count; - struct IncompleteLaterCompletedStructTy*__counted_by_or_null(count) ptr; // expected-note 2{{__counted_by_or_null attribute is here}} + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(count) ptr; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} }; -void consume_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by(0) p); // expected-note{{__counted_by attribute is here}} -void consume_CBON_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) p); // expected-note{{__counted_by_or_null attribute is here}} +void consume_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by(0) p); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +void consume_CBON_IncompleteLaterCompletedStructTy(struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) p); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} -struct IncompleteLaterCompletedStructTy*__counted_by(0) ret_IncompleteLaterCompletedStructTy(void); // expected-note{{__counted_by attribute is here}} -struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) ret_CBON_IncompleteLaterCompletedStructTy(void); // expected-note{{__counted_by_or_null attribute is here}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) ret_IncompleteLaterCompletedStructTy(void); // expected-note{{consider using '__sized_by' instead of '__counted_by'}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) ret_CBON_IncompleteLaterCompletedStructTy(void); // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} -// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before the function body or using the '__sized_by' attribute}} -struct IncompleteLaterCompletedStructTy*__counted_by(0) test_cb_expect_err( // expected-note{{__counted_by attribute is here}} - // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before the function body or using the '__sized_by' attribute}} - struct IncompleteLaterCompletedStructTy*__counted_by(0) param) { - // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before this definition or using the '__sized_by' attribute}} - struct IncompleteLaterCompletedStructTy*__counted_by(0) local; +// expected-error@+1{{cannot apply '__counted_by' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by(0) test_cb_expect_err( // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by(0) param) { // expected-note{{consider using '__sized_by' instead of '__counted_by'}} + // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by(0) local; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} - // expected-error@+1{{cannot assign to 'GlobalCBPtrTentativeDefUseWillErr' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'GlobalCBPtrTentativeDefUseWillErr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} GlobalCBPtrTentativeDefUseWillErr = 0; - // expected-error@+1{{annot initialize 'StructPtrIncompleteLaterCompleted::ptr' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot initialize 'StructPtrIncompleteLaterCompleted::ptr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} struct StructPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; struct StructPtrIncompleteLaterCompleted tmp2; - // expected-error@+1{{cannot use 'tmp2.ptr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'tmp2.ptr' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} consume_IncompleteLaterCompletedStructTy(tmp2.ptr); - // expected-error@+1{{cannot pass argument to parameter 'p' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot pass argument to parameter 'p' with '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} consume_IncompleteLaterCompletedStructTy(0x0); - // expected-error@+1{{cannot call 'ret_IncompleteLaterCompletedStructTy' with return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot call 'ret_IncompleteLaterCompletedStructTy' with '__counted_by' attributed return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} ret_IncompleteLaterCompletedStructTy(); - // expected-error@+1{{cannot return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot return '__counted_by' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} return 0x0; } -// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before the function body or using the '__sized_by_or_null' attribute}} -struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) test_cbon_expect_err( // expected-note{{__counted_by_or_null attribute is here}} - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before the function body or using the '__sized_by_or_null' attribute}} - struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) param) { - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' before this definition or using the '__sized_by_or_null' attribute}} - struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) local; +// expected-error@+1{{cannot apply '__counted_by_or_null' attribute to return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} +struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) test_cbon_expect_err( // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'param' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') on a function definition because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) param) { // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'local' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} + struct IncompleteLaterCompletedStructTy*__counted_by_or_null(0) local; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} - // expected-error@+1{{cannot assign to 'GlobalCBONPtrTentativeDefUseWillErr' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'GlobalCBONPtrTentativeDefUseWillErr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} GlobalCBONPtrTentativeDefUseWillErr = 0; - // expected-error@+1{{cannot initialize 'StructCBONPtrIncompleteLaterCompleted::ptr' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when initializing; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot initialize 'StructCBONPtrIncompleteLaterCompleted::ptr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} struct StructCBONPtrIncompleteLaterCompleted tmp = { .count = 0, .ptr = 0x0 }; struct StructCBONPtrIncompleteLaterCompleted tmp2; - // expected-error@+1{{cannot use 'tmp2.ptr' with type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'tmp2.ptr' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(count)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} consume_CBON_IncompleteLaterCompletedStructTy(tmp2.ptr); - // expected-error@+1{{cannot pass argument to parameter 'p' that has type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when passing; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot pass argument to parameter 'p' with '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} consume_CBON_IncompleteLaterCompletedStructTy(0x0); - // expected-error@+1{{cannot call 'ret_CBON_IncompleteLaterCompletedStructTy' with return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot call 'ret_CBON_IncompleteLaterCompletedStructTy' with '__counted_by_or_null' attributed return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} ret_CBON_IncompleteLaterCompletedStructTy(); - // expected-error@+1{{cannot return type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when returning; consider providing a complete definition for 'struct IncompleteLaterCompletedStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot return '__counted_by_or_null' attributed type 'struct IncompleteLaterCompletedStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteLaterCompletedStructTy *__single') because the pointee type 'struct IncompleteLaterCompletedStructTy' is incomplete}} return 0x0; } diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_blocks.c b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_blocks.c index 244db35a21b29..d5bcb1a9a28c4 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_blocks.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_blocks.c @@ -7,7 +7,7 @@ // pointee type on block parameters/return type //------------------------------------------------------------------------------ -struct IncompleteStructTy; // expected-note 6{{forward declaration of 'struct IncompleteStructTy'}} +struct IncompleteStructTy; // expected-note 6{{consider providing a complete definition for 'struct IncompleteStructTy'}} //------------------------------------------------------------------------------ // Attribute on block parameters @@ -20,8 +20,8 @@ void consume_cb(struct IncompleteStructTy* __counted_by(size), int size); void consume_cbon(struct IncompleteStructTy* __counted_by_or_null(size), int size); void use_block_params_cb(void) { - // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} - cb_block_fn_t f_named = ^(struct IncompleteStructTy* __counted_by(size) buf, int size) { + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + cb_block_fn_t f_named = ^(struct IncompleteStructTy* __counted_by(size) buf, int size) { // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // Uses don't generate diagnostics because the parameter is treated as invalid. buf = 0x0; buf[0] = 0; @@ -29,14 +29,14 @@ void use_block_params_cb(void) { consume_cb(buf); }; - // expected-error@+2{{cannot apply '__counted_by' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} + // expected-error@+2{{cannot apply '__counted_by' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} - cb_block_fn_t f_unnamed = ^(struct IncompleteStructTy* __counted_by(size), int size) { + cb_block_fn_t f_unnamed = ^(struct IncompleteStructTy* __counted_by(size), int size) { // expected-note{{consider using '__sized_by' instead of '__counted_by'}} }; void (^f_var_no_typedef_decl)(struct IncompleteStructTy* __counted_by(size), int size) = - // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by' attribute}} - ^(struct IncompleteStructTy* __counted_by(size) buf, int size) { + // expected-error@+1{{cannot apply '__counted_by' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + ^(struct IncompleteStructTy* __counted_by(size) buf, int size) { // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // Uses don't generate diagnostics because the parameter is treated as invalid. buf = 0x0; buf[0] = 0; @@ -46,8 +46,8 @@ void use_block_params_cb(void) { } void use_block_params_cbon(void) { - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} - cbon_block_fn_t f_named = ^(struct IncompleteStructTy* __counted_by_or_null(size) buf, int size) { + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + cbon_block_fn_t f_named = ^(struct IncompleteStructTy* __counted_by_or_null(size) buf, int size) { // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // Uses don't generate diagnostics because the parameter is treated as invalid. buf = 0x0; buf[0] = 0; @@ -55,14 +55,14 @@ void use_block_params_cbon(void) { consume_cb(buf); }; - // expected-error@+2{{cannot apply '__counted_by_or_null' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} + // expected-error@+2{{cannot apply '__counted_by_or_null' attribute to parameter with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} // expected-warning@+1{{omitting the parameter name in a function definition is a C23 extension}} - cbon_block_fn_t f_unnamed = ^(struct IncompleteStructTy* __counted_by_or_null(size), int size) { + cbon_block_fn_t f_unnamed = ^(struct IncompleteStructTy* __counted_by_or_null(size), int size) { // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} }; void (^f_var_no_typedef_decl)(struct IncompleteStructTy* __counted_by_or_null(size), int size) = - // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before the function body or using the '__sized_by_or_null' attribute}} - ^(struct IncompleteStructTy* __counted_by_or_null(size) buf, int size) { + // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to parameter 'buf' with type 'struct IncompleteStructTy *__single __counted_by_or_null(size)' (aka 'struct IncompleteStructTy *__single') on a function definition because the pointee type 'struct IncompleteStructTy' is incomplete}} + ^(struct IncompleteStructTy* __counted_by_or_null(size) buf, int size) { // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // Uses don't generate diagnostics because the parameter is treated as invalid. buf = 0x0; buf[0] = 0; diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_tentative_defs.c b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_tentative_defs.c index 72cee741e2ab8..10abf1674da4e 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_tentative_defs.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_incomplete_completable_struct_tentative_defs.c @@ -10,8 +10,8 @@ // the typedef. This seems like the right behavior because the typedef isn't the // forward declaration, `struct IncompleteStructTy` is. // -// expected-note@+2 2{{forward declaration of 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy')}} -// expected-note@+1 30{{forward declaration of 'struct IncompleteStructTy'}} +// expected-note@+2 2{{consider providing a complete definition for 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy')}} +// expected-note@+1 30{{consider providing a complete definition for 'struct IncompleteStructTy'}} struct IncompleteStructTy; //------------------------------------------------------------------------------ @@ -19,18 +19,18 @@ struct IncompleteStructTy; //------------------------------------------------------------------------------ // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_one' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy*__counted_by(0) cb_t_dfn_one; // expected-note{{__counted_by attribute is here}} +struct IncompleteStructTy*__counted_by(0) cb_t_dfn_one; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_one' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_one; // expected-note{{__counted_by_or_null attribute is here}} +struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_one; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_cb_t_dfn_one(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_one' that has type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_one' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_one = 0x0; } void use_cbon_t_dfn_one(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_one' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_one' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_one = 0x0; } @@ -43,19 +43,19 @@ void use_cbon_t_dfn_one(void) { struct IncompleteStructTy*__counted_by(0) cb_t_dfn_two; // OK - tentative definition acts like declaration // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_two' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy*__counted_by(0) cb_t_dfn_two; // expected-note{{__counted_by attribute is here}} +struct IncompleteStructTy*__counted_by(0) cb_t_dfn_two; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_two; // OK - tentative definition acts like declaration // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_two' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_two; // expected-note{{__counted_by_or_null attribute is here}} +struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_two; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_cb_t_dfn_two(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_two' that has type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_two' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_two = 0x0; } void use_cbon_t_dfn_two(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_two' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_two' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_two = 0x0; } @@ -66,24 +66,24 @@ void use_cbon_t_dfn_two(void) { // NOTE: The diagnostic about initializing `cb_t_dfn_after_def` is suppressed. // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'cb_t_dfn_after_def' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy*__counted_by(0) cb_t_dfn_after_def = 0x0; +struct IncompleteStructTy*__counted_by(0) cb_t_dfn_after_def = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} struct IncompleteStructTy*__counted_by(0) cb_t_dfn_after_def; // OK - tentative definition acts like declaration -// expected-note@+1{{__counted_by attribute is here}} +// expected-note@+1{{consider using '__sized_by' instead of '__counted_by'}} extern struct IncompleteStructTy*__counted_by(0) cb_t_dfn_after_def; // OK - declaration // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'cbon_t_dfn_after_def' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_after_def = 0x0; +struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_after_def = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_after_def; // OK - tentative definition acts like declaration // expected-note@+1{{__counted_by_or_null}} extern struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_after_def; // OK - declaration void use_cb_t_dfn_after_def(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_after_def' that has type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_after_def' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_after_def = 0x0; } void use_cbon_t_dfn_after_def(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_after_def' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_after_def' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_after_def = 0x0; } @@ -97,21 +97,21 @@ void use_cbon_t_dfn_after_def(void) { // than other `use_*` functions in this file. struct IncompleteStructTy*__counted_by(0) cb_t_dfn_before_def; // OK - tentative definition acts like declaration -// expected-note@+1 2{{__counted_by attribute is here}} +// expected-note@+1 2{{consider using '__sized_by' instead of '__counted_by'}} extern struct IncompleteStructTy*__counted_by(0) cb_t_dfn_before_def; // OK - declaration void consume_cb_const_count_zero(struct IncompleteStructTy*__counted_by(0) p); void use_cb_t_dfn_before_def_before_def(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_before_def' that has type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_before_def' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_before_def = 0x0; - // expected-error@+1{{cannot use 'cb_t_dfn_before_def' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot use 'cb_t_dfn_before_def' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_cb_const_count_zero(cb_t_dfn_before_def); } // expected-error@+1{{cannot apply '__counted_by' attribute to variable definition 'cb_t_dfn_before_def' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy*__counted_by(0) cb_t_dfn_before_def = 0x0; +struct IncompleteStructTy*__counted_by(0) cb_t_dfn_before_def = 0x0; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} void use_cb_t_dfn_before_def_after_def(void) { // no error here. At this point `cb_t_dfn_before_def` has been marked as invalid @@ -121,21 +121,21 @@ void use_cb_t_dfn_before_def_after_def(void) { } struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_before_def; // OK - tentative definition acts like declaration -// expected-note@+1 2{{__counted_by_or_null attribute is here}} +// expected-note@+1 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} extern struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_before_def; // OK - declaration void consume_cbon_const_count_zero(struct IncompleteStructTy*__counted_by_or_null(0) p); void use_cbon_t_dfn_before_def_before_def(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_before_def' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_before_def' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_before_def = 0x0; - // expected-error@+1{{cannot use 'cbon_t_dfn_before_def' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete in this context; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot use 'cbon_t_dfn_before_def' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} consume_cbon_const_count_zero(cbon_t_dfn_before_def); } // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to variable definition 'cbon_t_dfn_before_def' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_before_def = 0x0; +struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_before_def = 0x0; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_cbon_t_dfn_before_def_after_def(void) { // no error here. At this point `cbon_t_dfn_before_def` has been marked as invalid @@ -151,19 +151,19 @@ void use_cbon_t_dfn_before_def_after_def(void) { static struct IncompleteStructTy*__counted_by(0) cb_t_dfn_static_def; // OK - tentative definition acts like declaration // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_static_def' with type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -static struct IncompleteStructTy*__counted_by(0) cb_t_dfn_static_def; // expected-note{{__counted_by attribute is here}} +static struct IncompleteStructTy*__counted_by(0) cb_t_dfn_static_def; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} static struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_static_def; // OK - tentative definition acts like declaration // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_static_def' with type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -static struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_static_def; // expected-note{{__counted_by_or_null attribute is here}} +static struct IncompleteStructTy*__counted_by_or_null(0) cbon_t_dfn_static_def; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_cb_t_dfn_static_def(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_static_def' that has type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_static_def' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_static_def = 0x0; } void use_cbon_t_dfn_static_def(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_static_def' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_static_def' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_static_def = 0x0; } @@ -173,41 +173,41 @@ void use_cbon_t_dfn_static_def(void) { static int cb_t_dfn_static_non_const_count_count; // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_static_non_const_count' with type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -static struct IncompleteStructTy*__counted_by(cb_t_dfn_static_non_const_count_count) cb_t_dfn_static_non_const_count; // expected-note{{__counted_by attribute is here}} +static struct IncompleteStructTy*__counted_by(cb_t_dfn_static_non_const_count_count) cb_t_dfn_static_non_const_count; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} static int cbon_t_dfn_static_non_const_count_count; // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_static_non_const_count' with type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -static struct IncompleteStructTy*__counted_by_or_null(cbon_t_dfn_static_non_const_count_count) cbon_t_dfn_static_non_const_count; // expected-note{{__counted_by_or_null attribute is here}} +static struct IncompleteStructTy*__counted_by_or_null(cbon_t_dfn_static_non_const_count_count) cbon_t_dfn_static_non_const_count; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} int cb_t_dfn_non_const_count_count; // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_non_const_count' with type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by' attribute}} -struct IncompleteStructTy*__counted_by(cb_t_dfn_non_const_count_count) cb_t_dfn_non_const_count; // expected-note{{__counted_by attribute is here}} +struct IncompleteStructTy*__counted_by(cb_t_dfn_non_const_count_count) cb_t_dfn_non_const_count; // expected-note 2{{consider using '__sized_by' instead of '__counted_by'}} int cbon_t_dfn_non_const_count_count; // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_non_const_count' with type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete; consider providing a complete definition for 'struct IncompleteStructTy' before this definition or using the '__sized_by_or_null' attribute}} -struct IncompleteStructTy*__counted_by_or_null(cbon_t_dfn_non_const_count_count) cbon_t_dfn_non_const_count; // expected-note{{__counted_by_or_null attribute is here}} +struct IncompleteStructTy*__counted_by_or_null(cbon_t_dfn_non_const_count_count) cbon_t_dfn_non_const_count; // expected-note 2{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} void use_cb_t_dfn_static_non_const_count(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_static_non_const_count' that has type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_static_non_const_count' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_static_non_const_count = 0x0; cb_t_dfn_static_non_const_count_count = 0; } void use_cbon_t_dfn_static_non_const_count(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_static_non_const_count' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_static_non_const_count' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_static_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_static_non_const_count = 0x0; cbon_t_dfn_static_non_const_count_count = 0; } void use_cb_t_dfn_non_const_count(void) { - // expected-error@+1{{cannot assign to 'cb_t_dfn_non_const_count' that has type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by' attribute}} + // expected-error@+1{{cannot assign to 'cb_t_dfn_non_const_count' with '__counted_by' attributed type 'struct IncompleteStructTy *__single __counted_by(cb_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cb_t_dfn_non_const_count = 0x0; cb_t_dfn_non_const_count_count = 0; } void use_cbon_t_dfn_non_const_count(void) { - // expected-error@+1{{cannot assign to 'cbon_t_dfn_non_const_count' that has type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete and the '__counted_by_or_null' attribute requires the pointee type be complete when assigning; consider providing a complete definition for 'struct IncompleteStructTy' or using the '__sized_by_or_null' attribute}} + // expected-error@+1{{cannot assign to 'cbon_t_dfn_non_const_count' with '__counted_by_or_null' attributed type 'struct IncompleteStructTy *__single __counted_by_or_null(cbon_t_dfn_non_const_count_count)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'struct IncompleteStructTy' is incomplete}} cbon_t_dfn_non_const_count = 0x0; cbon_t_dfn_non_const_count_count = 0; } @@ -219,10 +219,10 @@ void use_cbon_t_dfn_non_const_count(void) { typedef struct IncompleteStructTy Incomplete_Struct_t; // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'cb_t_dfn_one_typedef' with type 'Incomplete_Struct_t *__single __counted_by(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by' attribute}} -Incomplete_Struct_t*__counted_by(0) cb_t_dfn_one_typedef; +Incomplete_Struct_t*__counted_by(0) cb_t_dfn_one_typedef; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'cbon_t_dfn_one_typedef' with type 'Incomplete_Struct_t *__single __counted_by_or_null(0)' (aka 'struct IncompleteStructTy *__single') because the pointee type 'Incomplete_Struct_t' (aka 'struct IncompleteStructTy') is incomplete; consider providing a complete definition for 'Incomplete_Struct_t' before this definition or using the '__sized_by_or_null' attribute}} -Incomplete_Struct_t*__counted_by_or_null(0) cbon_t_dfn_one_typedef; +Incomplete_Struct_t*__counted_by_or_null(0) cbon_t_dfn_one_typedef; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} //------------------------------------------------------------------------------ diff --git a/clang/test/BoundsSafety/Sema/counted_by_type_unknown_completable_union.c b/clang/test/BoundsSafety/Sema/counted_by_type_unknown_completable_union.c index 674ac0fe6388a..3a8e13550166b 100644 --- a/clang/test/BoundsSafety/Sema/counted_by_type_unknown_completable_union.c +++ b/clang/test/BoundsSafety/Sema/counted_by_type_unknown_completable_union.c @@ -5,15 +5,15 @@ // Test incomplete unions extern int external_union_len; -typedef union incomplete_union incomplete_union_t; // expected-note 2{{forward declaration of 'union incomplete_union'}} +typedef union incomplete_union incomplete_union_t; // expected-note 2{{consider providing a complete definition for 'union incomplete_union'}} extern incomplete_union_t* __counted_by(external_union_len) incompleteUnionPtr; // OK extern union incomplete_union* __counted_by(external_union_len) incompleteUnionPtr2; // OK int global_union_len; // expected-error@+1{{cannot apply '__counted_by' attribute to tentative variable definition 'GlobalCBUnionPtrImplicitInit' with type 'union incomplete_union *__single __counted_by(global_union_len)' (aka 'union incomplete_union *__single') because the pointee type 'union incomplete_union' is incomplete; consider providing a complete definition for 'union incomplete_union' before this definition or using the '__sized_by' attribute}} -union incomplete_union* __counted_by(global_union_len) GlobalCBUnionPtrImplicitInit; +union incomplete_union* __counted_by(global_union_len) GlobalCBUnionPtrImplicitInit; // expected-note{{consider using '__sized_by' instead of '__counted_by'}} // expected-error@+1{{cannot apply '__counted_by_or_null' attribute to tentative variable definition 'GlobalCBONUnionPtrImplicitInit' with type 'union incomplete_union *__single __counted_by_or_null(global_union_len)' (aka 'union incomplete_union *__single') because the pointee type 'union incomplete_union' is incomplete; consider providing a complete definition for 'union incomplete_union' before this definition or using the '__sized_by_or_null' attribute}} -union incomplete_union* __counted_by_or_null(global_union_len) GlobalCBONUnionPtrImplicitInit; +union incomplete_union* __counted_by_or_null(global_union_len) GlobalCBONUnionPtrImplicitInit; // expected-note{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} // Unions are handled like structs for the diagnostics so the testing for structs // should mean testing other combinations should be unnecessary. diff --git a/clang/test/BoundsSafety/Sema/source-location-for-counted-attribute-type.c b/clang/test/BoundsSafety/Sema/source-location-for-counted-attribute-type.c index a6ba2efc6c53b..debc307b39a70 100644 --- a/clang/test/BoundsSafety/Sema/source-location-for-counted-attribute-type.c +++ b/clang/test/BoundsSafety/Sema/source-location-for-counted-attribute-type.c @@ -22,24 +22,24 @@ struct IncompleteTy; // Incomplete #define COUNT_ARG 0 struct CB { int count; - // CHECK: [[@LINE+1]]:26: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:26: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __counted_by(count) b_macro; - // CHECK: [[@LINE+1]]:41: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:41: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __attribute__((counted_by(count))) b_direct_non_affixed; - // CHECK: [[@LINE+1]]:41: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:41: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __attribute__((__counted_by__(count))) b_direct_affixed; // NOTE: In these cases the locations just point to the count expressions as // a fallback. - // CHECK: [[@LINE+1]]:44: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:44: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* custom_counted_by(count) b_custom_macro; - // CHECK: [[@LINE+1]]:46: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:46: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* custom_counted_by__(count) b_custom_macro_underscored; - // CHECK: [[@LINE+1]]:39: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:39: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __counted_by(COUNT_ARG) b_macro_macro_arg; - // CHECK: [[@LINE+1]]:52: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:52: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __attribute__((counted_by(COUNT_ARG))) b_direct_non_affixed_macro_arg; - // CHECK: [[@LINE+1]]:56: note: __counted_by attribute is here + // CHECK: [[@LINE+1]]:56: note: consider using '__sized_by' instead of '__counted_by' struct IncompleteTy* __attribute__((__counted_by__(COUNT_ARG))) b_direct_affixed_macro_arg; }; @@ -63,24 +63,24 @@ void useCB(struct CB* cb) { struct CBON { int count; - // CHECK: [[@LINE+1]]:26: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:26: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __counted_by_or_null(count) b_macro; - // CHECK: [[@LINE+1]]:41: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:41: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __attribute__((counted_by_or_null(count))) b_direct_non_affixed; - // CHECK: [[@LINE+1]]:41: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:41: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __attribute__((__counted_by_or_null__(count))) b_direct_affixed; // NOTE: In these cases the locations just points to the count expressions as // a fallback. - // CHECK: [[@LINE+1]]:52: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:52: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* custom_counted_by_or_null(count) b_custom_macro; - // CHECK: [[@LINE+1]]:54: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:54: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* custom_counted_by_or_null__(count) b_custom_macro_underscored; - // CHECK: [[@LINE+1]]:47: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:47: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __counted_by_or_null(COUNT_ARG) b_macro_macro_arg; - // CHECK: [[@LINE+1]]:60: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:60: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __attribute__((counted_by_or_null(COUNT_ARG))) b_direct_non_affixed_macro_arg; - // CHECK: [[@LINE+1]]:64: note: __counted_by_or_null attribute is here + // CHECK: [[@LINE+1]]:64: note: consider using '__sized_by_or_null' instead of '__counted_by_or_null' struct IncompleteTy* __attribute__((__counted_by_or_null__(COUNT_ARG))) b_direct_affixed_macro_arg; }; diff --git a/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c b/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c index d0d4ef5751616..1dff82ac887ce 100644 --- a/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c +++ b/clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c @@ -19,13 +19,12 @@ struct on_member_pointer_complete_ty { }; struct on_member_pointer_incomplete_ty { - struct size_unknown * buf __counted_by(count); // expected-error{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} + struct size_unknown * buf __counted_by(count); // ok int count; }; struct on_member_pointer_const_incomplete_ty { - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by(count); + const struct size_unknown * buf __counted_by(count); // ok int count; }; diff --git a/clang/test/Sema/attr-counted-by-or-null-last-field.c b/clang/test/Sema/attr-counted-by-or-null-last-field.c index 12c0b6de44f72..60a1f571b19e9 100644 --- a/clang/test/Sema/attr-counted-by-or-null-last-field.c +++ b/clang/test/Sema/attr-counted-by-or-null-last-field.c @@ -118,12 +118,12 @@ struct annotated_with_anon_struct { struct count_unknown; struct on_member_ptr_incomplete_ty_ty_pos { int count; - struct count_unknown * ptr __counted_by_or_null(count); // expected-error {{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct count_unknown' is an incomplete type}} + struct count_unknown * ptr __counted_by_or_null(count); // ok }; struct on_member_ptr_incomplete_const_ty_ty_pos { int count; - const struct count_unknown * ptr __counted_by_or_null(count); // expected-error {{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'const struct count_unknown' is an incomplete type}} + const struct count_unknown * ptr __counted_by_or_null(count); // ok }; struct on_member_ptr_void_ty_ty_pos { diff --git a/clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c b/clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c index d81254631b628..c0acbb1ceea3d 100644 --- a/clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c +++ b/clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c @@ -20,13 +20,12 @@ struct on_member_pointer_complete_ty { }; struct on_member_pointer_incomplete_ty { - struct size_unknown * buf __counted_by_or_null(count); // expected-error{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} + struct size_unknown * buf __counted_by_or_null(count); // ok int count; }; struct on_member_pointer_const_incomplete_ty { - // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by_or_null(count); + const struct size_unknown * buf __counted_by_or_null(count); // ok int count; }; diff --git a/clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c b/clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c new file mode 100644 index 0000000000000..cff5a14c70b99 --- /dev/null +++ b/clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c @@ -0,0 +1,631 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s + +#define __counted_by_or_null(f) __attribute__((counted_by_or_null(f))) + +// ============================================================================= +// # Struct incomplete type with attribute in the decl position +// ============================================================================= + +// Note: This could be considered misleading. The typedef isn't actually on this +// line. Also note the discrepancy in diagnostic count (27 vs 51) is due to +// the pointer arithmetic on incomplete pointee type diagnostic always using +// diagnostic text that refers to the underlying forward decl, even when the +// typedef is used. +// expected-note@+3 27{{consider providing a complete definition for 'Incomplete_t' (aka 'struct IncompleteTy')}} +// The 'forward declaration' notes come from 'arithmetic on a pointer to an incomplete type' errors +// expected-note@+1 24{{forward declaration of 'struct IncompleteTy'}} +struct IncompleteTy; // expected-note 27{{consider providing a complete definition for 'struct IncompleteTy'}} + +typedef struct IncompleteTy Incomplete_t; + +struct CBBufDeclPos { + int count; + struct IncompleteTy* buf __counted_by_or_null(count); // OK expected-note 27{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + Incomplete_t* buf_typedef __counted_by_or_null(count); // OK expected-note 27{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void consume_struct_IncompleteTy(struct IncompleteTy* buf); + +int idx(void); + + + +void test_CBBufDeclPos(struct CBBufDeclPos* ptr) { + // =========================================================================== + // ## Local variable initialization + // =========================================================================== + struct CBBufDeclPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + .buf_typedef = 0x0 + }; + // Variable is not currently marked as invalid so uses of the variable allows + // diagnostics to fire. + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot use 'explicit_desig_init.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void *tmp = explicit_desig_init.buf; + // expected-error@+1{{cannot use 'explicit_desig_init.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void *tmp2 = explicit_desig_init.buf_typedef; + + struct CBBufDeclPos partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + }; + + struct CBBufDeclPos implicit_full_init = { + 0 + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + }; + // Variable is not currently marked as invalid so uses of the variable allows + // diagnostics to fire. + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + implicit_full_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + implicit_full_init.buf_typedef = 0x0; + // expected-error@+1{{cannot use 'implicit_full_init.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* tmp3 = implicit_full_init.buf; + // expected-error@+1{{cannot use 'implicit_full_init.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* tmp4 = implicit_full_init.buf_typedef; + + struct CBBufDeclPos explicit_non_desig_init = { + 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + 0x0 + }; + + + + + // =========================================================================== + // ## Assignment to fields + // =========================================================================== + struct CBBufDeclPos uninit; + uninit.count = 0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + uninit.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + uninit.buf_typedef = 0x0; + ptr->count = 0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + ptr->buf_typedef = 0x0; + + + // =========================================================================== + // ## Make sure modifying the fields through other assignment operators is not + // allowed + // =========================================================================== + uninit.buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ++uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf_typedef++; // // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ++uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + uninit.buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + --uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + --uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + ptr->buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ++ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + --ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + + ptr->buf_typedef++; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ++ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + --ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + // =========================================================================== + // ## Use of fields in expressions + // =========================================================================== + // expected-error@+2{{cannot use 'uninit.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* addr = + ((char*) uninit.buf ) + 1; + // expected-error@+2{{cannot use 'uninit.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* addr_typedef = + ((char*) uninit.buf_typedef ) + 1; + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* addr_ptr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* addr_ptr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + + // =========================================================================== + // ## Take address of fields + // =========================================================================== + // TODO: This should be forbidden, not because of the incomplete pointee type + // but because in the -fbounds-safety language model the address of a + // `counted_by` pointer cannot be taken to avoid it being possible to modify + // the `counted_by` pointer through another pointer. Whether or not this + // should be forbidden when `-fbounds-safety` is off is TBD. + // + // The incomplete pointee type isn't actually a problem here for + // `-fbounds-safety` because taking the address of a pointer returns a pointer + // that have the bounds of a single `void*`, so bounds checks on the resulting + // pointer don't need to know `sizeof(struct IncompleteTy)` but instead + // `sizeof(struct IncompleteTy* buf __counted_by_or_null(count))` which is just the + // size of a pointer. + void* take_addr = &uninit.buf; + void* take_addr_typedef = &uninit.buf_typedef; + void* take_addr_ptr = &ptr->buf; + void* take_addr_ptr_typedef = &ptr->buf_typedef; + + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_zero = &uninit.buf[0]; + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_idx = &uninit.buf[idx()]; + + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_zero_typedef = &uninit.buf_typedef[0]; + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_idx_typedef = &uninit.buf_typedef[idx()]; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0]; + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()]; + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0]; + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()]; + + + // =========================================================================== + // ## Use fields as call arguments + // =========================================================================== + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + consume_struct_IncompleteTy(uninit.buf); + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + consume_struct_IncompleteTy(uninit.buf_typedef); + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + consume_struct_IncompleteTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + consume_struct_IncompleteTy(ptr->buf_typedef); + + // =========================================================================== + // ## Use [] operator on fields + // =========================================================================== + // expected-error@+1 2{{cannot use 'uninit.buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + uninit.buf[0] = uninit.buf[1]; + // expected-error@+1 2{{cannot use 'uninit.buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + uninit.buf_typedef[0] = uninit.buf_typedef[1]; + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + + +// ============================================================================= +// ## Global initialization +// ============================================================================= + +struct CBBufDeclPos global_explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + .buf_typedef = 0x0 +}; + +void use_global_explicit_desig_init(void) { + // Variable isn't marked as invalid so diagnostics still fire + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + global_explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + global_explicit_desig_init.buf_typedef = 0x0; +} + +struct CBBufDeclPos global_partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} +}; + +struct CBBufDeclPos global_implicit_full_init = { + 0 + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} +}; + +struct CBBufDeclPos global_explicit_non_desig_init = { + 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_t * __counted_by_or_null(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + 0x0 +}; + +extern struct CBBufDeclPos global_declaration; // OK + +// TODO: These tentative definitions are implicitly empty initialized to zero. +// This should generate an error diagnostic but currently doesn't. There should +// be a carve out to allow `__counted_by_or_null(0)` which is the only constant count +// version of the attribute where it is valid to assign NULL. +struct CBBufDeclPos global_tentative_defn; +static struct CBBufDeclPos global_tentative_defn2; + +// ============================================================================= +// ## Completing the definition of the type allows use of CBBufDeclPos fields +// ============================================================================= +struct IncompleteTy { + int field; +}; + +void test_CBBufDeclPos_completed(struct CBBufDeclPos* ptr) { + // Initialization is ok + struct CBBufDeclPos explicit_desig_init = { + .count = 0, + .buf = 0x0, + .buf_typedef = 0x0 + }; + + struct CBBufDeclPos partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + }; + + struct CBBufDeclPos implicit_full_init = {0}; + + struct CBBufDeclPos explicit_non_desig_init = { + 0, + 0x0, + 0x0 + }; + + // Assignment to fields is ok + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + + // Use of fields in expressions is ok + void* tmp = ptr->buf; + void* tmp2 = ptr->buf_typedef; + + // Take address of fields is ok + void* take_addr_ptr = &ptr->buf; + void* take_addr_ptr_typedef = &ptr->buf_typedef; + + struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0]; + struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()]; + struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0]; + struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()]; + + // As call arguments is ok + consume_struct_IncompleteTy(ptr->buf); + consume_struct_IncompleteTy(ptr->buf_typedef); + + // In [] operator is ok + ptr->buf[0] = ptr->buf[1]; + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +// Global initialization is ok + +struct CBBufDeclPos global_explicit_desig_init_completed = { + .count = 0, + .buf = 0x0, + .buf_typedef = 0x0 +}; + +struct CBBufDeclPos global_partial_explicit_desig_init_completed = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized +}; + +struct CBBufDeclPos global_implicit_full_init_completed = {0}; + +struct CBBufDeclPos global_explicit_non_desig_init_completed = { + 0, + 0x0, + 0x0 +}; + +extern struct CBBufDeclPos global_declaration; +struct CBBufDeclPos global_tentative_defn; +static struct CBBufDeclPos global_tentative_defn2; + +// ============================================================================= +// # Struct incomplete type with attribute in the pointer position +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'Incomplete_ty2' (aka 'struct IncompleteTy2')}} +struct IncompleteTy2; // expected-note 8{{consider providing a complete definition for 'struct IncompleteTy2'}} +typedef struct IncompleteTy2 Incomplete_ty2; + +void consume_struct_IncompleteTy2(struct IncompleteTy2* buf); + +struct CBBufTyPos { + int count; + struct IncompleteTy2* __counted_by_or_null(count) buf ; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + Incomplete_ty2 *__counted_by_or_null(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void use_CBBufTyPos(struct CBBufTyPos* ptr) { + struct CBBufTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + consume_struct_IncompleteTy2(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + consume_struct_IncompleteTy2(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufTyPos global_explicit_desig_init_struct_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by_or_null' attributed type 'struct IncompleteTy2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'Incomplete_ty2 * __counted_by_or_null(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufTyPos` fields usable +struct IncompleteTy2 { + int field; +}; + +void use_CBBufTyPos_completed(struct CBBufTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// ============================================================================= +// # union incomplete type +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy')}} +union IncompleteUnionTy; // expected-note 8{{consider providing a complete definition for 'union IncompleteUnionTy'}} +typedef union IncompleteUnionTy IncompleteUnion_ty; + +void consume_struct_IncompleteUnionTy(union IncompleteUnionTy* buf); + +struct CBBufUnionTyPos { + int count; + union IncompleteUnionTy* __counted_by_or_null(count) buf ; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + IncompleteUnion_ty *__counted_by_or_null(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void use_CBBufUnionTyPos(struct CBBufUnionTyPos* ptr) { + struct CBBufUnionTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + consume_struct_IncompleteUnionTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + consume_struct_IncompleteUnionTy(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufUnionTyPos global_explicit_desig_init_union_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by_or_null' attributed type 'union IncompleteUnionTy * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteUnion_ty * __counted_by_or_null(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufUnionTyPos` fields usable +union IncompleteUnionTy { + int field; +}; + +void use_CBBufUnionTyPos_completed(struct CBBufUnionTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// ============================================================================= +// # enum incomplete type +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy')}} +enum IncompleteEnumTy; // expected-note 8{{consider providing a complete definition for 'enum IncompleteEnumTy'}} +typedef enum IncompleteEnumTy IncompleteEnum_ty; + +void consume_struct_IncompleteEnumTy(enum IncompleteEnumTy* buf); + +struct CBBufEnumTyPos { + int count; + enum IncompleteEnumTy* __counted_by_or_null(count) buf ; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} + IncompleteEnum_ty *__counted_by_or_null(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by_or_null' instead of '__counted_by_or_null'}} +}; + +void use_CBBufEnumTyPos(struct CBBufEnumTyPos* ptr) { + struct CBBufEnumTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + consume_struct_IncompleteEnumTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + consume_struct_IncompleteEnumTy(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufEnumTyPos global_explicit_desig_init_enum_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by_or_null' attributed type 'enum IncompleteEnumTy * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by_or_null' attributed type 'IncompleteEnum_ty * __counted_by_or_null(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufEnumTyPos` fields usable +enum IncompleteEnumTy { + ONE, + TWO +}; + +void use_CBBufEnumTyPos_completed(struct CBBufEnumTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// Make a complete enum by providing an underlying type +enum CompleteEnumTy : unsigned; +typedef enum CompleteEnumTy CompleteEnum_ty; +struct CBBufEnumTyPos2 { + int count; + enum CompleteEnumTy* __counted_by_or_null(count) buf; + CompleteEnum_ty *__counted_by_or_null(count) buf_typedef; +}; + +void use_CBBufEnumTyPos2(struct CBBufEnumTyPos2* ptr) { + struct CBBufEnumTyPos2 explicit_desig_init = { + .count = 0, + .buf = 0x0, // OK + .buf_typedef = 0x0 // OK + }; +} + +// Make a complete enum by providing a concrete declaration +enum CompleteEnumTy2 { + VALUE_ONE, + VALUE_TWO +}; +typedef enum CompleteEnumTy2 CompleteEnum_ty2; +struct CBBufEnumTyPos3 { + int count; + enum CompleteEnumTy2* __counted_by_or_null(count) buf; + CompleteEnum_ty2 *__counted_by_or_null(count) buf_typedef; +}; + +void use_CBBufEnumTyPos3(struct CBBufEnumTyPos3* ptr) { + struct CBBufEnumTyPos3 explicit_desig_init = { + .count = 0, + .buf = 0x0, // OK + .buf_typedef = 0x0 // OK + }; +} + + +// ============================================================================= +// # Array of __counted_by_or_null pointers +// ============================================================================= + +struct IncompleteTy3; + +struct CBBufFAMofCountedByPtrs { + int size; + // TODO: This is misleading. The attribute is written in the type position + // but clang currently doesn't treat it like that and it gets treated as + // an attribute on the array, rather than on the element type. + // expected-error@+1{{'counted_by_or_null' only applies to pointers; did you mean to use 'counted_by'?}} + struct IncompleteTy3* __counted_by_or_null(size) arr[]; +}; + +void arr_of_counted_by_ptr(struct CBBufFAMofCountedByPtrs* ptr) { + // TODO: Should be disallowed once parsing attributes in the type position + // works. + ptr->arr[0] = 0x0; + void* addr = ((char*) ptr->arr[0]) + 1; +} diff --git a/clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c b/clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c index 708bb727ce09d..0bb09059c97f9 100644 --- a/clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c +++ b/clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c @@ -22,14 +22,12 @@ struct on_member_pointer_complete_ty { struct on_member_pointer_incomplete_ty { int count; - // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * buf __counted_by_or_null(count); + struct size_unknown * buf __counted_by_or_null(count); // ok }; struct on_member_pointer_const_incomplete_ty { int count; - // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by_or_null(count); + const struct size_unknown * buf __counted_by_or_null(count); // ok }; struct on_member_pointer_void_ty { @@ -116,14 +114,12 @@ struct on_member_pointer_complete_ty_ty_pos { struct on_member_pointer_incomplete_ty_ty_pos { int count; - // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * __counted_by_or_null(count) buf; + struct size_unknown * __counted_by_or_null(count) buf; // ok }; struct on_member_pointer_const_incomplete_ty_ty_pos { int count; - // expected-error@+1{{'counted_by_or_null' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * __counted_by_or_null(count) buf; + const struct size_unknown * __counted_by_or_null(count) buf; // ok }; struct on_member_pointer_void_ty_ty_pos { diff --git a/clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c b/clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c new file mode 100644 index 0000000000000..d28a2086b51b8 --- /dev/null +++ b/clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c @@ -0,0 +1,630 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fexperimental-late-parse-attributes -fsyntax-only -verify %s + +#define __counted_by(f) __attribute__((counted_by(f))) + +// ============================================================================= +// # Struct incomplete type with attribute in the decl position +// ============================================================================= + +// Note: This could be considered misleading. The typedef isn't actually on this +// line. Also note the discrepancy in diagnostic count (27 vs 51) is due to +// the pointer arithmetic on incomplete pointee type diagnostic always using +// diagnostic text that refers to the underlying forward decl, even when the +// typedef is used. +// expected-note@+3 27{{consider providing a complete definition for 'Incomplete_t' (aka 'struct IncompleteTy')}} +// The 'forward declaration' notes come from 'arithmetic on a pointer to an incomplete type' errors +// expected-note@+1 24{{forward declaration of 'struct IncompleteTy'}} +struct IncompleteTy; // expected-note 27{{consider providing a complete definition for 'struct IncompleteTy'}} + +typedef struct IncompleteTy Incomplete_t; + +struct CBBufDeclPos { + int count; + struct IncompleteTy* buf __counted_by(count); // OK expected-note 27{{consider using '__sized_by' instead of '__counted_by'}} + Incomplete_t* buf_typedef __counted_by(count); // OK expected-note 27{{consider using '__sized_by' instead of '__counted_by'}} +}; + +void consume_struct_IncompleteTy(struct IncompleteTy* buf); + +int idx(void); + + + +void test_CBBufDeclPos(struct CBBufDeclPos* ptr) { + // =========================================================================== + // ## Local variable initialization + // =========================================================================== + struct CBBufDeclPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + .buf_typedef = 0x0 + }; + // Variable is not currently marked as invalid so uses of the variable allows + // diagnostics to fire. + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot use 'explicit_desig_init.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void *tmp = explicit_desig_init.buf; + // expected-error@+1{{cannot use 'explicit_desig_init.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void *tmp2 = explicit_desig_init.buf_typedef; + + struct CBBufDeclPos partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + }; + + struct CBBufDeclPos implicit_full_init = { + 0 + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + }; + // Variable is not currently marked as invalid so uses of the variable allows + // diagnostics to fire. + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + implicit_full_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + implicit_full_init.buf_typedef = 0x0; + // expected-error@+1{{cannot use 'implicit_full_init.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* tmp3 = implicit_full_init.buf; + // expected-error@+1{{cannot use 'implicit_full_init.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* tmp4 = implicit_full_init.buf_typedef; + + struct CBBufDeclPos explicit_non_desig_init = { + 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + 0x0 + }; + + + + + // =========================================================================== + // ## Assignment to fields + // =========================================================================== + struct CBBufDeclPos uninit; + uninit.count = 0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + uninit.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + uninit.buf_typedef = 0x0; + ptr->count = 0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + ptr->buf_typedef = 0x0; + + + // =========================================================================== + // ## Make sure modifying the fields through other assignment operators is not + // allowed + // =========================================================================== + uninit.buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ++uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf_typedef++; // // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ++uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + uninit.buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + --uninit.buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + uninit.buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + --uninit.buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + uninit.buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + ptr->buf++; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ++ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf--; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + --ptr->buf; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + ptr->buf -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'struct IncompleteTy'}} + + ptr->buf_typedef++; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ++ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef += 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef--; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + --ptr->buf_typedef; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + ptr->buf_typedef -= 1; // expected-error{{arithmetic on a pointer to an incomplete type 'Incomplete_t' (aka 'struct IncompleteTy')}} + + // =========================================================================== + // ## Use of fields in expressions + // =========================================================================== + // expected-error@+2{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* addr = + ((char*) uninit.buf ) + 1; + // expected-error@+2{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* addr_typedef = + ((char*) uninit.buf_typedef ) + 1; + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + void* addr_ptr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + void* addr_ptr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + + // =========================================================================== + // ## Take address of fields + // =========================================================================== + // TODO: This should be forbidden, not because of the incomplete pointee type + // but because in the -fbounds-safety language model the address of a + // `counted_by` pointer cannot be taken to avoid it being possible to modify + // the `counted_by` pointer through another pointer. Whether or not this + // should be forbidden when `-fbounds-safety` is off is TBD. + // + // The incomplete pointee type isn't actually a problem here for + // `-fbounds-safety` because taking the address of a pointer returns a pointer + // that have the bounds of a single `void*`, so bounds checks on the resulting + // pointer don't need to know `sizeof(struct IncompleteTy)` but instead + // `sizeof(struct IncompleteTy* buf __counted_by(count))` which is just the + // size of a pointer. + void* take_addr = &uninit.buf; + void* take_addr_typedef = &uninit.buf_typedef; + void* take_addr_ptr = &ptr->buf; + void* take_addr_ptr_typedef = &ptr->buf_typedef; + + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_zero = &uninit.buf[0]; + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_idx = &uninit.buf[idx()]; + + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_zero_typedef = &uninit.buf_typedef[0]; + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_idx_typedef = &uninit.buf_typedef[idx()]; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0]; + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()]; + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0]; + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()]; + + + // =========================================================================== + // ## Use fields as call arguments + // =========================================================================== + // expected-error@+1{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + consume_struct_IncompleteTy(uninit.buf); + // expected-error@+1{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + consume_struct_IncompleteTy(uninit.buf_typedef); + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + consume_struct_IncompleteTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + consume_struct_IncompleteTy(ptr->buf_typedef); + + // =========================================================================== + // ## Use [] operator on fields + // =========================================================================== + // expected-error@+1 2{{cannot use 'uninit.buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + uninit.buf[0] = uninit.buf[1]; + // expected-error@+1 2{{cannot use 'uninit.buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + uninit.buf_typedef[0] = uninit.buf_typedef[1]; + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + + +// ============================================================================= +// ## Global initialization +// ============================================================================= + +struct CBBufDeclPos global_explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + .buf_typedef = 0x0 +}; + +void use_global_explicit_desig_init(void) { + // Variable isn't marked as invalid so diagnostics still fire + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + global_explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + global_explicit_desig_init.buf_typedef = 0x0; +} + +struct CBBufDeclPos global_partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} +}; + +struct CBBufDeclPos global_implicit_full_init = { + 0 + // expected-error@+2{{cannot implicitly initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + // expected-error@+1{{cannot implicitly initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} +}; + +struct CBBufDeclPos global_explicit_non_desig_init = { + 0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf' with '__counted_by' attributed type 'struct IncompleteTy * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'struct IncompleteTy' is incomplete}} + 0x0, + // expected-error@+1{{cannot initialize 'CBBufDeclPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_t * __counted_by(count)' (aka 'struct IncompleteTy *') because the pointee type 'Incomplete_t' (aka 'struct IncompleteTy') is incomplete}} + 0x0 +}; + +extern struct CBBufDeclPos global_declaration; // OK + +// TODO: These tentative definitions are implicitly empty initialized to zero. +// This should generate an error diagnostic but currently doesn't. There should +// be a carve out to allow `__counted_by(0)` which is the only constant count +// version of the attribute where it is valid to assign NULL. +struct CBBufDeclPos global_tentative_defn; +static struct CBBufDeclPos global_tentative_defn2; + +// ============================================================================= +// ## Completing the definition of the type allows use of CBBufDeclPos fields +// ============================================================================= +struct IncompleteTy { + int field; +}; + +void test_CBBufDeclPos_completed(struct CBBufDeclPos* ptr) { + // Initialization is ok + struct CBBufDeclPos explicit_desig_init = { + .count = 0, + .buf = 0x0, + .buf_typedef = 0x0 + }; + + struct CBBufDeclPos partial_explicit_desig_init = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized + }; + + struct CBBufDeclPos implicit_full_init = {0}; + + struct CBBufDeclPos explicit_non_desig_init = { + 0, + 0x0, + 0x0 + }; + + // Assignment to fields is ok + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + + // Use of fields in expressions is ok + void* tmp = ptr->buf; + void* tmp2 = ptr->buf_typedef; + + // Take address of fields is ok + void* take_addr_ptr = &ptr->buf; + void* take_addr_ptr_typedef = &ptr->buf_typedef; + + struct IncompleteTy* addr_elt_zero_ptr = &ptr->buf[0]; + struct IncompleteTy* addr_elt_idx_ptr = &ptr->buf[idx()]; + struct IncompleteTy* addr_elt_zero_ptr_typedef = &ptr->buf_typedef[0]; + struct IncompleteTy* addr_elt_idx_ptr_typedef = &ptr->buf_typedef[idx()]; + + // As call arguments is ok + consume_struct_IncompleteTy(ptr->buf); + consume_struct_IncompleteTy(ptr->buf_typedef); + + // In [] operator is ok + ptr->buf[0] = ptr->buf[1]; + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +// Global initialization is ok + +struct CBBufDeclPos global_explicit_desig_init_completed = { + .count = 0, + .buf = 0x0, + .buf_typedef = 0x0 +}; + +struct CBBufDeclPos global_partial_explicit_desig_init_completed = { + .count = 0, + // .buf and .buf_typedef are implicit zero initialized +}; + +struct CBBufDeclPos global_implicit_full_init_completed = {0}; + +struct CBBufDeclPos global_explicit_non_desig_init_completed = { + 0, + 0x0, + 0x0 +}; + +extern struct CBBufDeclPos global_declaration; +struct CBBufDeclPos global_tentative_defn; +static struct CBBufDeclPos global_tentative_defn2; + +// ============================================================================= +// # Struct incomplete type with attribute in the pointer position +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'Incomplete_ty2' (aka 'struct IncompleteTy2')}} +struct IncompleteTy2; // expected-note 8{{consider providing a complete definition for 'struct IncompleteTy2'}} +typedef struct IncompleteTy2 Incomplete_ty2; + +void consume_struct_IncompleteTy2(struct IncompleteTy2* buf); + +struct CBBufTyPos { + int count; + struct IncompleteTy2* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} + Incomplete_ty2 *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} +}; + +void use_CBBufTyPos(struct CBBufTyPos* ptr) { + struct CBBufTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + consume_struct_IncompleteTy2(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + consume_struct_IncompleteTy2(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufTyPos global_explicit_desig_init_struct_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf' with '__counted_by' attributed type 'struct IncompleteTy2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'struct IncompleteTy2' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufTyPos::buf_typedef' with '__counted_by' attributed type 'Incomplete_ty2 * __counted_by(count)' (aka 'struct IncompleteTy2 *') because the pointee type 'Incomplete_ty2' (aka 'struct IncompleteTy2') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufTyPos` fields usable +struct IncompleteTy2 { + int field; +}; + +void use_CBBufTyPos_completed(struct CBBufTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// ============================================================================= +// # union incomplete type +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy')}} +union IncompleteUnionTy; // expected-note 8{{consider providing a complete definition for 'union IncompleteUnionTy'}} +typedef union IncompleteUnionTy IncompleteUnion_ty; + +void consume_struct_IncompleteUnionTy(union IncompleteUnionTy* buf); + +struct CBBufUnionTyPos { + int count; + union IncompleteUnionTy* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} + IncompleteUnion_ty *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} +}; + +void use_CBBufUnionTyPos(struct CBBufUnionTyPos* ptr) { + struct CBBufUnionTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + consume_struct_IncompleteUnionTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + consume_struct_IncompleteUnionTy(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufUnionTyPos global_explicit_desig_init_union_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf' with '__counted_by' attributed type 'union IncompleteUnionTy * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'union IncompleteUnionTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufUnionTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteUnion_ty * __counted_by(count)' (aka 'union IncompleteUnionTy *') because the pointee type 'IncompleteUnion_ty' (aka 'union IncompleteUnionTy') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufUnionTyPos` fields usable +union IncompleteUnionTy { + int field; +}; + +void use_CBBufUnionTyPos_completed(struct CBBufUnionTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// ============================================================================= +// # enum incomplete type +// ============================================================================= + +// expected-note@+1 8{{consider providing a complete definition for 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy')}} +enum IncompleteEnumTy; // expected-note 8{{consider providing a complete definition for 'enum IncompleteEnumTy'}} +typedef enum IncompleteEnumTy IncompleteEnum_ty; + +void consume_struct_IncompleteEnumTy(enum IncompleteEnumTy* buf); + +struct CBBufEnumTyPos { + int count; + enum IncompleteEnumTy* __counted_by(count) buf ; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} + IncompleteEnum_ty *__counted_by(count) buf_typedef; // OK expected-note 8{{consider using '__sized_by' instead of '__counted_by'}} +}; + +void use_CBBufEnumTyPos(struct CBBufEnumTyPos* ptr) { + struct CBBufEnumTyPos explicit_desig_init = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + .buf_typedef = 0x0 + }; + + // Assignment + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + explicit_desig_init.buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + explicit_desig_init.buf_typedef = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + ptr->buf = 0x0; + // expected-error@+1{{cannot assign to 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + ptr->buf_typedef = 0x0; + + // Use + // expected-error@+2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + void* addr = + ((char*) ptr->buf ) + 1; + // expected-error@+2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + void* addr_typedef = + ((char*) ptr->buf_typedef ) + 1; + + // expected-error@+1{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + consume_struct_IncompleteEnumTy(ptr->buf); + // expected-error@+1{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + consume_struct_IncompleteEnumTy(ptr->buf_typedef); + + // expected-error@+1 2{{cannot use 'ptr->buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + ptr->buf[0] = ptr->buf[1]; + // expected-error@+1 2{{cannot use 'ptr->buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + ptr->buf_typedef[0] = ptr->buf_typedef[1]; +} + +struct CBBufEnumTyPos global_explicit_desig_init_enum_type_pos = { + .count = 0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf' with '__counted_by' attributed type 'enum IncompleteEnumTy * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'enum IncompleteEnumTy' is incomplete}} + .buf = 0x0, + // expected-error@+1{{cannot initialize 'CBBufEnumTyPos::buf_typedef' with '__counted_by' attributed type 'IncompleteEnum_ty * __counted_by(count)' (aka 'enum IncompleteEnumTy *') because the pointee type 'IncompleteEnum_ty' (aka 'enum IncompleteEnumTy') is incomplete}} + .buf_typedef = 0x0 +}; + +// Defining the type makes `CBBufEnumTyPos` fields usable +enum IncompleteEnumTy { + ONE, + TWO +}; + +void use_CBBufEnumTyPos_completed(struct CBBufEnumTyPos* ptr) { + ptr->buf = 0x0; + ptr->buf_typedef = 0x0; + void* addr = ((char*) ptr->buf) + 1; + void* addr_typedef = ((char*) ptr->buf_typedef) + 1; +} + +// Make a complete enum by providing an underlying type +enum CompleteEnumTy : unsigned; +typedef enum CompleteEnumTy CompleteEnum_ty; +struct CBBufEnumTyPos2 { + int count; + enum CompleteEnumTy* __counted_by(count) buf; + CompleteEnum_ty *__counted_by(count) buf_typedef; +}; + +void use_CBBufEnumTyPos2(struct CBBufEnumTyPos2* ptr) { + struct CBBufEnumTyPos2 explicit_desig_init = { + .count = 0, + .buf = 0x0, // OK + .buf_typedef = 0x0 // OK + }; +} + +// Make a complete enum by providing a concrete declaration +enum CompleteEnumTy2 { + VALUE_ONE, + VALUE_TWO +}; +typedef enum CompleteEnumTy2 CompleteEnum_ty2; +struct CBBufEnumTyPos3 { + int count; + enum CompleteEnumTy2* __counted_by(count) buf; + CompleteEnum_ty2 *__counted_by(count) buf_typedef; +}; + +void use_CBBufEnumTyPos3(struct CBBufEnumTyPos3* ptr) { + struct CBBufEnumTyPos3 explicit_desig_init = { + .count = 0, + .buf = 0x0, // OK + .buf_typedef = 0x0 // OK + }; +} + + +// ============================================================================= +// # Array of __counted_by pointers +// ============================================================================= + +struct IncompleteTy3; + +struct CBBufFAMofCountedByPtrs { + int size; + // TODO: This is misleading. The attribute is written in the type position + // but clang currently doesn't treat it like that and it gets treated as + // an attribute on the array, rather than on the element type. + struct IncompleteTy3* __counted_by(size) arr[]; +}; + +void arr_of_counted_by_ptr(struct CBBufFAMofCountedByPtrs* ptr) { + // TODO: Should be disallowed once parsing attributes in the type position + // works. + ptr->arr[0] = 0x0; + void* addr = ((char*) ptr->arr[0]) + 1; +} diff --git a/clang/test/Sema/attr-counted-by-struct-ptrs.c b/clang/test/Sema/attr-counted-by-struct-ptrs.c index 321d6aafbeba2..c05d18262e2b7 100644 --- a/clang/test/Sema/attr-counted-by-struct-ptrs.c +++ b/clang/test/Sema/attr-counted-by-struct-ptrs.c @@ -21,14 +21,12 @@ struct on_member_pointer_complete_ty { struct on_member_pointer_incomplete_ty { int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * buf __counted_by(count); + struct size_unknown * buf __counted_by(count); // ok }; struct on_member_pointer_const_incomplete_ty { int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * buf __counted_by(count); + const struct size_unknown * buf __counted_by(count); // ok }; struct on_member_pointer_void_ty { @@ -115,14 +113,12 @@ struct on_member_pointer_complete_ty_ty_pos { struct on_member_pointer_incomplete_ty_ty_pos { int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct size_unknown' is an incomplete type}} - struct size_unknown * __counted_by(count) buf; + struct size_unknown * __counted_by(count) buf; // ok }; struct on_member_pointer_const_incomplete_ty_ty_pos { int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'const struct size_unknown' is an incomplete type}} - const struct size_unknown * __counted_by(count) buf; + const struct size_unknown * __counted_by(count) buf; // ok }; struct on_member_pointer_void_ty_ty_pos { diff --git a/clang/test/Sema/attr-counted-by-vla.c b/clang/test/Sema/attr-counted-by-vla.c index 35737c03f3222..5b1b4833dce7d 100644 --- a/clang/test/Sema/attr-counted-by-vla.c +++ b/clang/test/Sema/attr-counted-by-vla.c @@ -98,8 +98,7 @@ struct array_of_ints_count { struct not_a_fam { int count; - // expected-error@+1{{'counted_by' cannot be applied to a pointer with pointee of unknown size because 'struct bar' is an incomplete type}} - struct bar *non_fam __counted_by(count); + struct bar *non_fam __counted_by(count); // ok }; struct not_a_c99_fam {