@@ -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
19031895static 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}
0 commit comments