@@ -2538,58 +2538,78 @@ void AttributeChecker::visitExposeAttr(ExposeAttr *attr) {
25382538 }
25392539}
25402540
2541- bool IsCCompatibleFuncDeclRequest ::evaluate (Evaluator &evaluator,
2542- FuncDecl *FD ) const {
2543- if (FD ->isInvalid ())
2541+ bool IsCCompatibleDeclRequest ::evaluate (Evaluator &evaluator,
2542+ ValueDecl *VD ) const {
2543+ if (VD ->isInvalid ())
25442544 return false ;
25452545
2546- bool foundError = false ;
2547-
2548- if (FD->hasAsync ()) {
2549- FD->diagnose (diag::c_func_async);
2550- foundError = true ;
2551- }
2552-
2553- if (FD->hasThrows ()) {
2554- FD->diagnose (diag::c_func_throws);
2555- foundError = true ;
2556- }
2557-
2558- // --- Check for unsupported result types.
2559- Type resultTy = FD->getResultInterfaceType ();
2560- if (!resultTy->isVoid () && !resultTy->isRepresentableIn (ForeignLanguage::C, FD)) {
2561- FD->diagnose (diag::c_func_unsupported_type, resultTy);
2562- foundError = true ;
2563- }
2546+ if (auto FD = dyn_cast<FuncDecl>(VD)) {
2547+ bool foundError = false ;
25642548
2565- for (auto *param : *FD->getParameters ()) {
2566- // --- Check for unsupported specifiers.
2567- if (param->isVariadic ()) {
2568- FD->diagnose (diag::c_func_variadic, param->getName (), FD);
2549+ if (FD->hasAsync ()) {
2550+ FD->diagnose (diag::c_func_async);
25692551 foundError = true ;
25702552 }
2571- if (param->getSpecifier () != ParamSpecifier::Default) {
2572- param
2573- ->diagnose (diag::c_func_unsupported_specifier,
2574- ParamDecl::getSpecifierSpelling (param->getSpecifier ()),
2575- param->getName (), FD)
2576- .fixItRemove (param->getSpecifierLoc ());
2553+
2554+ if (FD->hasThrows ()) {
2555+ FD->diagnose (diag::c_func_throws);
25772556 foundError = true ;
25782557 }
25792558
2580- // --- Check for unsupported parameter types.
2581- auto paramTy = param-> getTypeInContext ();
2582- if (!paramTy ->isRepresentableIn (ForeignLanguage::C, FD)) {
2583- param ->diagnose (diag::c_func_unsupported_type, paramTy );
2559+ // --- Check for unsupported result types.
2560+ Type resultTy = FD-> getResultInterfaceType ();
2561+ if (!resultTy-> isVoid () && !resultTy ->isRepresentableIn (ForeignLanguage::C, FD)) {
2562+ FD ->diagnose (diag::c_unsupported_type, resultTy );
25842563 foundError = true ;
25852564 }
2565+
2566+ for (auto *param : *FD->getParameters ()) {
2567+ // --- Check for unsupported specifiers.
2568+ if (param->isVariadic ()) {
2569+ FD->diagnose (diag::c_func_variadic, param->getName (), FD);
2570+ foundError = true ;
2571+ }
2572+ if (param->getSpecifier () != ParamSpecifier::Default) {
2573+ param
2574+ ->diagnose (diag::c_func_unsupported_specifier,
2575+ ParamDecl::getSpecifierSpelling (param->getSpecifier ()),
2576+ param->getName (), FD)
2577+ .fixItRemove (param->getSpecifierLoc ());
2578+ foundError = true ;
2579+ }
2580+
2581+ // --- Check for unsupported parameter types.
2582+ auto paramTy = param->getTypeInContext ();
2583+ if (!paramTy->isRepresentableIn (ForeignLanguage::C, FD)) {
2584+ param->diagnose (diag::c_unsupported_type, paramTy);
2585+ foundError = true ;
2586+ }
2587+ }
2588+ return !foundError;
25862589 }
2587- return !foundError;
2590+
2591+ if (auto var = dyn_cast<VarDecl>(VD)) {
2592+ Type varType = var->getInterfaceType ();
2593+ if (!varType->isRepresentableIn (ForeignLanguage::C,
2594+ var->getDeclContext ())) {
2595+ var->diagnose (diag::c_unsupported_type, varType);
2596+ return true ;
2597+ }
2598+
2599+ if (!var->hasStorage ()) {
2600+ var->diagnose (diag::c_var_computed);
2601+ return false ;
2602+ }
2603+
2604+ return true ;
2605+ }
2606+
2607+ return false ;
25882608}
25892609
2590- static bool isCCompatibleFuncDecl (FuncDecl *FD ) {
2591- return evaluateOrDefault (FD ->getASTContext ().evaluator ,
2592- IsCCompatibleFuncDeclRequest{FD }, {});
2610+ static bool isCCompatibleDecl (ValueDecl *VD ) {
2611+ return evaluateOrDefault (VD ->getASTContext ().evaluator ,
2612+ IsCCompatibleDeclRequest{VD }, {});
25932613}
25942614
25952615void AttributeChecker::visitExternAttr (ExternAttr *attr) {
@@ -2598,17 +2618,27 @@ void AttributeChecker::visitExternAttr(ExternAttr *attr) {
25982618 diagnoseAndRemoveAttr (attr, diag::attr_extern_experimental);
25992619 return ;
26002620 }
2601-
2602- // Only top-level func or static func decls are currently supported.
2603- auto *FD = dyn_cast<FuncDecl>(D);
2604- if (!FD || (FD->getDeclContext ()->isTypeContext () && !FD->isStatic ())) {
2605- diagnose (attr->getLocation (), diag::extern_not_at_top_level_func);
2606- }
26072621
2622+ auto VD = dyn_cast<ValueDecl>(D);
2623+ if (!VD)
2624+ return ;
2625+
2626+ // Check the declaration context.
2627+ // FIXME: Unify this with @c / @_cdecl checking.
2628+ if (VD->getDeclContext ()->isModuleScopeContext ()) {
2629+ // Top-level declarations are okay.
2630+ } else if (VD->getDeclContext ()->isTypeContext () &&
2631+ !VD->getDeclContext ()->getGenericSignatureOfContext () &&
2632+ ((isa<FuncDecl>(VD) && cast<FuncDecl>(VD)->isStatic ()) ||
2633+ (isa<VarDecl>(VD) && cast<VarDecl>(VD)->isStatic ()))) {
2634+ // Static members of non-generic types are okay.
2635+ } else {
2636+ diagnose (attr->getLocation (), diag::extern_not_at_top_level);
2637+ }
26082638
26092639 // C name must not be empty.
26102640 if (attr->getExternKind () == ExternKind::C) {
2611- StringRef cName = attr->getCName (FD );
2641+ StringRef cName = attr->getCName (VD );
26122642 if (cName.empty ()) {
26132643 diagnose (attr->getLocation (), diag::extern_empty_c_name);
26142644 } else if (!attr->Name .has_value () && !clang::isValidAsciiIdentifier (cName)) {
@@ -2630,10 +2660,10 @@ void AttributeChecker::visitExternAttr(ExternAttr *attr) {
26302660 }
26312661
26322662 // Ensure the decl has C compatible interface. Otherwise it produces diagnostics.
2633- if (!isCCompatibleFuncDecl (FD )) {
2663+ if (!isCCompatibleDecl (VD )) {
26342664 attr->setInvalid ();
26352665 // Mark the decl itself invalid not to require body even with invalid ExternAttr.
2636- FD ->setInvalid ();
2666+ VD ->setInvalid ();
26372667 }
26382668 }
26392669
@@ -5715,7 +5745,9 @@ TypeChecker::diagnosticIfDeclCannotBeUnavailable(const Decl *D,
57155745static bool shouldBlockImplicitDynamic (Decl *D) {
57165746 if (D->getAttrs ().hasAttribute <SILGenNameAttr>() ||
57175747 D->getAttrs ().hasAttribute <TransparentAttr>() ||
5718- D->getAttrs ().hasAttribute <InlinableAttr>())
5748+ D->getAttrs ().hasAttribute <InlinableAttr>() ||
5749+ D->getAttrs ().hasAttribute <CDeclAttr>() ||
5750+ D->getAttrs ().hasAttribute <ExternAttr>())
57195751 return true ;
57205752 return false ;
57215753}
0 commit comments