Skip to content

Commit 7d6447b

Browse files
authored
Merge pull request #81519 from xymus/cdecl-diags
Sema: Update more diagnostics for `@cdecl` and representability in the C language
2 parents 5382e12 + ef84f0e commit 7d6447b

File tree

7 files changed

+195
-51
lines changed

7 files changed

+195
-51
lines changed

include/swift/AST/DiagnosticsCommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace swift {
5555
} // end namespace detail
5656

5757
enum class StaticSpellingKind : uint8_t;
58+
enum class ForeignLanguage : uint8_t;
5859

5960
namespace diag {
6061

include/swift/AST/DiagnosticsSema.def

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5537,11 +5537,15 @@ FIXIT(insert_globalactor_attr, "@%0 ", (Type))
55375537
ERROR(main_function_must_be_mainActor,none,
55385538
"main() must be '@MainActor'", ())
55395539

5540+
// Keep aligned with enum ForeignLanguage
5541+
#define FOREIGN_LANG_SELECT "select{C|Objective-C}"
5542+
55405543
ERROR(not_objc_function_async,none,
55415544
"'async' %kindonly0 cannot be represented in Objective-C",
55425545
(const AbstractFunctionDecl *))
55435546
NOTE(not_objc_function_type_async,none,
5544-
"'async' function types cannot be represented in Objective-C", ())
5547+
"'async' function types cannot be represented "
5548+
"in %" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
55455549
ERROR(actor_isolated_objc,none,
55465550
"actor-isolated %kind0 cannot be '@objc'",
55475551
(const ValueDecl *))
@@ -6557,9 +6561,6 @@ ERROR(objc_cannot_infer_name_raw_identifier,none,
65576561
// If you change this, also change enum ObjCReason
65586562
#define OBJC_ATTR_SELECT "select{marked '@cdecl'|marked '@_cdecl'|marked dynamic|marked '@objc'|marked '@objcMembers'|marked '@IBOutlet'|marked '@IBAction'|marked '@IBSegueAction'|marked '@NSManaged'|a member of an '@objc' protocol|implicitly '@objc'|an '@objc' override|an implementation of an '@objc' requirement|marked '@IBInspectable'|marked '@GKInspectable'|in an '@objc' extension of a class (without '@nonobjc')|in an '@objc @implementation' extension of a class (without final or '@nonobjc')|marked '@objc' by an access note}"
65596563

6560-
// Keep aligned with enum ForeignLanguage
6561-
#define FOREIGN_LANG_SELECT "select{C|Objective-C}"
6562-
65636564
ERROR(objc_invalid_on_var,none,
65646565
"property cannot be %" OBJC_ATTR_SELECT "0 "
65656566
"because its type cannot be represented in Objective-C", (unsigned))
@@ -6594,25 +6595,32 @@ NOTE(not_objc_error_protocol_composition,none,
65946595
"protocol-constrained type containing 'Error' cannot be represented "
65956596
"in Objective-C", ())
65966597
NOTE(not_objc_empty_tuple,none,
6597-
"empty tuple type cannot be represented in Objective-C", ())
6598+
"empty tuple type cannot be represented in %" FOREIGN_LANG_SELECT "0",
6599+
(ForeignLanguage))
65986600
NOTE(not_objc_non_trivial_cxx_class,none,
6599-
"non-trivial C++ classes cannot be represented in Objective-C", ())
6601+
"non-trivial C++ classes cannot be represented in "
6602+
"%" FOREIGN_LANG_SELECT "0",
6603+
(ForeignLanguage))
66006604
NOTE(not_objc_tuple,none,
6601-
"tuples cannot be represented in Objective-C", ())
6605+
"tuples cannot be represented in %" FOREIGN_LANG_SELECT "0",
6606+
(ForeignLanguage))
66026607
NOTE(not_objc_swift_class,none,
66036608
"classes not annotated with '@objc' cannot be represented "
66046609
"in Objective-C", ())
66056610
NOTE(not_objc_swift_struct,none,
6606-
"Swift structs cannot be represented in Objective-C", ())
6611+
"Swift structs cannot be represented in %" FOREIGN_LANG_SELECT "0",
6612+
(ForeignLanguage))
66076613
NOTE(not_objc_swift_enum,none,
66086614
"non-'@objc' enums cannot be represented in Objective-C", ())
66096615
NOTE(not_objc_generic_type_param,none,
6610-
"generic type parameters cannot be represented in Objective-C", ())
6616+
"generic type parameters cannot be represented in "
6617+
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
66116618
NOTE(not_objc_function_type_param,none,
6612-
"function types cannot be represented in Objective-C unless their "
6613-
"parameters and returns can be", ())
6619+
"function types cannot be represented in %" FOREIGN_LANG_SELECT "0 "
6620+
"unless their parameters and returns can be", (ForeignLanguage))
66146621
NOTE(not_objc_function_type_throwing,none,
6615-
"throwing function types cannot be represented in Objective-C", ())
6622+
"throwing function types cannot be represented in "
6623+
"%" FOREIGN_LANG_SELECT "0", (ForeignLanguage))
66166624
NOTE(objc_inferring_on_objc_protocol_member,none,
66176625
"inferring '@objc' because the declaration is a member of "
66186626
"an '@objc' protocol", ())
@@ -6622,6 +6630,11 @@ NOTE(objc_witness_objc_requirement,none,
66226630
"satisfying requirement for %kind0 in protocol %1",
66236631
(const ValueDecl *, const ProtocolDecl *))
66246632

