Skip to content

Commit 6ab5f3e

Browse files
committed
fixup: refactor semantic checks
Change error descriptions and restructure the checks code.
1 parent 585f214 commit 6ab5f3e

File tree

4 files changed

+56
-49
lines changed

4 files changed

+56
-49
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3453,14 +3453,18 @@ def warn_attribute_return_span_only
34533453
: Warning<"%0 attribute only applies to functions that return span-like "
34543454
"structures">,
34553455
InGroup<IgnoredAttributes>;
3456-
def note_span_must_be_struct : Note<"span-like type must be a struct">;
3457-
def note_span_must_be_complete : Note<"span-like type must be complete">;
3458-
def note_wrong_span_field_count : Note<"span-like type must have 2 fields">;
3459-
def note_wrong_span_field_types
3460-
: Note<"span-like type must have a pointer and an integer field or two "
3461-
"pointer fields">;
3462-
def note_span_invalid_integer : Note<"the integer field must be an actual "
3463-
"integer that is at least as big as int">;
3456+
def note_returned_not_struct : Note<"returned type is not a struct/class type">;
3457+
def note_returned_incomlete_type : Note<"returned type is incomplete">;
3458+
def note_returned_not_two_field_struct
3459+
: Note<"returned struct/class has %0 fields, expected 2">;
3460+
def note_returned_not_span_struct
3461+
: Note<"returned struct/class fields are not a supported combination for a "
3462+
"span-like type (expected pointer/integer or pointer/pointer)">;
3463+
def note_returned_not_integer_field
3464+
: Note<"field #%0 expected to be an integer">;
3465+
def note_returned_not_wide_enough_field
3466+
: Note<"integer field #%0 of span-like type is not wide enough (minimum "
3467+
"width: %1)">;
34643468
def warn_attribute_return_pointers_refs_only : Warning<
34653469
"%0 attribute only applies to return values that are pointers or references">,
34663470
InGroup<IgnoredAttributes>;

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,59 +1850,51 @@ static bool checkSpanLikeType(Sema &S, const ParsedAttr &AL,
18501850
// lead to false positive results.
18511851
auto emitWarning = [&S, &AL](unsigned NoteDiagID) {
18521852
S.Diag(AL.getLoc(), diag::warn_attribute_return_span_only) << AL;
1853-
S.Diag(AL.getLoc(), NoteDiagID);
1853+
return S.Diag(AL.getLoc(), NoteDiagID);
18541854
};
1855+
if (Ty->isIncompleteType())
1856+
return emitWarning(diag::note_returned_incomlete_type);
18551857
const RecordDecl *RD = Ty->getAsRecordDecl();
1856-
if (!RD || RD->isUnion()) {
1857-
emitWarning(diag::note_span_must_be_struct);
1858-
return false;
1859-
}
1860-
const RecordDecl *Def = RD->getDefinition();
1861-
if (!Def) {
1862-
emitWarning(diag::note_span_must_be_complete);
1863-
return false; // This is an incomplete type.
1864-
}
1865-
auto FieldsBegin = Def->field_begin();
1866-
if (std::distance(FieldsBegin, Def->field_end()) != 2) {
1867-
emitWarning(diag::note_wrong_span_field_count);
1868-
return false;
1869-
}
1858+
if (!RD || RD->isUnion())
1859+
return emitWarning(diag::note_returned_not_struct);
1860+
auto FieldsBegin = RD->field_begin();
1861+
const auto FieldsCount = std::distance(FieldsBegin, RD->field_end());
1862+
if (FieldsCount != 2)
1863+
return emitWarning(diag::note_returned_not_two_field_struct) << FieldsCount;
18701864
const QualType FirstFieldType = FieldsBegin->getType();
18711865
const QualType SecondFieldType = std::next(FieldsBegin)->getType();
18721866
auto validatePointerType = [](const QualType &T) {
18731867
// It must not point to functions.
18741868
return T->isPointerType() && !T->isFunctionPointerType();
18751869
};
1876-
auto checkIntegerType = [&S, emitWarning](const QualType &T) {
1877-
bool valid = false;
1878-
// Must be an actual integer and at least as bit as int.
1879-
if (const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType())) {
1880-
const auto IntSize = S.Context.getTypeSize(S.Context.IntTy);
1881-
valid = BT->isInteger() && S.Context.getTypeSize(BT) >= IntSize;
1882-
}
1883-
if (!valid) {
1884-
emitWarning(diag::note_span_invalid_integer);
1885-
}
1886-
return valid;
1870+
auto checkIntegerType = [&S, emitWarning](const QualType &T,
1871+
const int FieldNo) -> bool {
1872+
const auto *BT = dyn_cast<BuiltinType>(T.getCanonicalType());
1873+
if (!BT || !BT->isInteger())
1874+
return emitWarning(diag::note_returned_not_integer_field) << FieldNo;
1875+
const auto IntSize = S.Context.getTypeSize(S.Context.IntTy);
1876+
if (S.Context.getTypeSize(BT) < IntSize)
1877+
return emitWarning(diag::note_returned_not_wide_enough_field)
1878+
<< FieldNo << IntSize;
1879+
return false;
18871880
};
18881881
if (validatePointerType(FirstFieldType) &&
18891882
validatePointerType(SecondFieldType)) {
18901883
// Pointer + pointer.
1891-
return true;
1884+
return false;
18921885
} else if (validatePointerType(FirstFieldType)) {
18931886
// Pointer + integer?
1894-
return checkIntegerType(SecondFieldType);
1887+
return checkIntegerType(SecondFieldType, 2);
18951888
} else if (validatePointerType(SecondFieldType)) {
18961889
// Integer + pointer?
1897-
return checkIntegerType(FirstFieldType);
1890+
return checkIntegerType(FirstFieldType, 1);
18981891
}
1899-
emitWarning(diag::note_wrong_span_field_types);
1900-
return false;
1892+
return emitWarning(diag::note_returned_not_span_struct);
19011893
}
19021894

