@@ -48,6 +48,7 @@ swift::behaviorLimitForObjCReason(ObjCReason reason, ASTContext &ctx) {
4848 LLVM_FALLTHROUGH;
4949
5050 case ObjCReason::ExplicitlyCDecl:
51+ case ObjCReason::ExplicitlyUnderscoreCDecl:
5152 case ObjCReason::ExplicitlyDynamic:
5253 case ObjCReason::ExplicitlyObjC:
5354 case ObjCReason::ExplicitlyObjCMembers:
@@ -81,6 +82,7 @@ swift::behaviorLimitForObjCReason(ObjCReason reason, ASTContext &ctx) {
8182unsigned swift::getObjCDiagnosticAttrKind (ObjCReason reason) {
8283 switch (reason) {
8384 case ObjCReason::ExplicitlyCDecl:
85+ case ObjCReason::ExplicitlyUnderscoreCDecl:
8486 case ObjCReason::ExplicitlyDynamic:
8587 case ObjCReason::ExplicitlyObjC:
8688 case ObjCReason::ExplicitlyObjCMembers:
@@ -132,6 +134,7 @@ void ObjCReason::describe(const Decl *D) const {
132134
133135 case ObjCReason::ExplicitlyObjCByAccessNote:
134136 case ObjCReason::ExplicitlyCDecl:
137+ case ObjCReason::ExplicitlyUnderscoreCDecl:
135138 case ObjCReason::ExplicitlyDynamic:
136139 case ObjCReason::ExplicitlyObjC:
137140 case ObjCReason::ExplicitlyObjCMembers:
@@ -293,18 +296,21 @@ static void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
293296
294297static void diagnoseFunctionParamNotRepresentable (
295298 const AbstractFunctionDecl *AFD, unsigned NumParams,
296- unsigned ParamIndex, const ParamDecl *P, ObjCReason Reason) {
299+ unsigned ParamIndex, const ParamDecl *P, ObjCReason Reason,
300+ ForeignLanguage Language) {
297301 auto behavior = behaviorLimitForObjCReason (Reason, AFD->getASTContext ());
298302
299303 if (NumParams == 1 ) {
300304 softenIfAccessNote (AFD, Reason.getAttr (),
301305 AFD->diagnose (diag::objc_invalid_on_func_single_param_type,
302- getObjCDiagnosticAttrKind (Reason))
306+ AFD, getObjCDiagnosticAttrKind (Reason),
307+ (unsigned )Language)
303308 .limitBehavior (behavior));
304309 } else {
305310 softenIfAccessNote (AFD, Reason.getAttr (),
306311 AFD->diagnose (diag::objc_invalid_on_func_param_type,
307- ParamIndex + 1 , getObjCDiagnosticAttrKind (Reason))
312+ AFD, ParamIndex + 1 , getObjCDiagnosticAttrKind (Reason),
313+ (unsigned )Language)
308314 .limitBehavior (behavior));
309315 }
310316 SourceRange SR;
@@ -321,9 +327,10 @@ static void diagnoseFunctionParamNotRepresentable(
321327 Reason.describe (AFD);
322328}
323329
324- static bool isParamListRepresentableInObjC (const AbstractFunctionDecl *AFD,
325- const ParameterList *PL,
326- ObjCReason Reason) {
330+ static bool isParamListRepresentableInLanguage (const AbstractFunctionDecl *AFD,
331+ const ParameterList *PL,
332+ ObjCReason Reason,
333+ ForeignLanguage Language) {
327334 // If you change this function, you must add or modify a test in PrintAsClang.
328335 ASTContext &ctx = AFD->getASTContext ();
329336 auto &diags = ctx.Diags ;
@@ -349,7 +356,7 @@ static bool isParamListRepresentableInObjC(const AbstractFunctionDecl *AFD,
349356 if (param->isInOut ()) {
350357 softenIfAccessNote (AFD, Reason.getAttr (),
351358 diags.diagnose (param->getStartLoc (), diag::objc_invalid_on_func_inout,
352- getObjCDiagnosticAttrKind (Reason))
359+ AFD, getObjCDiagnosticAttrKind (Reason), ( unsigned )Language )
353360 .highlight (param->getSourceRange ())
354361 .limitBehavior (behavior));
355362 Reason.describe (AFD);
@@ -362,11 +369,11 @@ static bool isParamListRepresentableInObjC(const AbstractFunctionDecl *AFD,
362369
363370 if (param->hasAttachedPropertyWrapper ()) {
364371 if (param->getPropertyWrapperBackingPropertyType ()->isRepresentableIn (
365- ForeignLanguage::ObjectiveC ,
372+ Language ,
366373 const_cast <AbstractFunctionDecl *>(AFD)))
367374 continue ;
368375 } else if (param->getTypeInContext ()->isRepresentableIn (
369- ForeignLanguage::ObjectiveC ,
376+ Language ,
370377 const_cast <AbstractFunctionDecl *>(AFD))) {
371378 continue ;
372379 }
@@ -387,7 +394,7 @@ static bool isParamListRepresentableInObjC(const AbstractFunctionDecl *AFD,
387394
388395 IsObjC = false ;
389396 diagnoseFunctionParamNotRepresentable (AFD, NumParams, ParamIndex,
390- param, Reason);
397+ param, Reason, Language );
391398 }
392399 return IsObjC;
393400}
@@ -645,14 +652,16 @@ static bool isValidObjectiveCErrorResultType(DeclContext *dc, Type type) {
645652 llvm_unreachable (" Unhandled ForeignRepresentableKind in switch." );
646653}
647654
648- bool swift::isRepresentableInObjC (
655+ bool swift::isRepresentableInLanguage (
649656 const AbstractFunctionDecl *AFD, ObjCReason Reason,
650657 std::optional<ForeignAsyncConvention> &asyncConvention,
651- std::optional<ForeignErrorConvention> &errorConvention) {
658+ std::optional<ForeignErrorConvention> &errorConvention,
659+ ForeignLanguage Language) {
652660 auto abiRole = ABIRoleInfo (AFD);
653661 if (!abiRole.providesAPI () && abiRole.getCounterpart ())
654- return isRepresentableInObjC (abiRole.getCounterpart (), Reason,
655- asyncConvention, errorConvention);
662+ return isRepresentableInLanguage (abiRole.getCounterpart (), Reason,
663+ asyncConvention, errorConvention,
664+ Language);
656665
657666 // Clear out the async and error conventions. They will be added later if
658667 // needed.
@@ -688,6 +697,7 @@ bool swift::isRepresentableInObjC(
688697 auto storage = accessor->getStorage ();
689698 bool storageIsObjC = storage->isObjC ()
690699 || Reason == ObjCReason::ExplicitlyCDecl
700+ || Reason == ObjCReason::ExplicitlyUnderscoreCDecl
691701 || Reason == ObjCReason::WitnessToObjC
692702 || Reason == ObjCReason::MemberOfObjCProtocol;
693703
@@ -773,9 +783,10 @@ bool swift::isRepresentableInObjC(
773783 isSpecialInit = init->isObjCZeroParameterWithLongSelector ();
774784
775785 if (!isSpecialInit &&
776- !isParamListRepresentableInObjC (AFD,
777- AFD->getParameters (),
778- Reason)) {
786+ !isParamListRepresentableInLanguage (AFD,
787+ AFD->getParameters (),
788+ Reason,
789+ Language)) {
779790 return false ;
780791 }
781792
@@ -785,11 +796,12 @@ bool swift::isRepresentableInObjC(
785796 !ResultType->hasError () &&
786797 !ResultType->isVoid () &&
787798 !ResultType->isUninhabited () &&
788- !ResultType->isRepresentableIn (ForeignLanguage::ObjectiveC ,
799+ !ResultType->isRepresentableIn (Language ,
789800 const_cast <FuncDecl *>(FD))) {
790801 softenIfAccessNote (AFD, Reason.getAttr (),
791802 AFD->diagnose (diag::objc_invalid_on_func_result_type,
792- getObjCDiagnosticAttrKind (Reason))
803+ FD, getObjCDiagnosticAttrKind (Reason),
804+ (unsigned )Language)
793805 .limitBehavior (behavior));
794806 diagnoseTypeNotRepresentableInObjC (FD, ResultType,
795807 FD->getResultTypeSourceRange (),
@@ -842,11 +854,11 @@ bool swift::isRepresentableInObjC(
842854 completionHandlerParams.push_back (AnyFunctionType::Param (type));
843855
844856 // Make sure that the parameter type is representable in Objective-C.
845- if (!type->isRepresentableIn (
846- ForeignLanguage::ObjectiveC, const_cast <FuncDecl *>(FD))) {
857+ if (!type->isRepresentableIn (Language, const_cast <FuncDecl *>(FD))) {
847858 softenIfAccessNote (AFD, Reason.getAttr (),
848859 AFD->diagnose (diag::objc_invalid_on_func_result_type,
849- getObjCDiagnosticAttrKind (Reason))
860+ FD, getObjCDiagnosticAttrKind (Reason),
861+ (unsigned )Language)
850862 .limitBehavior (behavior));
851863 diagnoseTypeNotRepresentableInObjC (FD, type,
852864 FD->getResultTypeSourceRange (),
@@ -1260,8 +1272,10 @@ bool swift::canBeRepresentedInObjC(const ValueDecl *decl) {
12601272 if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
12611273 std::optional<ForeignAsyncConvention> asyncConvention;
12621274 std::optional<ForeignErrorConvention> errorConvention;
1263- return isRepresentableInObjC (func, ObjCReason::MemberOfObjCMembersClass,
1264- asyncConvention, errorConvention);
1275+ return isRepresentableInLanguage (func,
1276+ ObjCReason::MemberOfObjCMembersClass,
1277+ asyncConvention, errorConvention,
1278+ ForeignLanguage::ObjectiveC);
12651279 }
12661280
12671281 if (auto var = dyn_cast<VarDecl>(decl))
@@ -1865,8 +1879,9 @@ bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
18651879 } else if (isa<DestructorDecl>(VD)) {
18661880 // Destructors need no additional checking.
18671881 } else if (auto func = dyn_cast<AbstractFunctionDecl>(VD)) {
1868- if (!isRepresentableInObjC (
1869- func, *isObjC, asyncConvention, errorConvention)) {
1882+ if (!isRepresentableInLanguage (
1883+ func, *isObjC, asyncConvention, errorConvention,
1884+ ForeignLanguage::ObjectiveC)) {
18701885 isObjC->setAttrInvalid ();
18711886 return false ;
18721887 }
@@ -4150,17 +4165,25 @@ TypeCheckCDeclAttributeRequest::evaluate(Evaluator &evaluator,
41504165 CDeclAttr *attr) const {
41514166 auto &ctx = FD->getASTContext ();
41524167
4168+ auto lang = FD->getCDeclKind ();
4169+ assert (lang && " missing @cdecl?" );
4170+ auto kind = lang == ForeignLanguage::ObjectiveC
4171+ ? ObjCReason::ExplicitlyUnderscoreCDecl
4172+ : ObjCReason::ExplicitlyCDecl;
4173+ ObjCReason reason (kind, attr);
4174+
41534175 std::optional<ForeignAsyncConvention> asyncConvention;
41544176 std::optional<ForeignErrorConvention> errorConvention;
4155- ObjCReason reason (ObjCReason::ExplicitlyCDecl, attr);
4156- if ( isRepresentableInObjC (FD, reason, asyncConvention, errorConvention )) {
4177+ if ( isRepresentableInLanguage (FD, reason, asyncConvention, errorConvention,
4178+ *lang )) {
41574179 if (FD->hasAsync ()) {
41584180 FD->setForeignAsyncConvention (*asyncConvention);
41594181 ctx.Diags .diagnose (attr->getLocation (), diag::attr_decl_async,
41604182 attr, FD);
41614183 } else if (FD->hasThrows ()) {
41624184 FD->setForeignErrorConvention (*errorConvention);
4163- ctx.Diags .diagnose (attr->getLocation (), diag::cdecl_throws);
4185+ ctx.Diags .diagnose (attr->getLocation (), diag::cdecl_throws,
4186+ attr);
41644187 }
41654188 } else {
41664189 reason.setAttrInvalid ();
0 commit comments