@@ -564,37 +564,14 @@ static bool checkParamIsIntegerType(Sema &S, const Decl *D, const AttrInfo &AI,
564564 return true ;
565565}
566566
567- static bool isSpanLikeType (const QualType &Ty) {
568- // Check that the type is a plain record with the first field being a pointer
569- // type and the second field being an integer.
570- // This matches the common implementation of std::span or sized_allocation_t
571- // in P0901R11.
572- // Note that there may also be numerous cases of pointer+integer structures
573- // not actually exhibiting a std::span-like semantics, so sometimes
574- // this heuristic expectedly leads to false positive results.
575- const RecordDecl *RD = Ty->getAsRecordDecl ();
576- if (!RD || RD->isUnion ())
577- return false ;
578- const RecordDecl *Def = RD->getDefinition ();
579- if (!Def)
580- return false ; // This is an incomplete type.
581- auto FieldsBegin = Def->field_begin ();
582- if (std::distance (FieldsBegin, Def->field_end ()) != 2 )
583- return false ;
584- const FieldDecl *FirstField = *FieldsBegin;
585- const FieldDecl *SecondField = *std::next (FieldsBegin);
586- return FirstField->getType ()->isAnyPointerType () &&
587- SecondField->getType ()->isIntegerType ();
588- }
589-
590567static void handleAllocSizeAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
591568 if (!AL.checkAtLeastNumArgs (S, 1 ) || !AL.checkAtMostNumArgs (S, 2 ))
592569 return ;
593570
594571 assert (isFuncOrMethodForAttrSubject (D) && hasFunctionProto (D));
595572
596573 QualType RetTy = getFunctionOrMethodResultType (D);
597- if (!RetTy->isPointerType () && ! isSpanLikeType (RetTy) ) {
574+ if (!RetTy->isPointerType ()) {
598575 S.Diag (AL.getLoc (), diag::warn_attribute_return_pointers_only) << AL;
599576 return ;
600577 }
@@ -1771,6 +1748,29 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17711748 D->addAttr (::new (S.Context ) TLSModelAttr (S.Context , AL, Model));
17721749}
17731750
1751+ static bool isSpanLikeType (const QualType &Ty) {
1752+ // Check that the type is a plain record with the first field being a pointer
1753+ // type and the second field being an integer.
1754+ // This matches the common implementation of std::span or sized_allocation_t
1755+ // in P0901R11.
1756+ // Note that there may also be numerous cases of pointer+integer structures
1757+ // not actually exhibiting a std::span-like semantics, so sometimes
1758+ // this heuristic expectedly leads to false positive results.
1759+ const RecordDecl *RD = Ty->getAsRecordDecl ();
1760+ if (!RD || RD->isUnion ())
1761+ return false ;
1762+ const RecordDecl *Def = RD->getDefinition ();
1763+ if (!Def)
1764+ return false ; // This is an incomplete type.
1765+ auto FieldsBegin = Def->field_begin ();
1766+ if (std::distance (FieldsBegin, Def->field_end ()) != 2 )
1767+ return false ;
1768+ const FieldDecl *FirstField = *FieldsBegin;
1769+ const FieldDecl *SecondField = *std::next (FieldsBegin);
1770+ return FirstField->getType ()->isAnyPointerType () &&
1771+ SecondField->getType ()->isIntegerType ();
1772+ }
1773+
17741774static void handleRestrictAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
17751775 QualType ResultType = getFunctionOrMethodResultType (D);
17761776 if (!ResultType->isAnyPointerType () && !ResultType->isBlockPointerType () &&
0 commit comments