Skip to content

Commit fc77dc5

Browse files
committed
Parser: Intro @cdecl attribute and gate it behind feature flag CDecl
1 parent 031ec43 commit fc77dc5

File tree

11 files changed

+51
-12
lines changed

11 files changed

+51
-12
lines changed

include/swift/AST/Attr.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -694,22 +694,29 @@ class SectionAttr : public DeclAttribute {
694694
/// Defines the @_cdecl attribute.
695695
class CDeclAttr : public DeclAttribute {
696696
public:
697-
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit)
698-
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit), Name(Name) {
697+
CDeclAttr(StringRef Name, SourceLoc AtLoc, SourceRange Range, bool Implicit,
698+
bool Underscored)
699+
: DeclAttribute(DeclAttrKind::CDecl, AtLoc, Range, Implicit),
700+
Name(Name), Underscored(Underscored) {
699701
}
700702

701-
CDeclAttr(StringRef Name, bool Implicit)
702-
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit) {}
703+
CDeclAttr(StringRef Name, bool Implicit, bool Underscored)
704+
: CDeclAttr(Name, SourceLoc(), SourceRange(), Implicit, Underscored) {}
703705

704706
/// The symbol name.
705707
const StringRef Name;
706708

709+
/// Is this the version of the attribute that's underscored?
710+
/// Used to preserve retro compatibility with early adopters.
711+
const bool Underscored;
712+
707713
static bool classof(const DeclAttribute *DA) {
708714
return DA->getKind() == DeclAttrKind::CDecl;
709715
}
710716

711717
CDeclAttr *clone(ASTContext &ctx) const {
712-
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit());
718+
return new (ctx) CDeclAttr(Name, AtLoc, Range, isImplicit(),
719+
Underscored);
713720
}
714721

