Skip to content

Commit b130ece

Browse files
Merge pull request #31220 from nate-chandler/main-attribute-53
[5.3] @main: Attribute to add an entry point to a type.
2 parents 43c4db2 + da9eaad commit b130ece

File tree

68 files changed

+925
-67
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+925
-67
lines changed

include/swift/AST/Attr.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,10 @@ SIMPLE_DECL_ATTR(dynamicCallable, DynamicCallable,
147147
OnNominalType |
148148
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
149149
6)
150-
// NOTE: 7 is unused
150+
SIMPLE_DECL_ATTR(main, MainType,
151+
OnClass | OnStruct | OnEnum | OnExtension |
152+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
153+
7)
151154
SIMPLE_DECL_ATTR(_exported, Exported,
152155
OnImport |
153156
UserInaccessible |

include/swift/AST/Decl.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ bool conflicting(ASTContext &ctx,
272272
bool *wouldConflictInSwift5 = nullptr,
273273
bool skipProtocolExtensionCheck = false);
274274

275+
/// The kind of artificial main to generate.
276+
enum class ArtificialMainKind : uint8_t {
277+
NSApplicationMain,
278+
UIApplicationMain,
279+
TypeMain,
280+
};
281+
275282
/// Decl - Base class for all declarations in Swift.
276283
class alignas(1 << DeclAlignInBits) Decl {
277284
protected:
@@ -779,6 +786,13 @@ class alignas(1 << DeclAlignInBits) Decl {
779786

780787
SourceLoc TrailingSemiLoc;
781788

789+
/// Returns the appropriate kind of entry point to generate for this class,
790+
/// based on its attributes.
791+
///
792+
/// It is an error to call this on a type that does not have either an
793+
/// *ApplicationMain or an main attribute.
794+
ArtificialMainKind getArtificialMainKind() const;
795+
782796
SWIFT_DEBUG_DUMP;
783797
SWIFT_DEBUG_DUMPER(dump(const char *filename));
784798
void dump(raw_ostream &OS, unsigned Indent = 0) const;
@@ -3810,12 +3824,6 @@ class StructDecl final : public NominalTypeDecl {
38103824
}
38113825
};
38123826

3813-
/// The kind of artificial main to generate for a class.
3814-
enum class ArtificialMainKind : uint8_t {
3815-
NSApplicationMain,
3816-
UIApplicationMain,
3817-
};
3818-
38193827
/// This is the base type for AncestryOptions. Each flag describes possible
38203828
/// interesting kinds of superclasses that a class may have.
38213829
enum class AncestryFlags : uint8_t {
@@ -4083,13 +4091,6 @@ class ClassDecl final : public NominalTypeDecl {
40834091
/// the Objective-C runtime.
40844092
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
40854093

4086-
/// Returns the appropriate kind of entry point to generate for this class,
4087-
/// based on its attributes.
4088-
///
4089-
/// It is an error to call this on a class that does not have a
4090-
/// *ApplicationMain attribute.
4091-
ArtificialMainKind getArtificialMainKind() const;
4092-
40934094
using NominalTypeDecl::lookupDirect;
40944095

40954096
/// Look in this class and its extensions (but not any of its protocols or
@@ -6293,6 +6294,8 @@ class FuncDecl : public AbstractFunctionDecl {
62936294
}
62946295
bool isCallAsFunctionMethod() const;
62956296

6297+
bool isMainTypeMainMethod() const;
6298+
62966299
SelfAccessKind getSelfAccessKind() const;
62976300

62986301
void setSelfAccessKind(SelfAccessKind mod) {

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2893,17 +2893,19 @@ ERROR(nscopying_doesnt_conform,none,
28932893
" the NSCopying protocol", ())
28942894

28952895
// UIApplicationMain/NSApplicationMain attribute
2896-
#define SELECT_APPLICATION_MAIN "select{'UIApplicationMain'|'NSApplicationMain'}"
2896+
#define SELECT_APPLICATION_MAIN "select{'UIApplicationMain'|'NSApplicationMain'|'main'}"
28972897
#define SELECT_APPLICATION_DELEGATE "select{'UIApplicationDelegate'|'NSApplicationDelegate'}"
2898+
#define SELECT_APPLICATION_TYPE "select{class|class|type}"
2899+
#define SELECT_APPLICATION_TYPES "select{classes|classes|types}"
28982900

28992901
ERROR(attr_ApplicationMain_not_ApplicationDelegate,none,
29002902
"%" SELECT_APPLICATION_MAIN "0 class must conform to the %" SELECT_APPLICATION_DELEGATE "0 protocol",
29012903
(unsigned))
29022904
ERROR(attr_generic_ApplicationMain_not_supported,none,
2903-
"generic %" SELECT_APPLICATION_MAIN "0 classes are not supported",
2905+
"generic %" SELECT_APPLICATION_MAIN "0 %" SELECT_APPLICATION_TYPES "0 are not supported",
29042906
(unsigned))
29052907
ERROR(attr_ApplicationMain_multiple,none,
2906-
"%" SELECT_APPLICATION_MAIN "0 attribute can only apply to one class in a module",
2908+
"%" SELECT_APPLICATION_MAIN "0 attribute can only apply to one %" SELECT_APPLICATION_TYPE "0 in a module",
29072909
(unsigned))
29082910
ERROR(attr_ApplicationMain_with_script,none,
29092911
"%" SELECT_APPLICATION_MAIN "0 attribute cannot be used in a module that contains "
@@ -2913,6 +2915,10 @@ NOTE(attr_ApplicationMain_script_here,none,
29132915
"top-level code defined in this source file",
29142916
())
29152917

2918+
ERROR(attr_MainType_without_main,none,
2919+
"%0 is annotated with @main and must provide a main static function of type () -> Void or () throws -> Void.",
2920+
(DeclName))
2921+
29162922
#undef SELECT_APPLICATION_MAIN
29172923
#undef SELECT_APPLICATION_DELEGATE
29182924

include/swift/AST/FileUnit.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,13 @@ class FileUnit : public DeclContext {
260260
bool hasMainClass() const {
261261
return getMainClass();
262262
}
263-
virtual ClassDecl *getMainClass() const {
264-
assert(hasEntryPoint());
265-
return nullptr;
263+
ClassDecl *getMainClass() const {
264+
return dyn_cast_or_null<ClassDecl>(getMainDecl());
265+
}
266+
bool hasMainDecl() const { return getMainDecl(); }
267+
virtual Decl *getMainDecl() const { return nullptr; }
268+
FuncDecl *getMainFunc() const {
269+
return dyn_cast_or_null<FuncDecl>(getMainDecl());
266270
}
267271
virtual bool hasEntryPoint() const {
268272
return false;

include/swift/AST/KnownIdentifiers.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ IDENTIFIER(keyPath)
9292
IDENTIFIER(makeIterator)
9393
IDENTIFIER(Iterator)
9494
IDENTIFIER(load)
95+
IDENTIFIER(main)
96+
IDENTIFIER_WITH_NAME(MainEntryPoint, "$main")
9597
IDENTIFIER(next)
9698
IDENTIFIER_(nsErrorDomain)
9799
IDENTIFIER(objectAtIndexedSubscript)

include/swift/AST/SourceFile.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,12 @@ class SourceFile final : public FileUnit {
148148
Optional<ReferencedNameTracker> ReferencedNames;
149149
Optional<ReferencedNameTracker> RequestReferencedNames;
150150

151-
/// The class in this file marked \@NS/UIApplicationMain.
152-
ClassDecl *MainClass = nullptr;
151+
/// Either the class marked \@NS/UIApplicationMain or the synthesized FuncDecl
152+
/// that calls main on the type marked @main.
153+
Decl *MainDecl = nullptr;
153154

154-
/// The source location of the main class.
155-
SourceLoc MainClassDiagLoc;
155+
/// The source location of the main type.
156+
SourceLoc MainDeclDiagLoc;
156157

157158
/// A hash of all interface-contributing tokens that have been lexed for
158159
/// this source file so far.
@@ -555,26 +556,28 @@ class SourceFile final : public FileUnit {
555556
llvm_unreachable("bad SourceFileKind");
556557
}
557558

558-
ClassDecl *getMainClass() const override {
559-
return MainClass;
559+
Decl *getMainDecl() const override { return MainDecl; }
560+
SourceLoc getMainDeclDiagLoc() const {
561+
assert(hasMainDecl());
562+
return MainDeclDiagLoc;
560563
}
561564
SourceLoc getMainClassDiagLoc() const {
562565
assert(hasMainClass());
563-
return MainClassDiagLoc;
566+
return getMainDeclDiagLoc();
564567
}
565568

566569
/// Register a "main" class for the module, complaining if there is more than
567570
/// one.
568571
///
569572
/// Should only be called during type-checking.
570-
bool registerMainClass(ClassDecl *mainClass, SourceLoc diagLoc);
573+
bool registerMainDecl(Decl *mainDecl, SourceLoc diagLoc);
571574

572575
/// True if this source file has an application entry point.
573576
///
574577
/// This is true if the source file either is in script mode or contains
575578
/// a designated main class.
576579
bool hasEntryPoint() const override {
577-
return isScriptMode() || hasMainClass();
580+
return isScriptMode() || hasMainDecl();
578581
}
579582

580583
/// Get the root refinement context for the file. The root context may be

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ class SerializedASTFile final : public LoadedFile {
410410

411411
virtual StringRef getModuleDefiningPath() const override;
412412

413-
ClassDecl *getMainClass() const override;
413+
Decl *getMainDecl() const override;
414414

415415
bool hasEntryPoint() const override;
416416

lib/AST/Decl.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4437,12 +4437,14 @@ StringRef ClassDecl::getObjCRuntimeName(
44374437
return mangleObjCRuntimeName(this, buffer);
44384438
}
44394439

4440-
ArtificialMainKind ClassDecl::getArtificialMainKind() const {
4440+
ArtificialMainKind Decl::getArtificialMainKind() const {
44414441
if (getAttrs().hasAttribute<UIApplicationMainAttr>())
44424442
return ArtificialMainKind::UIApplicationMain;
44434443
if (getAttrs().hasAttribute<NSApplicationMainAttr>())
44444444
return ArtificialMainKind::NSApplicationMain;
4445-
llvm_unreachable("class has no @ApplicationMain attr?!");
4445+
if (isa<FuncDecl>(this))
4446+
return ArtificialMainKind::TypeMain;
4447+
llvm_unreachable("type has no @Main attr?!");
44464448
}
44474449

44484450
static bool isOverridingDecl(const ValueDecl *Derived,
@@ -7327,6 +7329,12 @@ bool FuncDecl::isCallAsFunctionMethod() const {
73277329
isInstanceMember();
73287330
}
73297331

7332+
bool FuncDecl::isMainTypeMainMethod() const {
7333+
return (getBaseIdentifier() == getASTContext().Id_main) &&
7334+
!isInstanceMember() && getResultInterfaceType()->isVoid() &&
7335+
getParameters()->size() == 0;
7336+
}
7337+
73307338
ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
73317339
bool Failable, SourceLoc FailabilityLoc,
73327340
bool Throws,

lib/AST/Module.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,16 +1570,17 @@ bool ModuleDecl::isBuiltinModule() const {
15701570
return this == getASTContext().TheBuiltinModule;
15711571
}
15721572

1573-
bool SourceFile::registerMainClass(ClassDecl *mainClass, SourceLoc diagLoc) {
1574-
if (mainClass == MainClass)
1573+
bool SourceFile::registerMainDecl(Decl *mainDecl, SourceLoc diagLoc) {
1574+
if (mainDecl == MainDecl)
15751575
return false;
15761576

1577-
ArtificialMainKind kind = mainClass->getArtificialMainKind();
1577+
ArtificialMainKind kind = mainDecl->getArtificialMainKind();
15781578
if (getParentModule()->registerEntryPointFile(this, diagLoc, kind))
15791579
return true;
15801580

1581-
MainClass = mainClass;
1582-
MainClassDiagLoc = diagLoc;
1581+
MainDecl = mainDecl;
1582+
MainDeclDiagLoc = diagLoc;
1583+
15831584
return false;
15841585
}
15851586

@@ -1599,53 +1600,59 @@ bool ModuleDecl::registerEntryPointFile(FileUnit *file, SourceLoc diagLoc,
15991600
enum : unsigned {
16001601
UIApplicationMainClass = 0,
16011602
NSApplicationMainClass = 1,
1602-
} mainClassDiagKind;
1603+
MainType = 2,
1604+
} mainTypeDiagKind;
16031605

16041606
switch (kind.getValue()) {
16051607
case ArtificialMainKind::UIApplicationMain:
1606-
mainClassDiagKind = UIApplicationMainClass;
1608+
mainTypeDiagKind = UIApplicationMainClass;
16071609
break;
16081610
case ArtificialMainKind::NSApplicationMain:
1609-
mainClassDiagKind = NSApplicationMainClass;
1611+
mainTypeDiagKind = NSApplicationMainClass;
1612+
break;
1613+
case ArtificialMainKind::TypeMain:
1614+
mainTypeDiagKind = MainType;
16101615
break;
16111616
}
16121617

16131618
FileUnit *existingFile = EntryPointInfo.getEntryPointFile();
1614-
const ClassDecl *existingClass = existingFile->getMainClass();
1619+
const Decl *existingDecl = existingFile->getMainDecl();
16151620
SourceLoc existingDiagLoc;
16161621

16171622
if (auto *sourceFile = dyn_cast<SourceFile>(existingFile)) {
1618-
if (existingClass) {
1619-
existingDiagLoc = sourceFile->getMainClassDiagLoc();
1623+
if (existingDecl) {
1624+
existingDiagLoc = sourceFile->getMainDeclDiagLoc();
16201625
} else {
16211626
if (auto bufID = sourceFile->getBufferID())
16221627
existingDiagLoc = getASTContext().SourceMgr.getLocForBufferStart(*bufID);
16231628
}
16241629
}
16251630

1626-
if (existingClass) {
1631+
if (existingDecl) {
16271632
if (EntryPointInfo.markDiagnosedMultipleMainClasses()) {
1628-
// If we already have a main class, and we haven't diagnosed it,
1633+
// If we already have a main type, and we haven't diagnosed it,
16291634
// do so now.
16301635
if (existingDiagLoc.isValid()) {
1631-
getASTContext().Diags.diagnose(existingDiagLoc, diag::attr_ApplicationMain_multiple,
1632-
mainClassDiagKind);
1636+
getASTContext().Diags.diagnose(existingDiagLoc,
1637+
diag::attr_ApplicationMain_multiple,
1638+
mainTypeDiagKind);
16331639
} else {
1634-
getASTContext().Diags.diagnose(existingClass, diag::attr_ApplicationMain_multiple,
1635-
mainClassDiagKind);
1640+
getASTContext().Diags.diagnose(existingDecl,
1641+
diag::attr_ApplicationMain_multiple,
1642+
mainTypeDiagKind);
16361643
}
16371644
}
16381645

16391646
// Always diagnose the new class.
16401647
getASTContext().Diags.diagnose(diagLoc, diag::attr_ApplicationMain_multiple,
1641-
mainClassDiagKind);
1648+
mainTypeDiagKind);
16421649

16431650
} else {
16441651
// We don't have an existing class, but we /do/ have a file in script mode.
16451652
// Diagnose that.
16461653
if (EntryPointInfo.markDiagnosedMainClassWithScript()) {
1647-
getASTContext().Diags.diagnose(diagLoc, diag::attr_ApplicationMain_with_script,
1648-
mainClassDiagKind);
1654+
getASTContext().Diags.diagnose(
1655+
diagLoc, diag::attr_ApplicationMain_with_script, mainTypeDiagKind);
16491656

16501657
if (existingDiagLoc.isValid()) {
16511658
getASTContext().Diags.diagnose(existingDiagLoc,

lib/SILGen/SILGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,7 +1781,7 @@ class SourceFileScope {
17811781

17821782
// If the source file contains an artificial main, emit the implicit
17831783
// toplevel code.
1784-
if (auto mainClass = sf->getMainClass()) {
1784+
if (auto mainDecl = sf->getMainDecl()) {
17851785
assert(!sgm.M.lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION)
17861786
&& "already emitted toplevel before main class?!");
17871787

@@ -1798,7 +1798,7 @@ class SourceFileScope {
17981798
SGF.F.getConventions().getParameterSILTypes().begin();
17991799
entry->createFunctionArgument(*paramTypeIter);
18001800
entry->createFunctionArgument(*std::next(paramTypeIter));
1801-
SGF.emitArtificialTopLevel(mainClass);
1801+
SGF.emitArtificialTopLevel(mainDecl);
18021802
}
18031803
}
18041804
};

0 commit comments

Comments
 (0)