@@ -564,14 +564,37 @@ 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+
567590static void handleAllocSizeAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
568591 if (!AL.checkAtLeastNumArgs (S, 1 ) || !AL.checkAtMostNumArgs (S, 2 ))
569592 return ;
570593
571594 assert (isFuncOrMethodForAttrSubject (D) && hasFunctionProto (D));
572595
573596 QualType RetTy = getFunctionOrMethodResultType (D);
574- if (!RetTy->isPointerType () && !RetTy-> isSpanLikeType ()) {
597+ if (!RetTy->isPointerType () && !isSpanLikeType (RetTy )) {
575598 S.Diag (AL.getLoc (), diag::warn_attribute_return_pointers_only) << AL;
576599 return ;
577600 }
@@ -1751,7 +1774,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
17511774static void handleRestrictAttr (Sema &S, Decl *D, const ParsedAttr &AL) {
17521775 QualType ResultType = getFunctionOrMethodResultType (D);
17531776 if (!ResultType->isAnyPointerType () && !ResultType->isBlockPointerType () &&
1754- !ResultType-> isSpanLikeType ()) {
1777+ !isSpanLikeType (ResultType )) {
17551778 S.Diag (AL.getLoc (), diag::warn_attribute_return_pointers_only)
17561779 << AL << getFunctionOrMethodResultSourceRange (D);
17571780 return ;
0 commit comments