Skip to content

Commit 770e017

Browse files
committed
fixup: support different span struct field orderings
Do not demand that the pointer should be the first field and the integer type the second field.
1 parent e0fa07d commit 770e017

File tree

3 files changed

+22
-19
lines changed

3 files changed

+22
-19
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5256,9 +5256,9 @@ like a system memory allocation function and returns a span-like structure,
52565256
where the returned memory range does not alias storage from any other object
52575257
accessible to the caller.
52585258

5259-
In this context, a span-like structure is assumed to have a pointer to the
5260-
allocated memory as its first field and any integer type containing the size
5261-
of the actually allocated memory as the second field.
5259+
In this context, a span-like structure is assumed to have two fields, one of
5260+
which is a pointer to the allocated memory and another one is an integer type
5261+
containing the size of the actually allocated memory.
52625262
}];
52635263
}
52645264

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,8 +1840,8 @@ static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
18401840
}
18411841

18421842
static bool isSpanLikeType(const QualType &Ty) {
1843-
// Check that the type is a plain record with the first field being a pointer
1844-
// type and the second field being an integer. This matches the common
1843+
// Check that the type is a plain record with one field being a pointer
1844+
// type and the other field being an integer. This matches the common
18451845
// implementation of std::span or sized_allocation_t in P0901R11.
18461846
// Note that there may also be numerous cases of pointer+integer structures
18471847
// not actually exhibiting a span-like semantics, so sometimes
@@ -1855,10 +1855,13 @@ static bool isSpanLikeType(const QualType &Ty) {
18551855
auto FieldsBegin = Def->field_begin();
18561856
if (std::distance(FieldsBegin, Def->field_end()) != 2)
18571857
return false;
1858-
const FieldDecl *FirstField = *FieldsBegin;
1859-
const FieldDecl *SecondField = *std::next(FieldsBegin);
1860-
return FirstField->getType()->isAnyPointerType() &&
1861-
SecondField->getType()->isIntegerType();
1858+
const QualType FirstFieldType = FieldsBegin->getType();
1859+
const QualType SecondFieldType = std::next(FieldsBegin)->getType();
1860+
// Verify two possible orderings.
1861+
return (FirstFieldType->isAnyPointerType() &&
1862+
SecondFieldType->isIntegerType()) ||
1863+
(FirstFieldType->isIntegerType() &&
1864+
SecondFieldType->isAnyPointerType());
18621865
}
18631866

18641867
static void handleMallocSpanAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

clang/test/Sema/attr-malloc_span.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66
typedef struct {
77
void *ptr;
88
size_t n;
9-
} sized_ptr;
10-
sized_ptr returns_sized_ptr (void) __attribute((malloc_span)); // no-warning
9+
} span;
10+
span returns_span (void) __attribute((malloc_span)); // no-warning
1111

12-
// The first struct field must be pointer and the second must be an integer.
13-
// Check the possible ways to violate it.
12+
// Try out a different field ordering.
1413
typedef struct {
1514
size_t n;
1615
void *ptr;
17-
} invalid_span1;
18-
invalid_span1 returns_non_std_span1 (void) __attribute((malloc_span)); // expected-warning {{attribute only applies to return values that are span-like structures}}
16+
} span2;
17+
span2 returns_span2 (void) __attribute((malloc_span)); // no-warning
1918

19+
// Ensure that a warning is produced on malloc_span precondition violation.
2020
typedef struct {
2121
void *ptr;
2222
void *ptr2;
23-
} invalid_span2;
24-
invalid_span2 returns_non_std_span2 (void) __attribute((malloc_span)); // expected-warning {{attribute only applies to return values that are span-like structures}}
23+
} invalid_span1;
24+
invalid_span1 returns_non_std_span1 (void) __attribute((malloc_span)); // expected-warning {{attribute only applies to return values that are span-like structures}}
2525

2626
typedef struct {
2727
void *ptr;
2828
size_t n;
2929
size_t n2;
30-
} invalid_span3;
31-
invalid_span3 returns_non_std_span3 (void) __attribute((malloc_span)); // expected-warning {{attribute only applies to return values that are span-like structures}}
30+
} invalid_span2;
31+
invalid_span2 returns_non_std_span2 (void) __attribute((malloc_span)); // expected-warning {{attribute only applies to return values that are span-like structures}}

0 commit comments

Comments
 (0)