6633+
NOTE(cdecl_incompatible_with_protocols,none,
6634+
"protocols cannot be represented in C", ())
6635+
NOTE(cdecl_incompatible_with_classes,none,
6636+
"classes cannot be represented in C", ())
6637+
66256638
ERROR(no_opaque_return_type_of,none,
66266639
"unable to resolve type for _opaqueReturnTypeOf attribute", ())
66276640

@@ -6635,24 +6648,24 @@ ERROR(objc_addressor, none,
66356648
ERROR(objc_coroutine_accessor, none,
66366649
"'read' and 'modify' accessors are not allowed to be marked '@objc'", ())
66376650
ERROR(objc_invalid_on_func_variadic,none,
6638-
"method cannot be %" OBJC_ATTR_SELECT "0 because it has a variadic "
6639-
"parameter", (unsigned))
6651+
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because it has a variadic "
6652+
"parameter", (const AbstractFunctionDecl*, unsigned))
66406653
ERROR(objc_invalid_on_func_inout,none,
66416654
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because inout "
66426655
"parameters cannot be represented in %" FOREIGN_LANG_SELECT "2",
6643-
(const AbstractFunctionDecl*, unsigned, unsigned))
6656+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66446657
ERROR(objc_invalid_on_func_param_type,none,
66456658
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "2 because the type of the "
66466659
"parameter %1 cannot be represented in %" FOREIGN_LANG_SELECT "3",
6647-
(const AbstractFunctionDecl*, unsigned, unsigned, unsigned))
6660+
(const AbstractFunctionDecl*, unsigned, unsigned, ForeignLanguage))
66486661
ERROR(objc_invalid_on_func_single_param_type,none,
66496662
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because the type of the "
66506663
"parameter cannot be represented in %" FOREIGN_LANG_SELECT "2",
6651-
(const AbstractFunctionDecl*, unsigned, unsigned))
6664+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66526665
ERROR(objc_invalid_on_func_result_type,none,
66536666
"%kindonly0 cannot be %" OBJC_ATTR_SELECT "1 because its result type "
66546667
"cannot be represented in %" FOREIGN_LANG_SELECT "2",
6655-
(const AbstractFunctionDecl*, unsigned, unsigned))
6668+
(const AbstractFunctionDecl*, unsigned, ForeignLanguage))
66566669
ERROR(objc_invalid_on_foreign_class,none,
66576670
"method cannot be %" OBJC_ATTR_SELECT "0 because Core Foundation "
66586671
"types are not classes in Objective-C", (unsigned))