715722
bool isEquivalent(const CDeclAttr *other, Decl *attachedTo) const {

include/swift/AST/DeclAttr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ DECL_ATTR(_cdecl, CDecl,
368368
OnFunc | OnAccessor,
369369
LongAttribute | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
370370
63)
371+
DECL_ATTR_ALIAS(cdecl, CDecl)
371372

372373
SIMPLE_DECL_ATTR(usableFromInline, UsableFromInline,
373374
OnAbstractFunction | OnVar | OnSubscript | OnNominalType | OnTypeAlias,

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,9 @@ ERROR(cdecl_empty_name,none,
20362036
"@_cdecl symbol name cannot be empty", ())
20372037
ERROR(cdecl_throws,none,
20382038
"raising errors from @_cdecl functions is not supported", ())
2039+
ERROR(cdecl_feature_required,none,
2040+
"@cdecl requires '-enable-experimental-feature CDecl'",
2041+
())
20392042

20402043
// @_used and @_section
20412044
ERROR(section_linkage_markers_disabled,none,

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,9 @@ EXPERIMENTAL_FEATURE(ClosureBodyMacro, true)
519519
/// Allow declarations of Swift runtime symbols using @_silgen_name.
520520
EXPERIMENTAL_FEATURE(AllowRuntimeSymbolDeclarations, true)
521521

522+
/// Allow use of `@cdecl`
523+
EXPERIMENTAL_FEATURE(CDecl, false)
524+
522525
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
523526
#undef EXPERIMENTAL_FEATURE
524527
#undef UPCOMING_FEATURE

lib/AST/Attr.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1809,7 +1809,9 @@ StringRef DeclAttribute::getAttrName() const {
18091809
case DeclAttrKind::Alignment:
18101810
return "_alignment";
18111811
case DeclAttrKind::CDecl:
1812-
return "_cdecl";
1812+
if (cast<CDeclAttr>(this)->Underscored)
1813+
return "_cdecl";
1814+
return "cdecl";
18131815
case DeclAttrKind::SwiftNativeObjCRuntimeBase:
18141816
return "_swift_native_objc_runtime_base";
18151817
case DeclAttrKind::Semantics:

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
250250
BridgedStringRef cName) {
251251
return new (cContext.unbridged())
252252
CDeclAttr(cName.unbridged(), cAtLoc.unbridged(), cRange.unbridged(),
253-
/*Implicit=*/false);
253+
/*Implicit=*/false, /*Underscored*/false);
254254
}
255255

256256
BridgedCustomAttr BridgedCustomAttr_createParsed(

lib/AST/FeatureSet.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,11 @@ static bool usesFeatureClosureBodyMacro(Decl *decl) {
392392
return false;
393393
}
394394

395+
static bool usesFeatureCDecl(Decl *decl) {
396+
auto attr = decl->getAttrs().getAttribute<CDeclAttr>();
397+
return attr && !attr->Underscored;
398+
}
399+
395400
static bool usesFeatureMemorySafetyAttributes(Decl *decl) {
396401
if (decl->getAttrs().hasAttribute<SafeAttr>() ||
397402
decl->getAttrs().hasAttribute<UnsafeAttr>())

lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3074,10 +3074,12 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
30743074
if (DK == DeclAttrKind::SILGenName)
30753075
Attributes.add(new (Context) SILGenNameAttr(AsmName.value(), Raw, AtLoc,
30763076
AttrRange, /*Implicit=*/false));
3077-
else if (DK == DeclAttrKind::CDecl)
3077+
else if (DK == DeclAttrKind::CDecl) {
3078+
bool underscored = AttrName.starts_with("_");
30783079
Attributes.add(new (Context) CDeclAttr(AsmName.value(), AtLoc,
3079-
AttrRange, /*Implicit=*/false));
3080-
else if (DK == DeclAttrKind::Expose) {
3080+
AttrRange, /*Implicit=*/false,
3081+
/*isUnderscored*/underscored));
3082+
} else if (DK == DeclAttrKind::Expose) {
30813083
for (auto *EA : Attributes.getAttributes<ExposeAttr>()) {
30823084
// A single declaration cannot have two @_exported attributes with
30833085
// the same exposure kind.

lib/Sema/TypeCheckAttr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,6 +2367,11 @@ void AttributeChecker::visitCDeclAttr(CDeclAttr *attr) {
23672367
diagnose(attr->getLocation(), diag::reserved_runtime_symbol_name,
23682368
attr->Name);
23692369
}
2370+
2371+
if (!attr->Underscored &&
2372+
!Ctx.LangOpts.hasFeature(Feature::CDecl)) {
2373+
Ctx.Diags.diagnose(attr->getLocation(), diag::cdecl_feature_required);
2374+
}
23702375
}
23712376

23722377
void AttributeChecker::visitExposeAttr(ExposeAttr *attr) {

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5993,9 +5993,10 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
59935993

59945994
case decls_block::CDecl_DECL_ATTR: {
59955995
bool isImplicit;
5996+
bool isUnderscored = false;
59965997
serialization::decls_block::CDeclDeclAttrLayout::readRecord(
5997-
scratch, isImplicit);
5998-
Attr = new (ctx) CDeclAttr(blobData, isImplicit);
5998+
scratch, isImplicit); // TODO isUnderscored
5999+
Attr = new (ctx) CDeclAttr(blobData, isImplicit, isUnderscored);
59996000
break;
60006001
}
60016002

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// RUN: %target-swift-frontend -typecheck %s \
3+
// RUN: -enable-experimental-feature CDecl
4+
5+
@cdecl("cdecl_foo") func foo() { } // expected-error {{@cdecl requires '-enable-experimental-feature CDecl'}}
6+
7+
var computed: Int {
8+
@cdecl("get_computed") get { return 0 } // expected-error {{@cdecl requires '-enable-experimental-feature CDecl'}}
9+
@cdecl("set_computed") set { } // expected-error {{@cdecl requires '-enable-experimental-feature CDecl'}}
10+
}

0 commit comments

Comments
 (0)