Skip to content

Commit 0b44315

Browse files
committed
fixup: move isSpanLikeType() to SemaDeclAttr.cpp
Also leave a comment about possible false positives.
1 parent cb8dba4 commit 0b44315

File tree

3 files changed

+25
-23
lines changed

3 files changed

+25
-23
lines changed

clang/include/clang/AST/TypeBase.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2601,7 +2601,6 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
26012601
bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
26022602
bool isPointerType() const;
26032603
bool isPointerOrReferenceType() const;
2604-
bool isSpanLikeType() const;
26052604
bool isSignableType(const ASTContext &Ctx) const;
26062605
bool isSignablePointerType() const;
26072606
bool isSignableIntegerType(const ASTContext &Ctx) const;

clang/lib/AST/Type.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5753,23 +5753,3 @@ StringRef PredefinedSugarType::getName(Kind KD) {
57535753
}
57545754
llvm_unreachable("unexpected kind");
57555755
}
5756-
5757-
bool Type::isSpanLikeType() const {
5758-
// Check that the type is a plain record with the first field being a pointer
5759-
// type and the second field being an integer.
5760-
// This matches the common implementation of std::span or sized_allocation_t
5761-
// in P0901R11.
5762-
const RecordDecl *RD = getAsRecordDecl();
5763-
if (!RD || RD->isUnion())
5764-
return false;
5765-
const RecordDecl *Def = RD->getDefinition();
5766-
if (!Def)
5767-
return false; // This is an incomplete type.
5768-
auto FieldsBegin = Def->field_begin();
5769-
if (std::distance(FieldsBegin, Def->field_end()) != 2)
5770-
return false;
5771-
const FieldDecl *FirstField = *FieldsBegin;
5772-
const FieldDecl *SecondField = *std::next(FieldsBegin);
5773-
return FirstField->getType()->isAnyPointerType() &&
5774-
SecondField->getType()->isIntegerType();
5775-
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
567590
static 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) {
17511774
static 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

Comments
 (0)