include/swift/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ inline SubstOptions operator|(SubstFlags lhs, SubstFlags rhs) {
161161

162162
/// Enumeration describing foreign languages to which Swift may be
163163
/// bridged.
164-
enum class ForeignLanguage {
164+
enum class ForeignLanguage : uint8_t {
165165
C,
166166
ObjectiveC,
167167
};

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -170,24 +170,32 @@ void ObjCReason::setAttrInvalid() const {
170170
static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
171171
Type T,
172172
SourceRange TypeRange,
173-
DiagnosticBehavior behavior) {
173+
DiagnosticBehavior behavior,
174+
ObjCReason reason) {
174175
auto &diags = DC->getASTContext().Diags;
176+
auto language = reason.getForeignLanguage();
175177

176178
// Special diagnostic for tuples.
177179
if (T->is<TupleType>()) {
178180
if (T->isVoid())
179-
diags.diagnose(TypeRange.Start, diag::not_objc_empty_tuple)
181+
diags.diagnose(TypeRange.Start, diag::not_objc_empty_tuple, language)
180182
.highlight(TypeRange)
181183
.limitBehavior(behavior);
182184
else
183-
diags.diagnose(TypeRange.Start, diag::not_objc_tuple)
185+
diags.diagnose(TypeRange.Start, diag::not_objc_tuple, language)
184186
.highlight(TypeRange)
185187
.limitBehavior(behavior);
186188
return;
187189
}
188190

189191
// Special diagnostic for classes.
190192
if (auto *CD = T->getClassOrBoundGenericClass()) {
193+
if (language == ForeignLanguage::C) {
194+
diags.diagnose(TypeRange.Start, diag::cdecl_incompatible_with_classes)
195+
.limitBehavior(behavior);
196+
return;
197+
}
198+
191199
if (!CD->isObjC())
192200
diags.diagnose(TypeRange.Start, diag::not_objc_swift_class)
193201
.highlight(TypeRange)
@@ -199,12 +207,14 @@ static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
199207
if (auto *SD = T->getStructOrBoundGenericStruct()) {
200208
if (isa_and_nonnull<clang::CXXRecordDecl>(SD->getClangDecl())) {
201209
// This can be a non-trivial C++ record.
202-
diags.diagnose(TypeRange.Start, diag::not_objc_non_trivial_cxx_class)
210+
diags.diagnose(TypeRange.Start, diag::not_objc_non_trivial_cxx_class,
211+
language)
203212
.highlight(TypeRange)
204213
.limitBehavior(behavior);
205214
return;
206215
}
207-
diags.diagnose(TypeRange.Start, diag::not_objc_swift_struct)
216+
diags.diagnose(TypeRange.Start, diag::not_objc_swift_struct,
217+
language)
208218
.highlight(TypeRange)
209219
.limitBehavior(behavior);
210220
return;
@@ -220,6 +230,13 @@ static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
220230

221231
// Special diagnostic for protocols and protocol compositions.
222232
if (T->isExistentialType()) {
233+
// No protocol is representable in C.
234+
if (language == ForeignLanguage::C) {
235+
diags.diagnose(TypeRange.Start, diag::cdecl_incompatible_with_protocols)
236+
.limitBehavior(behavior);
237+
return;
238+
}
239+
223240
if (T->isAny()) {
224241
// Any is not @objc.
225242
diags.diagnose(TypeRange.Start,
@@ -267,28 +284,32 @@ static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
267284
}
268285

269286
if (T->is<ArchetypeType>() || T->isTypeParameter()) {
270-
diags.diagnose(TypeRange.Start, diag::not_objc_generic_type_param)
287+
diags.diagnose(TypeRange.Start, diag::not_objc_generic_type_param,
288+
language)
271289
.highlight(TypeRange)
272290
.limitBehavior(behavior);
273291
return;
274292
}
275293

276294
if (auto fnTy = T->getAs<FunctionType>()) {
277295
if (fnTy->getExtInfo().isAsync()) {
278-
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_async)
296+
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_async,
297+
language)
279298
.highlight(TypeRange)
280299
.limitBehavior(behavior);
281300
return;
282301
}
283302

284303
if (fnTy->getExtInfo().isThrowing()) {
285-
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_throwing)
304+
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_throwing,
305+
language)
286306
.highlight(TypeRange)
287307
.limitBehavior(behavior);
288308
return;
289309
}
290310

291-
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_param)
311+
diags.diagnose(TypeRange.Start, diag::not_objc_function_type_param,
312+
language)
292313
.highlight(TypeRange)
293314
.limitBehavior(behavior);
294315
return;
@@ -305,25 +326,26 @@ static void diagnoseFunctionParamNotRepresentable(
305326
softenIfAccessNote(AFD, Reason.getAttr(),
306327
AFD->diagnose(diag::objc_invalid_on_func_single_param_type,
307328
AFD, getObjCDiagnosticAttrKind(Reason),
308-
(unsigned)language)
329+
language)
309330
.limitBehavior(behavior));
310331
} else {
311332
softenIfAccessNote(AFD, Reason.getAttr(),
312333
AFD->diagnose(diag::objc_invalid_on_func_param_type,
313334
AFD, ParamIndex + 1, getObjCDiagnosticAttrKind(Reason),
314-
(unsigned)language)
335+
language)
315336
.limitBehavior(behavior));
316337
}
317338
SourceRange SR;
318339

319340
if (P->hasAttachedPropertyWrapper()) {
320341
auto wrapperTy = P->getPropertyWrapperBackingPropertyType();
321342
SR = P->getOutermostAttachedPropertyWrapper()->getRange();
322-
diagnoseTypeNotRepresentableInObjC(AFD, wrapperTy, SR, behavior);
343+
diagnoseTypeNotRepresentableInObjC(AFD, wrapperTy, SR, behavior, Reason);
323344
} else {
324345
if (auto typeRepr = P->getTypeRepr())
325346
SR = typeRepr->getSourceRange();
326-
diagnoseTypeNotRepresentableInObjC(AFD, P->getTypeInContext(), SR, behavior);
347+
diagnoseTypeNotRepresentableInObjC(AFD, P->getTypeInContext(), SR,
348+
behavior, Reason);
327349
}
328350
Reason.describe(AFD);
329351
}
@@ -345,7 +367,7 @@ static bool isParamListRepresentableInLanguage(const AbstractFunctionDecl *AFD,
345367
if (param->isVariadic()) {
346368
softenIfAccessNote(AFD, Reason.getAttr(),
347369
diags.diagnose(param->getStartLoc(), diag::objc_invalid_on_func_variadic,
348-
getObjCDiagnosticAttrKind(Reason))
370+
AFD, getObjCDiagnosticAttrKind(Reason))
349371
.highlight(param->getSourceRange())
350372
.limitBehavior(behavior));
351373
Reason.describe(AFD);
@@ -358,7 +380,7 @@ static bool isParamListRepresentableInLanguage(const AbstractFunctionDecl *AFD,
358380
softenIfAccessNote(AFD, Reason.getAttr(),
359381
diags.diagnose(param->getStartLoc(), diag::objc_invalid_on_func_inout,
360382
AFD, getObjCDiagnosticAttrKind(Reason),
361-
(unsigned)language)
383+
language)
362384
.highlight(param->getSourceRange())
363385
.limitBehavior(behavior));
364386
Reason.describe(AFD);
@@ -800,11 +822,11 @@ bool swift::isRepresentableInLanguage(
800822
softenIfAccessNote(AFD, Reason.getAttr(),
801823
AFD->diagnose(diag::objc_invalid_on_func_result_type,
802824
FD, getObjCDiagnosticAttrKind(Reason),
803-
(unsigned)language)
825+
language)
804826
.limitBehavior(behavior));
805827
diagnoseTypeNotRepresentableInObjC(FD, ResultType,
806828
FD->getResultTypeSourceRange(),
807-
behavior);
829+
behavior, Reason);
808830
Reason.describe(FD);
809831
return false;
810832
}
@@ -857,11 +879,11 @@ bool swift::isRepresentableInLanguage(
857879
softenIfAccessNote(AFD, Reason.getAttr(),
858880
AFD->diagnose(diag::objc_invalid_on_func_result_type,
859881
FD, getObjCDiagnosticAttrKind(Reason),
860-
(unsigned)language)
882+
language)
861883
.limitBehavior(behavior));
862884
diagnoseTypeNotRepresentableInObjC(FD, type,
863885
FD->getResultTypeSourceRange(),
864-
behavior);
886+
behavior, Reason);
865887
Reason.describe(FD);
866888

867889
return true;
@@ -1168,7 +1190,7 @@ bool swift::isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason) {
11681190
.limitBehavior(behavior));
11691191
diagnoseTypeNotRepresentableInObjC(VD->getDeclContext(),
11701192
VD->getInterfaceType(),
1171-
TypeRange, behavior);
1193+
TypeRange, behavior, Reason);
11721194
Reason.describe(VD);
11731195
}
11741196

@@ -1256,7 +1278,7 @@ bool swift::isRepresentableInObjC(const SubscriptDecl *SD, ObjCReason Reason) {
12561278
diagnoseTypeNotRepresentableInObjC(SD->getDeclContext(),
12571279
!IndexResult ? IndexType
12581280
: ElementType,
1259-
TypeRange, behavior);
1281+
TypeRange, behavior, Reason);
12601282
Reason.describe(SD);
12611283
}
12621284

0 commit comments

Comments
 (0)