19031895
static void handleMallocSpanAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
19041896
QualType ResultType = getFunctionOrMethodResultType(D);
1905-
if (checkSpanLikeType(S, AL, ResultType)) {
1897+
if (!checkSpanLikeType(S, AL, ResultType)) {
19061898
D->addAttr(::new (S.Context) MallocSpanAttr(S.Context, AL));
19071899
}
19081900
}

clang/test/Sema/attr-malloc_span.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ typedef struct {
99
} span;
1010
span returns_span (void) __attribute((malloc_span)); // no-warning
1111

12-
// Try out a different field ordering.
1312
typedef struct {
1413
size_t n;
1514
void *ptr;
@@ -21,8 +20,20 @@ typedef struct {
2120
void *ptr2;
2221
} span3;
2322
span3 returns_span3 (void) __attribute((malloc_span)); // no-warning
23+
24+
typedef struct {
25+
void *ptr;
26+
int n;
27+
} span4;
28+
span4 returns_span4 (void) __attribute((malloc_span)); // no-warning
29+
30+
typedef struct incomplete_span incomplete_span;
31+
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
32+
// expected-note@+1 {{returned type is incomplete}}
33+
incomplete_span returns_incomplete_span (void) __attribute((malloc_span));
34+
2435
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
25-
// expected-note@+1 {{span-like type must be a struct}}
36+
// expected-note@+1 {{returned type is not a struct/class type}}
2637
int *returns_int_ptr (void) __attribute((malloc_span));
2738

2839
typedef struct {
@@ -31,7 +42,7 @@ typedef struct {
3142
size_t n2;
3243
} too_long_span;
3344
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
34-
// expected-note@+1 {{span-like type must have 2 fields}}
45+
// expected-note@+1 {{returned struct/class has 3 fields, expected 2}}
3546
too_long_span returns_too_long_span (void) __attribute((malloc_span));
3647

3748
// Function pointers are not allowed.
@@ -40,7 +51,7 @@ typedef struct {
4051
size_t n;
4152
} func_span;
4253
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
43-
// expected-note@+1 {{span-like type must have a pointer and an integer field or two pointer fields}}
54+
// expected-note@+1 {{returned struct/class fields are not a supported combination}}
4455
func_span returns_func_span (void) __attribute((malloc_span));
4556

4657
// Integer should not be an enum.
@@ -50,7 +61,7 @@ typedef struct {
5061
enum some_enum field;
5162
} enum_span;
5263
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
53-
// expected-note@+1 {{the integer field must be an actual integer}}
64+
// expected-note@+1 {{field #2 expected to be an integer}}
5465
enum_span returns_enum_span (void) __attribute((malloc_span));
5566

5667
// Bit integers are also not supported.
@@ -59,7 +70,7 @@ typedef struct {
5970
_BitInt(16) n;
6071
} bit_span;
6172
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
62-
// expected-note@+1 {{the integer field must be an actual integer}}
73+
// expected-note@+1 {{field #2 expected to be an integer}}
6374
bit_span returns_bit_span (void) __attribute((malloc_span));
6475

6576
// Integer must be at least as big as int.
@@ -68,5 +79,5 @@ typedef struct {
6879
short n;
6980
} short_span;
7081
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
71-
// expected-note@+1 {{the integer field must be an actual integer}}
82+
// expected-note@+1 {{integer field #2 of span-like type is not wide enough (minimum width: 32)}}
7283
short_span returns_short_span (void) __attribute((malloc_span));

clang/test/SemaCXX/attr-malloc_span.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct DataMemberSpan {
1212
};
1313

1414
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
15-
// expected-note@+1 {{span-like type must have a pointer and an integer field or two pointer fields}}
15+
// expected-note@+1 {{returned struct/class fields are not a supported combination}}
1616
DataMemberSpan returns_data_member_span(void) __attribute((malloc_span)) {
1717
return DataMemberSpan{};
1818
}
@@ -24,7 +24,7 @@ struct MemberFuncSpan {
2424
};
2525

2626
// expected-warning@+2 {{attribute only applies to functions that return span-like structures}}
27-
// expected-note@+1 {{span-like type must have a pointer and an integer field or two pointer fields}}
27+
// expected-note@+1 {{returned struct/class fields are not a supported combination}}
2828
MemberFuncSpan returns_member_func_span(void) __attribute((malloc_span)) {
2929
return MemberFuncSpan{};
3030
}

0 commit comments

Comments
 (0)