Merge pull request #30693 from nate-chandler/main-attribute

@main: Attribute to add an entry point to a type.
This commit is contained in:
nate-chandler
2020-04-22 15:42:49 -07:00
committed by GitHub
68 changed files with 925 additions and 67 deletions

View File

@@ -1562,16 +1562,17 @@ bool ModuleDecl::isBuiltinModule() const {
return this == getASTContext().TheBuiltinModule;
}
bool SourceFile::registerMainClass(ClassDecl *mainClass, SourceLoc diagLoc) {
if (mainClass == MainClass)
bool SourceFile::registerMainDecl(Decl *mainDecl, SourceLoc diagLoc) {
if (mainDecl == MainDecl)
return false;
ArtificialMainKind kind = mainClass->getArtificialMainKind();
ArtificialMainKind kind = mainDecl->getArtificialMainKind();
if (getParentModule()->registerEntryPointFile(this, diagLoc, kind))
return true;
MainClass = mainClass;
MainClassDiagLoc = diagLoc;
MainDecl = mainDecl;
MainDeclDiagLoc = diagLoc;
return false;
}
@@ -1591,53 +1592,59 @@ bool ModuleDecl::registerEntryPointFile(FileUnit *file, SourceLoc diagLoc,
enum : unsigned {
UIApplicationMainClass = 0,
NSApplicationMainClass = 1,
} mainClassDiagKind;
MainType = 2,
} mainTypeDiagKind;
switch (kind.getValue()) {
case ArtificialMainKind::UIApplicationMain:
mainClassDiagKind = UIApplicationMainClass;
mainTypeDiagKind = UIApplicationMainClass;
break;
case ArtificialMainKind::NSApplicationMain:
mainClassDiagKind = NSApplicationMainClass;
mainTypeDiagKind = NSApplicationMainClass;
break;
case ArtificialMainKind::TypeMain:
mainTypeDiagKind = MainType;
break;
}
FileUnit *existingFile = EntryPointInfo.getEntryPointFile();
const ClassDecl *existingClass = existingFile->getMainClass();
const Decl *existingDecl = existingFile->getMainDecl();
SourceLoc existingDiagLoc;
if (auto *sourceFile = dyn_cast<SourceFile>(existingFile)) {
if (existingClass) {
existingDiagLoc = sourceFile->getMainClassDiagLoc();
if (existingDecl) {
existingDiagLoc = sourceFile->getMainDeclDiagLoc();
} else {
if (auto bufID = sourceFile->getBufferID())
existingDiagLoc = getASTContext().SourceMgr.getLocForBufferStart(*bufID);
}
}
if (existingClass) {
if (existingDecl) {
if (EntryPointInfo.markDiagnosedMultipleMainClasses()) {
// If we already have a main class, and we haven't diagnosed it,
// If we already have a main type, and we haven't diagnosed it,
// do so now.
if (existingDiagLoc.isValid()) {
getASTContext().Diags.diagnose(existingDiagLoc, diag::attr_ApplicationMain_multiple,
mainClassDiagKind);
getASTContext().Diags.diagnose(existingDiagLoc,
diag::attr_ApplicationMain_multiple,
mainTypeDiagKind);
} else {
getASTContext().Diags.diagnose(existingClass, diag::attr_ApplicationMain_multiple,
mainClassDiagKind);
getASTContext().Diags.diagnose(existingDecl,
diag::attr_ApplicationMain_multiple,
mainTypeDiagKind);
}
}
// Always diagnose the new class.
getASTContext().Diags.diagnose(diagLoc, diag::attr_ApplicationMain_multiple,
mainClassDiagKind);
mainTypeDiagKind);
} else {
// We don't have an existing class, but we /do/ have a file in script mode.
// Diagnose that.
if (EntryPointInfo.markDiagnosedMainClassWithScript()) {
getASTContext().Diags.diagnose(diagLoc, diag::attr_ApplicationMain_with_script,
mainClassDiagKind);
getASTContext().Diags.diagnose(
diagLoc, diag::attr_ApplicationMain_with_script, mainTypeDiagKind);
if (existingDiagLoc.isValid()) {
getASTContext().Diags.diagnose(existingDiagLoc,