diff --git a/include/swift/AST/DefaultArgumentKind.h b/include/swift/AST/DefaultArgumentKind.h index f687bb4426eac..11aa4f79b0897 100644 --- a/include/swift/AST/DefaultArgumentKind.h +++ b/include/swift/AST/DefaultArgumentKind.h @@ -36,18 +36,6 @@ enum class DefaultArgumentKind : uint8_t { /// The default argument is inherited from the corresponding argument of the /// overridden declaration. Inherited, - /// The #file default argument, which is expanded at the call site. - File, - /// The #filePath default argument, which is expanded at the call site. - FilePath, - /// The #line default argument, which is expanded at the call site. - Line, - /// The #column default argument, which is expanded at the call site. - Column, - /// The #function default argument, which is expanded at the call site. - Function, - /// The #dsohandle default argument, which is expanded at the call site. - DSOHandle, /// The "nil" literal. NilLiteral, /// An empty array literal. @@ -56,8 +44,11 @@ enum class DefaultArgumentKind : uint8_t { EmptyDictionary, /// A reference to the stored property. This is a special default argument /// kind for the synthesized memberwise constructor to emit a call to the - // property's initializer. + /// property's initializer. StoredProperty, + // Magic identifier literals expanded at the call site: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) NAME, +#include "swift/AST/MagicIdentifierKinds.def" }; enum { NumDefaultArgumentKindBits = 4 }; diff --git a/include/swift/AST/DiagnosticsCommon.def b/include/swift/AST/DiagnosticsCommon.def index a5bebe4123280..cd4801ba89761 100644 --- a/include/swift/AST/DiagnosticsCommon.def +++ b/include/swift/AST/DiagnosticsCommon.def @@ -114,14 +114,22 @@ ERROR(sdk_node_unrecognized_decl_kind,none, ERROR(sdk_node_unrecognized_accessor_kind,none, "unrecognized accessor kind '%0' in SDK node", (StringRef)) -// Emitted from ModuleDecl::computeMagicFileStringMap() -WARNING(pound_source_location_creates_pound_file_conflicts,none, - "'#sourceLocation' directive produces '#file' string of '%0', which " - "conflicts with '#file' strings produced by other paths in the module", - (StringRef)) +// Emitted from ModuleDecl::computeFileIDMap() +WARNING(source_location_creates_file_id_conflicts,none, + "'#sourceLocation' directive produces '#fileID' string of '%0', which " + "conflicts with '#fileID' strings produced by other paths in the " + "module", (StringRef)) NOTE(fixit_correct_source_location_file,none, "change file in '#sourceLocation' to '%0'", (StringRef)) +// Usually, but not always, emitted from the driver +ERROR(error_two_files_same_name,none, + "filename \"%0\" used twice: '%1' and '%2'", + (StringRef, StringRef, StringRef)) +NOTE(note_explain_two_files_same_name,none, + "filenames are used to distinguish private declarations with the same " + "name", ()) + //------------------------------------------------------------------------------ // MARK: Circular reference diagnostics //------------------------------------------------------------------------------ diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def index 52d864ca5fe52..7cc306fbeb727 100644 --- a/include/swift/AST/DiagnosticsDriver.def +++ b/include/swift/AST/DiagnosticsDriver.def @@ -104,13 +104,6 @@ WARNING(warn_arclite_not_found_when_link_objc_runtime,none, "unable to find Objective-C runtime support library 'arclite'; " "pass '-no-link-objc-runtime' to silence this warning", ()) -ERROR(error_two_files_same_name,none, - "filename \"%0\" used twice: '%1' and '%2'", - (StringRef, StringRef, StringRef)) -NOTE(note_explain_two_files_same_name,none, - "filenames are used to distinguish private declarations with the same " - "name", ()) - WARNING(warn_cannot_stat_input,none, "unable to determine when '%0' was last modified: %1", (StringRef, StringRef)) diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 923a68fa743cb..af21aeef49b9e 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1074,17 +1074,14 @@ class InterpolatedStringLiteralExpr : public LiteralExpr { class MagicIdentifierLiteralExpr : public LiteralExpr { public: enum Kind : unsigned { - File, FilePath, Line, Column, Function, DSOHandle +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) NAME, +#include "swift/AST/MagicIdentifierKinds.def" }; static StringRef getKindString(MagicIdentifierLiteralExpr::Kind value) { switch (value) { - case File: return "#file"; - case FilePath: return "#filePath"; - case Function: return "#function"; - case Line: return "#line"; - case Column: return "#column"; - case DSOHandle: return "#dsohandle"; +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) case NAME: return STRING; +#include "swift/AST/MagicIdentifierKinds.def" } llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in getKindString."); @@ -1107,21 +1104,15 @@ class MagicIdentifierLiteralExpr : public LiteralExpr { return static_cast(Bits.MagicIdentifierLiteralExpr.Kind); } - bool isFile() const { return getKind() == File; } - bool isFunction() const { return getKind() == Function; } - bool isLine() const { return getKind() == Line; } - bool isColumn() const { return getKind() == Column; } - bool isString() const { switch (getKind()) { - case File: - case FilePath: - case Function: +#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case NAME: \ return true; - case Line: - case Column: - case DSOHandle: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case NAME: \ return false; +#include "swift/AST/MagicIdentifierKinds.def" } llvm_unreachable("bad Kind"); } diff --git a/include/swift/AST/MagicIdentifierKinds.def b/include/swift/AST/MagicIdentifierKinds.def new file mode 100644 index 0000000000000..e1ef52edfcaf9 --- /dev/null +++ b/include/swift/AST/MagicIdentifierKinds.def @@ -0,0 +1,116 @@ +//===--- MagicIdentifierKinds.def - Swift #ident metaprogramming -*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines macros used for macro-metaprogramming with magic +// identifier literals. +// +//===----------------------------------------------------------------------===// + +// Used for any magic identifier. +#ifndef MAGIC_IDENTIFIER +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) +#endif + +// Used for magic identifiers which produce string literals. +#ifndef MAGIC_STRING_IDENTIFIER +#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) +#endif + +// Used for magic identifiers which produce integer literals. +#ifndef MAGIC_INT_IDENTIFIER +#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) +#endif + +// Used for magic identifiers which produce raw pointers. +#ifndef MAGIC_POINTER_IDENTIFIER +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) +#endif + +// Used when a given token always maps to a particular magic identifier kind. +#ifndef MAGIC_IDENTIFIER_TOKEN +#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) +#endif + +// Used when a given token always maps to a particular magic identifier kind, +// but that token is deprecated. +#ifndef MAGIC_IDENTIFIER_DEPRECATED_TOKEN +#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) +#endif + + + +// +// Magic string literals +// + +/// The \c #fileID magic identifier literal. +MAGIC_STRING_IDENTIFIER(FileID, "#fileID", PoundFileIDExpr) + MAGIC_IDENTIFIER_TOKEN(FileID, pound_fileID) + +/// The \c #file magic identifier literal, written in code where it is +/// a synonym for \c #fileID (i.e. "Swift 6 mode" code). +MAGIC_STRING_IDENTIFIER(FileIDSpelledAsFile, "#file", PoundFileExpr) + // tok::pound_file is shared with FilePathSpelledAsFile; please write custom + // code paths for it. + +/// The \c #filePath magic identifier literal. +MAGIC_STRING_IDENTIFIER(FilePath, "#filePath", PoundFilePathExpr) + MAGIC_IDENTIFIER_TOKEN(FilePath, pound_filePath) + +/// The \c #file magic identifier literal, written in code where it is +/// a synonym for \c #filePath (i.e. Swift 5 mode code). +MAGIC_STRING_IDENTIFIER(FilePathSpelledAsFile, "#file", PoundFileExpr) + // tok::pound_file is shared with FileIDSpelledAsFile; please write custom + // code paths for it. + MAGIC_IDENTIFIER_DEPRECATED_TOKEN(FilePathSpelledAsFile, kw___FILE__) + +/// The \c #function magic identifier literal. +MAGIC_STRING_IDENTIFIER(Function, "#function", PoundFunctionExpr) + MAGIC_IDENTIFIER_TOKEN(Function, pound_function) + MAGIC_IDENTIFIER_DEPRECATED_TOKEN(Function, kw___FUNCTION__) + + + +// +// Magic integer literals +// + +/// The \c #line magic identifier literal. +MAGIC_INT_IDENTIFIER(Line, "#line", PoundLineExpr) + MAGIC_IDENTIFIER_TOKEN(Line, pound_line) + MAGIC_IDENTIFIER_DEPRECATED_TOKEN(Line, kw___LINE__) + +/// The \c #column magic identifier literal. +MAGIC_INT_IDENTIFIER(Column, "#column", PoundColumnExpr) + MAGIC_IDENTIFIER_TOKEN(Column, pound_column) + MAGIC_IDENTIFIER_DEPRECATED_TOKEN(Column, kw___COLUMN__) + + + +// +// Magic raw pointer literals +// + +/// The \c #dsohandle magic identifier literal. +MAGIC_POINTER_IDENTIFIER(DSOHandle, "#dsohandle", PoundDsohandleExpr) + MAGIC_IDENTIFIER_TOKEN(DSOHandle, pound_dsohandle) + MAGIC_IDENTIFIER_DEPRECATED_TOKEN(DSOHandle, kw___DSO_HANDLE__) + + + + +#undef MAGIC_IDENTIFIER +#undef MAGIC_STRING_IDENTIFIER +#undef MAGIC_INT_IDENTIFIER +#undef MAGIC_POINTER_IDENTIFIER +#undef MAGIC_IDENTIFIER_TOKEN +#undef MAGIC_IDENTIFIER_DEPRECATED_TOKEN diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index bc1aa99ed4ed2..ce1693fe003c2 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -294,23 +294,20 @@ class ModuleDecl : public DeclContext, public TypeDecl { void addFile(FileUnit &newFile); void removeFile(FileUnit &existingFile); - /// Creates a map from \c #filePath strings to corresponding \c #file + /// Creates a map from \c #filePath strings to corresponding \c #fileID /// strings, diagnosing any conflicts. /// - /// A given \c #filePath string always maps to exactly one \c #file string, + /// A given \c #filePath string always maps to exactly one \c #fileID string, /// but it is possible for \c #sourceLocation directives to introduce /// duplicates in the opposite direction. If there are such conflicts, this /// method will diagnose the conflict and choose a "winner" among the paths - /// in a reproducible way. The \c bool paired with the \c #file string is + /// in a reproducible way. The \c bool paired with the \c #fileID string is /// \c true for paths which did not have a conflict or won a conflict, and /// \c false for paths which lost a conflict. Thus, if you want to generate a - /// reverse mapping, you should drop or special-case the \c #file strings that - /// are paired with \c false. - /// - /// Note that this returns an empty StringMap if concise \c #file strings are - /// disabled. Users should fall back to using the file path in this case. + /// reverse mapping, you should drop or special-case the \c #fileID strings + /// that are paired with \c false. llvm::StringMap> - computeMagicFileStringMap(bool shouldDiagnose) const; + computeFileIDMap(bool shouldDiagnose) const; /// Add a file declaring a cross-import overlay. void addCrossImportOverlayFile(StringRef file); diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 1514a7cc23578..0c82c3d50f107 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -516,7 +516,7 @@ def enable_experimental_additive_arithmetic_derivation : def enable_experimental_concise_pound_file : Flag<["-"], "enable-experimental-concise-pound-file">, - Flags<[FrontendOption]>, + Flags<[FrontendOption, ModuleInterfaceOption]>, HelpText<"Enable experimental concise '#file' identifier">; // Diagnostic control options diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index dc413c7d0c321..799a5f38bc58c 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -321,13 +321,10 @@ getForeignErrorConventionKindString(ForeignErrorConvention::Kind value) { static StringRef getDefaultArgumentKindString(DefaultArgumentKind value) { switch (value) { case DefaultArgumentKind::None: return "none"; - case DefaultArgumentKind::Column: return "#column"; - case DefaultArgumentKind::DSOHandle: return "#dsohandle"; - case DefaultArgumentKind::File: return "#file"; - case DefaultArgumentKind::FilePath: return "#filePath"; - case DefaultArgumentKind::Function: return "#function"; +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: return STRING; +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::Inherited: return "inherited"; - case DefaultArgumentKind::Line: return "#line"; case DefaultArgumentKind::NilLiteral: return "nil"; case DefaultArgumentKind::EmptyArray: return "[]"; case DefaultArgumentKind::EmptyDictionary: return "[:]"; diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 9c1590e950266..8d508506e63ae 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -2739,12 +2739,9 @@ void PrintAST::printOneParameter(const ParamDecl *param, Printer << " = "; switch (param->getDefaultArgumentKind()) { - case DefaultArgumentKind::File: - case DefaultArgumentKind::Line: - case DefaultArgumentKind::Column: - case DefaultArgumentKind::Function: - case DefaultArgumentKind::DSOHandle: - case DefaultArgumentKind::NilLiteral: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: +#include "swift/AST/MagicIdentifierKinds.def" Printer.printKeyword(defaultArgStr, Options); break; default: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d81c8f4fdc582..414757aeb8454 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -6321,12 +6321,9 @@ bool ParamDecl::hasDefaultExpr() const { case DefaultArgumentKind::StoredProperty: return false; case DefaultArgumentKind::Normal: - case DefaultArgumentKind::File: - case DefaultArgumentKind::FilePath: - case DefaultArgumentKind::Line: - case DefaultArgumentKind::Column: - case DefaultArgumentKind::Function: - case DefaultArgumentKind::DSOHandle: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::NilLiteral: case DefaultArgumentKind::EmptyArray: case DefaultArgumentKind::EmptyDictionary: @@ -6344,12 +6341,9 @@ bool ParamDecl::hasCallerSideDefaultExpr() const { case DefaultArgumentKind::StoredProperty: case DefaultArgumentKind::Normal: return false; - case DefaultArgumentKind::File: - case DefaultArgumentKind::FilePath: - case DefaultArgumentKind::Line: - case DefaultArgumentKind::Column: - case DefaultArgumentKind::Function: - case DefaultArgumentKind::DSOHandle: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::NilLiteral: case DefaultArgumentKind::EmptyArray: case DefaultArgumentKind::EmptyDictionary: @@ -6585,12 +6579,9 @@ ParamDecl::getDefaultValueStringRepresentation( scratch); } case DefaultArgumentKind::Inherited: return "super"; - case DefaultArgumentKind::File: return "#file"; - case DefaultArgumentKind::FilePath: return "#filePath"; - case DefaultArgumentKind::Line: return "#line"; - case DefaultArgumentKind::Column: return "#column"; - case DefaultArgumentKind::Function: return "#function"; - case DefaultArgumentKind::DSOHandle: return "#dsohandle"; +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: return STRING; +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::NilLiteral: return "nil"; case DefaultArgumentKind::EmptyArray: return "[]"; case DefaultArgumentKind::EmptyDictionary: return "[:]"; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index d0f443f4f42df..bb77fdc3b1532 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -2367,20 +2367,18 @@ getInfoForUsedFileNames(const ModuleDecl *module) { return result; } -static void -computeMagicFileString(const ModuleDecl *module, StringRef name, - SmallVectorImpl &result) { +static void computeFileID(const ModuleDecl *module, StringRef name, + SmallVectorImpl &result) { result.assign(module->getNameStr().begin(), module->getNameStr().end()); result.push_back('/'); result.append(name.begin(), name.end()); } static StringRef -resolveMagicNameConflicts(const ModuleDecl *module, StringRef fileString, - const llvm::StringMap &paths, - bool shouldDiagnose) { +resolveFileIDConflicts(const ModuleDecl *module, StringRef fileString, + const llvm::StringMap &paths, + bool shouldDiagnose) { assert(paths.size() > 1); - assert(module->getASTContext().LangOpts.EnableConcisePoundFile); /// The path we consider to be "correct"; we will emit fix-its changing the /// other paths to match this one. @@ -2417,13 +2415,20 @@ resolveMagicNameConflicts(const ModuleDecl *module, StringRef fileString, // Don't diagnose #sourceLocations that match the physical file. if (pathPair.second.physicalFileLoc.isValid()) { - assert(isWinner && "physical files should always win; duplicate name?"); + if (!isWinner) { + // The driver is responsible for diagnosing this, but naughty people who + // have directly invoked the frontend could make it happen here instead. + StringRef filename = llvm::sys::path::filename(winner); + diags.diagnose(SourceLoc(), diag::error_two_files_same_name, + filename, winner, pathPair.first()); + diags.diagnose(SourceLoc(), diag::note_explain_two_files_same_name); + } continue; } for (auto loc : pathPair.second.virtualFileLocs) { diags.diagnose(loc, - diag::pound_source_location_creates_pound_file_conflicts, + diag::source_location_creates_file_id_conflicts, fileString); // Offer a fix-it unless it would be tautological. @@ -2437,26 +2442,23 @@ resolveMagicNameConflicts(const ModuleDecl *module, StringRef fileString, } llvm::StringMap> -ModuleDecl::computeMagicFileStringMap(bool shouldDiagnose) const { +ModuleDecl::computeFileIDMap(bool shouldDiagnose) const { llvm::StringMap> result; SmallString<64> scratch; - if (!getASTContext().LangOpts.EnableConcisePoundFile) - return result; - for (auto &namePair : getInfoForUsedFileNames(this)) { - computeMagicFileString(this, namePair.first(), scratch); + computeFileID(this, namePair.first(), scratch); auto &infoForPaths = namePair.second; assert(!infoForPaths.empty()); // TODO: In the future, we'd like to handle these conflicts gracefully by - // generating a unique `#file` string for each conflicting name. For now, we - // will simply warn about conflicts. + // generating a unique `#fileID` string for each conflicting name. For now, + // we will simply warn about conflicts. StringRef winner = infoForPaths.begin()->first(); if (infoForPaths.size() > 1) - winner = resolveMagicNameConflicts(this, scratch, infoForPaths, - shouldDiagnose); + winner = resolveFileIDConflicts(this, scratch, infoForPaths, + shouldDiagnose); for (auto &pathPair : infoForPaths) { result[pathPair.first()] = diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 1e99701ee94c6..a898b5ebd7a30 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -2604,12 +2604,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { case DefaultArgumentKind::EmptyDictionary: return !includeDefaultArgs; - case DefaultArgumentKind::File: - case DefaultArgumentKind::FilePath: - case DefaultArgumentKind::Line: - case DefaultArgumentKind::Column: - case DefaultArgumentKind::Function: - case DefaultArgumentKind::DSOHandle: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: +#include "swift/AST/MagicIdentifierKinds.def" // Skip parameters that are defaulted to source location or other // caller context information. Users typically don't want to specify // these parameters. @@ -4042,35 +4039,53 @@ class CompletionLookup final : public swift::VisibleDeclConsumer { /// Add '#file', '#line', et at. void addPoundLiteralCompletions(bool needPound) { - auto addFromProto = [&](StringRef name, CodeCompletionKeywordKind kwKind, - CodeCompletionLiteralKind literalKind) { + auto addFromProto = [&](MagicIdentifierLiteralExpr::Kind magicKind, + Optional literalKind) { + CodeCompletionKeywordKind kwKind; + switch (magicKind) { + case MagicIdentifierLiteralExpr::FileIDSpelledAsFile: + kwKind = CodeCompletionKeywordKind::pound_file; + break; + case MagicIdentifierLiteralExpr::FilePathSpelledAsFile: + // Already handled by above case. + return; +#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \ + case MagicIdentifierLiteralExpr::NAME: \ + kwKind = CodeCompletionKeywordKind::TOKEN; \ + break; +#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) +#include "swift/AST/MagicIdentifierKinds.def" + } + + StringRef name = MagicIdentifierLiteralExpr::getKindString(magicKind); if (!needPound) name = name.substr(1); + if (!literalKind) { + // Pointer type + addKeyword(name, "UnsafeRawPointer", kwKind); + return; + } + CodeCompletionResultBuilder builder( Sink, CodeCompletionResult::ResultKind::Keyword, SemanticContextKind::None, {}); - builder.setLiteralKind(literalKind); + builder.setLiteralKind(literalKind.getValue()); builder.setKeywordKind(kwKind); builder.addBaseName(name); - addTypeRelationFromProtocol(builder, literalKind); + addTypeRelationFromProtocol(builder, literalKind.getValue()); }; - addFromProto("#function", CodeCompletionKeywordKind::pound_function, - CodeCompletionLiteralKind::StringLiteral); - addFromProto("#file", CodeCompletionKeywordKind::pound_file, +#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + addFromProto(MagicIdentifierLiteralExpr::NAME, \ CodeCompletionLiteralKind::StringLiteral); - if (Ctx.LangOpts.EnableConcisePoundFile) { - addFromProto("#filePath", CodeCompletionKeywordKind::pound_file, - CodeCompletionLiteralKind::StringLiteral); - } - addFromProto("#line", CodeCompletionKeywordKind::pound_line, - CodeCompletionLiteralKind::IntegerLiteral); - addFromProto("#column", CodeCompletionKeywordKind::pound_column, +#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + addFromProto(MagicIdentifierLiteralExpr::NAME, \ CodeCompletionLiteralKind::IntegerLiteral); - - addKeyword(needPound ? "#dsohandle" : "dsohandle", "UnsafeRawPointer", - CodeCompletionKeywordKind::pound_dsohandle); +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + addFromProto(MagicIdentifierLiteralExpr::NAME, \ + None); +#include "swift/AST/MagicIdentifierKinds.def" } void addValueLiteralCompletions() { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d26c076f3a44b..8ef283e4bad56 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1018,31 +1018,34 @@ static bool isValidTrailingClosure(bool isExprBasic, Parser &P){ /// Map magic literal tokens such as #file to their /// MagicIdentifierLiteralExpr kind. static MagicIdentifierLiteralExpr::Kind -getMagicIdentifierLiteralKind(tok Kind) { +getMagicIdentifierLiteralKind(tok Kind, const LangOptions &Opts) { switch (Kind) { - case tok::kw___COLUMN__: - case tok::pound_column: - return MagicIdentifierLiteralExpr::Kind::Column; - case tok::kw___FILE__: case tok::pound_file: - return MagicIdentifierLiteralExpr::Kind::File; - case tok::pound_filePath: - return MagicIdentifierLiteralExpr::Kind::FilePath; - case tok::kw___FUNCTION__: - case tok::pound_function: - return MagicIdentifierLiteralExpr::Kind::Function; - case tok::kw___LINE__: - case tok::pound_line: - return MagicIdentifierLiteralExpr::Kind::Line; - case tok::kw___DSO_HANDLE__: - case tok::pound_dsohandle: - return MagicIdentifierLiteralExpr::Kind::DSOHandle; - + // TODO: Enable by default at the next source break. + return Opts.EnableConcisePoundFile + ? MagicIdentifierLiteralExpr::FileIDSpelledAsFile + : MagicIdentifierLiteralExpr::FilePathSpelledAsFile; +#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \ + case tok::TOKEN: \ + return MagicIdentifierLiteralExpr::Kind::NAME; +#include "swift/AST/MagicIdentifierKinds.def" default: llvm_unreachable("not a magic literal"); } } +/// Map magic literal kinds such as #file to their SyntaxKind. +static SyntaxKind +getMagicIdentifierSyntaxKind(MagicIdentifierLiteralExpr::Kind LiteralKind) { + switch (LiteralKind) { +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ + return SyntaxKind::SYNTAX_KIND; +#include "swift/AST/MagicIdentifierKinds.def" + } + llvm_unreachable("not a magic literal kind"); +} + ParserResult Parser::parseExprPostfixSuffix(ParserResult Result, bool isExprBasic, bool periodHasKeyPathBehavior, @@ -1450,20 +1453,12 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { BooleanLiteralExpr(isTrue, consumeToken())); } - case tok::kw___FILE__: - case tok::kw___LINE__: - case tok::kw___COLUMN__: - case tok::kw___FUNCTION__: - case tok::kw___DSO_HANDLE__: { - StringRef replacement = ""; - switch (Tok.getKind()) { - default: llvm_unreachable("can't get here"); - case tok::kw___FILE__: replacement = "#file"; break; - case tok::kw___LINE__: replacement = "#line"; break; - case tok::kw___COLUMN__: replacement = "#column"; break; - case tok::kw___FUNCTION__: replacement = "#function"; break; - case tok::kw___DSO_HANDLE__: replacement = "#dsohandle"; break; - } + // Cases for deprecated magic identifier tokens +#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) case tok::TOKEN: +#include "swift/AST/MagicIdentifierKinds.def" + { + auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts); + auto replacement = MagicIdentifierLiteralExpr::getKindString(Kind); diagnose(Tok.getLoc(), diag::snake_case_deprecated, Tok.getText(), replacement) @@ -1471,26 +1466,18 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { LLVM_FALLTHROUGH; } - case tok::pound_column: + // Cases for non-deprecated magic identifier tokens case tok::pound_file: - case tok::pound_filePath: - case tok::pound_function: - case tok::pound_line: - case tok::pound_dsohandle: { - SyntaxKind SKind = SyntaxKind::UnknownExpr; - switch (Tok.getKind()) { - case tok::pound_column: SKind = SyntaxKind::PoundColumnExpr; break; - case tok::pound_file: SKind = SyntaxKind::PoundFileExpr; break; - case tok::pound_filePath: SKind = SyntaxKind::PoundFilePathExpr; break; - case tok::pound_function: SKind = SyntaxKind::PoundFunctionExpr; break; - // FIXME: #line was renamed to #sourceLocation - case tok::pound_line: SKind = SyntaxKind::PoundLineExpr; break; - case tok::pound_dsohandle: SKind = SyntaxKind::PoundDsohandleExpr; break; - default: break; - } +#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN) +#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) case tok::TOKEN: +#include "swift/AST/MagicIdentifierKinds.def" + { + auto Kind = getMagicIdentifierLiteralKind(Tok.getKind(), Context.LangOpts); + SyntaxKind SKind = getMagicIdentifierSyntaxKind(Kind); + ExprContext.setCreateSyntax(SKind); - auto Kind = getMagicIdentifierLiteralKind(Tok.getKind()); SourceLoc Loc = consumeToken(); + return makeParserResult(new (Context) MagicIdentifierLiteralExpr( Kind, Loc, /*implicit=*/false)); } diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index f056eddb81e1f..ad8a9d8330aac 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -44,18 +44,9 @@ static DefaultArgumentKind getDefaultArgKind(Expr *init) { return DefaultArgumentKind::Normal; switch (magic->getKind()) { - case MagicIdentifierLiteralExpr::Column: - return DefaultArgumentKind::Column; - case MagicIdentifierLiteralExpr::File: - return DefaultArgumentKind::File; - case MagicIdentifierLiteralExpr::FilePath: - return DefaultArgumentKind::FilePath; - case MagicIdentifierLiteralExpr::Line: - return DefaultArgumentKind::Line; - case MagicIdentifierLiteralExpr::Function: - return DefaultArgumentKind::Function; - case MagicIdentifierLiteralExpr::DSOHandle: - return DefaultArgumentKind::DSOHandle; +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: return DefaultArgumentKind::NAME; +#include "swift/AST/MagicIdentifierKinds.def" } llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch."); diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index 8bb72433624b5..00b8131d64c73 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -2870,12 +2870,10 @@ printSILCoverageMaps(SILPrintContext &Ctx, M->print(Ctx); } -using MagicFileStringMap = - llvm::StringMap>; +using FileIDMap = llvm::StringMap>; -static void -printMagicFileStringMapEntry(SILPrintContext &Ctx, - const MagicFileStringMap::MapEntryTy &entry) { +static void printFileIDMapEntry(SILPrintContext &Ctx, + const FileIDMap::MapEntryTy &entry) { auto &OS = Ctx.OS(); OS << "// '" << std::get<0>(entry.second) << "' => '" << entry.first() << "'"; @@ -2886,12 +2884,11 @@ printMagicFileStringMapEntry(SILPrintContext &Ctx, OS << "\n"; } -static void printMagicFileStringMap(SILPrintContext &Ctx, - const MagicFileStringMap map) { +static void printFileIDMap(SILPrintContext &Ctx, const FileIDMap map) { if (map.empty()) return; - Ctx.OS() << "\n\n// Mappings from '#file' to '#filePath':\n"; + Ctx.OS() << "\n\n// Mappings from '#fileID' to '#filePath':\n"; if (Ctx.sortSIL()) { llvm::SmallVector keys; @@ -2914,10 +2911,10 @@ static void printMagicFileStringMap(SILPrintContext &Ctx, }); for (auto key : keys) - printMagicFileStringMapEntry(Ctx, *map.find(key)); + printFileIDMapEntry(Ctx, *map.find(key)); } else { for (const auto &entry : map) - printMagicFileStringMapEntry(Ctx, entry); + printFileIDMapEntry(Ctx, entry); } } @@ -3036,8 +3033,8 @@ void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M, printExternallyVisibleDecls(PrintCtx, externallyVisible.getArrayRef()); if (M) - printMagicFileStringMap( - PrintCtx, M->computeMagicFileStringMap(/*shouldDiagnose=*/false)); + printFileIDMap( + PrintCtx, M->computeFileIDMap(/*shouldDiagnose=*/false)); OS << "\n\n"; } diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index cc75929674201..87ff960ed5d99 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -51,8 +51,7 @@ using namespace Lowering; SILGenModule::SILGenModule(SILModule &M, ModuleDecl *SM) : M(M), Types(M.Types), SwiftModule(SM), TopLevelSGF(nullptr), - MagicFileStringsByFilePath( - SM->computeMagicFileStringMap(/*shouldDiagnose=*/true)) { + FileIDsByFilePath(SM->computeFileIDMap(/*shouldDiagnose=*/true)) { const SILOptions &Opts = M.getOptions(); if (!Opts.UseProfile.empty()) { auto ReaderOrErr = llvm::IndexedInstrProfReader::create(Opts.UseProfile); @@ -1200,12 +1199,9 @@ void SILGenModule::emitDefaultArgGenerator(SILDeclRef constant, } case DefaultArgumentKind::Inherited: - case DefaultArgumentKind::Column: - case DefaultArgumentKind::File: - case DefaultArgumentKind::FilePath: - case DefaultArgumentKind::Line: - case DefaultArgumentKind::Function: - case DefaultArgumentKind::DSOHandle: +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::NilLiteral: case DefaultArgumentKind::EmptyArray: case DefaultArgumentKind::EmptyDictionary: diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h index 287d656fe1261..44a7cd0fa5c27 100644 --- a/lib/SILGen/SILGen.h +++ b/lib/SILGen/SILGen.h @@ -131,8 +131,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor { ASTContext &getASTContext() { return M.getASTContext(); } - llvm::StringMap> - MagicFileStringsByFilePath; + llvm::StringMap> FileIDsByFilePath; static DeclName getMagicFunctionName(SILDeclRef ref); static DeclName getMagicFunctionName(DeclContext *dc); diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index b774c781119d8..b5f3d2339c82c 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -4611,11 +4611,11 @@ StringRef SILGenFunction::getMagicFilePathString(SourceLoc loc) { return getSourceManager().getDisplayNameForLoc(loc); } -std::string SILGenFunction::getMagicFileString(SourceLoc loc) { +std::string SILGenFunction::getMagicFileIDString(SourceLoc loc) { auto path = getMagicFilePathString(loc); - auto result = SGM.MagicFileStringsByFilePath.find(path); - if (result != SGM.MagicFileStringsByFilePath.end()) + auto result = SGM.FileIDsByFilePath.find(path); + if (result != SGM.FileIDsByFilePath.end()) return std::get<0>(result->second); return path.str(); @@ -4849,8 +4849,9 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { auto magicLiteral = cast(literal); switch (magicLiteral->getKind()) { - case MagicIdentifierLiteralExpr::File: { - std::string value = loc.isValid() ? getMagicFileString(loc) : ""; + case MagicIdentifierLiteralExpr::FileIDSpelledAsFile: + case MagicIdentifierLiteralExpr::FileID: { + std::string value = loc.isValid() ? getMagicFileIDString(loc) : ""; builtinLiteralArgs = emitStringLiteral(*this, literal, value, C, magicLiteral->getStringEncoding()); builtinInit = magicLiteral->getBuiltinInitializer(); @@ -4858,6 +4859,7 @@ RValue SILGenFunction::emitLiteral(LiteralExpr *literal, SGFContext C) { break; } + case MagicIdentifierLiteralExpr::FilePathSpelledAsFile: case MagicIdentifierLiteralExpr::FilePath: { StringRef value = loc.isValid() ? getMagicFilePathString(loc) : ""; builtinLiteralArgs = emitStringLiteral(*this, literal, value, C, diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp index dbedd6fa13eb0..032864527492f 100644 --- a/lib/SILGen/SILGenConvert.cpp +++ b/lib/SILGen/SILGenConvert.cpp @@ -144,7 +144,7 @@ auto SILGenFunction::emitSourceLocationArgs(SourceLoc sourceLoc, unsigned line = 0; unsigned column = 0; if (sourceLoc.isValid()) { - filename = getMagicFileString(sourceLoc); + filename = getMagicFileIDString(sourceLoc); std::tie(line, column) = ctx.SourceMgr.getLineAndColumn(sourceLoc); } diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index dbfb32a679b32..ae6e71b35aca9 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -3756,12 +3756,12 @@ visitKeyPathApplicationExpr(KeyPathApplicationExpr *E, SGFContext C) { RValue RValueEmitter:: visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) { switch (E->getKind()) { - case MagicIdentifierLiteralExpr::File: - case MagicIdentifierLiteralExpr::FilePath: - case MagicIdentifierLiteralExpr::Function: - case MagicIdentifierLiteralExpr::Line: - case MagicIdentifierLiteralExpr::Column: +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: +#include "swift/AST/MagicIdentifierKinds.def" return SGF.emitLiteral(E, C); + case MagicIdentifierLiteralExpr::DSOHandle: { auto SILLoc = SILLocation(E); auto UnsafeRawPointer = SGF.getASTContext().getUnsafeRawPointerDecl(); diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h index 5474bc87dd62b..6e6038cfd55f5 100644 --- a/lib/SILGen/SILGenFunction.h +++ b/lib/SILGen/SILGenFunction.h @@ -564,7 +564,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction Optional getUnknownEnforcement(VarDecl *var = nullptr); SourceManager &getSourceManager() { return SGM.M.getASTContext().SourceMgr; } - std::string getMagicFileString(SourceLoc loc); + std::string getMagicFileIDString(SourceLoc loc); StringRef getMagicFilePathString(SourceLoc loc); StringRef getMagicFunctionString(); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 19b2d22f0ff5a..df7cb3f6b7baf 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2591,17 +2591,16 @@ namespace { Expr *visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) { switch (expr->getKind()) { - case MagicIdentifierLiteralExpr::File: - case MagicIdentifierLiteralExpr::FilePath: - case MagicIdentifierLiteralExpr::Function: +#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ return handleStringLiteralExpr(expr); - - case MagicIdentifierLiteralExpr::Line: - case MagicIdentifierLiteralExpr::Column: +#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ return handleIntegerLiteralExpr(expr); - - case MagicIdentifierLiteralExpr::DSOHandle: +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ return expr; +#include "swift/AST/MagicIdentifierKinds.def" } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index a913ddafec0dc..43bc0307fc26d 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1331,15 +1331,11 @@ namespace { Type visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) { switch (expr->getKind()) { - case MagicIdentifierLiteralExpr::Column: - case MagicIdentifierLiteralExpr::File: - case MagicIdentifierLiteralExpr::FilePath: - case MagicIdentifierLiteralExpr::Function: - case MagicIdentifierLiteralExpr::Line: - return visitLiteralExpr(expr); - - case MagicIdentifierLiteralExpr::DSOHandle: { - // #dsohandle has type UnsafeMutableRawPointer. + // Magic pointer identifiers are of type UnsafeMutableRawPointer. +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: +#include "swift/AST/MagicIdentifierKinds.def" + { auto &ctx = CS.getASTContext(); if (TypeChecker::requirePointerArgumentIntrinsics(ctx, expr->getLoc())) return nullptr; @@ -1347,6 +1343,10 @@ namespace { auto unsafeRawPointer = ctx.getUnsafeRawPointerDecl(); return unsafeRawPointer->getDeclaredType(); } + + default: + // Others are actual literals and should be handled like any literal. + return visitLiteralExpr(expr); } llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch."); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 99cc06c7f3b8d..a995a7a0243ff 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -355,7 +355,7 @@ synthesizeStubBody(AbstractFunctionDecl *fn, void *) { initName->setBuiltinInitializer(staticStringInit); auto *file = new (ctx) MagicIdentifierLiteralExpr( - MagicIdentifierLiteralExpr::File, loc, /*Implicit=*/true); + MagicIdentifierLiteralExpr::FileID, loc, /*Implicit=*/true); file->setType(staticStringType); file->setBuiltinInitializer(staticStringInit); diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index cfbfe1f230140..5e7645e4a9984 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -436,10 +436,10 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, auto calleeDefaultArg = getMagicIdentifierDefaultArgKind(calleeParam); auto callerDefaultArg = getMagicIdentifierDefaultArgKind(callerParam); - // If one of the parameters doesn't have a default arg, or they both have - // the same one, everything's fine. + // If one of the parameters doesn't have a default arg, or they're both + // compatible, everything's fine. if (!calleeDefaultArg || !callerDefaultArg || - *calleeDefaultArg == *callerDefaultArg) + areMagicIdentifiersCompatible(*calleeDefaultArg, *callerDefaultArg)) return; StringRef calleeDefaultArgString = @@ -474,18 +474,10 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, Optional getMagicIdentifierDefaultArgKind(const ParamDecl *param) { switch (param->getDefaultArgumentKind()) { - case DefaultArgumentKind::Column: - return MagicIdentifierLiteralExpr::Kind::Column; - case DefaultArgumentKind::DSOHandle: - return MagicIdentifierLiteralExpr::Kind::DSOHandle; - case DefaultArgumentKind::File: - return MagicIdentifierLiteralExpr::Kind::File; - case DefaultArgumentKind::FilePath: - return MagicIdentifierLiteralExpr::Kind::FilePath; - case DefaultArgumentKind::Function: - return MagicIdentifierLiteralExpr::Kind::Function; - case DefaultArgumentKind::Line: - return MagicIdentifierLiteralExpr::Kind::Line; +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: \ + return MagicIdentifierLiteralExpr::Kind::NAME; +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::None: case DefaultArgumentKind::Normal: @@ -501,6 +493,52 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC, "getMagicIdentifierDefaultArgKind"); } + static bool + areMagicIdentifiersCompatible(MagicIdentifierLiteralExpr::Kind a, + MagicIdentifierLiteralExpr::Kind b) { + if (a == b) + return true; + + // The rest of this handles special compatibility rules between the + // `*SpelledAsFile` cases and various other File-related cases. + // + // The way we're going to do this is a bit magical. We will arrange the + // cases in MagicIdentifierLiteralExpr::Kind so that that they sort in + // this order: + // + // #fileID < Swift 6 #file < #filePath < Swift 5 #file < others + // + // Before we continue, let's verify that this holds. + + using Kind = MagicIdentifierLiteralExpr::Kind; + + static_assert(Kind::FileID < Kind::FileIDSpelledAsFile, + "#fileID < Swift 6 #file"); + static_assert(Kind::FileIDSpelledAsFile < Kind::FilePath, + "Swift 6 #file < #filePath"); + static_assert(Kind::FilePath < Kind::FilePathSpelledAsFile, + "#filePath < Swift 5 #file"); + + static_assert(Kind::FilePathSpelledAsFile < Kind::Line, + "Swift 5 #file < #line"); + static_assert(Kind::FilePathSpelledAsFile < Kind::Column, + "Swift 5 #file < #column"); + static_assert(Kind::FilePathSpelledAsFile < Kind::Function, + "Swift 5 #file < #function"); + static_assert(Kind::FilePathSpelledAsFile < Kind::DSOHandle, + "Swift 5 #file < #dsohandle"); + + // The rules are all commutative, so we will take the greater of the two + // kinds. + auto maxKind = std::max(a, b); + + // Both Swift 6 #file and Swift 5 #file are greater than all of the cases + // they're compatible with. So if `maxCase` is one of those two, the other + // case must have been compatible with it! + return maxKind == Kind::FileIDSpelledAsFile || + maxKind == Kind::FilePathSpelledAsFile; + } + void checkUseOfModule(DeclRefExpr *E) { // Allow module values as a part of: // - ignored base expressions; diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index ae84ed824b78a..ecf11117cb73a 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -729,35 +729,12 @@ static Expr *synthesizeCallerSideDefault(const ParamDecl *param, SourceLoc loc) { auto &ctx = param->getASTContext(); switch (param->getDefaultArgumentKind()) { - case DefaultArgumentKind::Column: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::Column, loc, - /*implicit=*/true); - - case DefaultArgumentKind::File: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::File, loc, - /*implicit=*/true); - - case DefaultArgumentKind::FilePath: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::FilePath, loc, - /*implicit=*/true); - - case DefaultArgumentKind::Line: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::Line, loc, - /*implicit=*/true); - - case DefaultArgumentKind::Function: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::Function, loc, - /*implicit=*/true); - - case DefaultArgumentKind::DSOHandle: - return new (ctx) - MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::DSOHandle, loc, +#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case DefaultArgumentKind::NAME: \ + return new (ctx) \ + MagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr::NAME, loc, \ /*implicit=*/true); +#include "swift/AST/MagicIdentifierKinds.def" case DefaultArgumentKind::NilLiteral: return new (ctx) NilLiteralExpr(loc, /*Implicit=*/true); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 8286e4fda3d6d..a307086c77ad8 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -121,21 +121,23 @@ ProtocolDecl *TypeChecker::getLiteralProtocol(ASTContext &Context, Expr *expr) { if (auto E = dyn_cast(expr)) { switch (E->getKind()) { - case MagicIdentifierLiteralExpr::File: - case MagicIdentifierLiteralExpr::FilePath: - case MagicIdentifierLiteralExpr::Function: - return TypeChecker::getProtocol( - Context, expr->getLoc(), +#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ + return TypeChecker::getProtocol( \ + Context, expr->getLoc(), \ KnownProtocolKind::ExpressibleByStringLiteral); - case MagicIdentifierLiteralExpr::Line: - case MagicIdentifierLiteralExpr::Column: - return TypeChecker::getProtocol( - Context, expr->getLoc(), +#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ + return TypeChecker::getProtocol( \ + Context, expr->getLoc(), \ KnownProtocolKind::ExpressibleByIntegerLiteral); - case MagicIdentifierLiteralExpr::DSOHandle: +#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \ + case MagicIdentifierLiteralExpr::NAME: \ return nullptr; + +#include "swift/AST/MagicIdentifierKinds.def" } } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index a2a5276b132b0..db132f44c81b8 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -211,32 +211,25 @@ getActualAccessorKind(uint8_t raw) { static Optional getActualDefaultArgKind(uint8_t raw) { switch (static_cast(raw)) { - case serialization::DefaultArgumentKind::None: - return swift::DefaultArgumentKind::None; - case serialization::DefaultArgumentKind::Normal: - return swift::DefaultArgumentKind::Normal; - case serialization::DefaultArgumentKind::Inherited: - return swift::DefaultArgumentKind::Inherited; - case serialization::DefaultArgumentKind::Column: - return swift::DefaultArgumentKind::Column; - case serialization::DefaultArgumentKind::File: - return swift::DefaultArgumentKind::File; - case serialization::DefaultArgumentKind::FilePath: - return swift::DefaultArgumentKind::FilePath; - case serialization::DefaultArgumentKind::Line: - return swift::DefaultArgumentKind::Line; - case serialization::DefaultArgumentKind::Function: - return swift::DefaultArgumentKind::Function; - case serialization::DefaultArgumentKind::DSOHandle: - return swift::DefaultArgumentKind::DSOHandle; - case serialization::DefaultArgumentKind::NilLiteral: - return swift::DefaultArgumentKind::NilLiteral; - case serialization::DefaultArgumentKind::EmptyArray: - return swift::DefaultArgumentKind::EmptyArray; - case serialization::DefaultArgumentKind::EmptyDictionary: - return swift::DefaultArgumentKind::EmptyDictionary; - case serialization::DefaultArgumentKind::StoredProperty: - return swift::DefaultArgumentKind::StoredProperty; +#define CASE(X) \ + case serialization::DefaultArgumentKind::X: \ + return swift::DefaultArgumentKind::X; + CASE(None) + CASE(Normal) + CASE(Inherited) + CASE(Column) + CASE(FileID) + CASE(FilePath) + CASE(FileIDSpelledAsFile) + CASE(FilePathSpelledAsFile) + CASE(Line) + CASE(Function) + CASE(DSOHandle) + CASE(NilLiteral) + CASE(EmptyArray) + CASE(EmptyDictionary) + CASE(StoredProperty) +#undef CASE } return None; } diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 3376baac0fb85..a82630319116f 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -55,7 +55,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 556; // Serialization of -implicit-dynamic +const uint16_t SWIFTMODULE_VERSION_MINOR = 557; // #fileID /// A standard hash seed used for all string hashes in a serialized module. /// @@ -459,8 +459,10 @@ using ValueOwnershipField = BCFixed<2>; enum class DefaultArgumentKind : uint8_t { None = 0, Normal, - File, + FileID, FilePath, + FileIDSpelledAsFile, + FilePathSpelledAsFile, Line, Column, Function, diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 322b7be43fd7f..2b200cf2a4af6 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1119,8 +1119,10 @@ static uint8_t getRawStableDefaultArgumentKind(swift::DefaultArgumentKind kind) CASE(Normal) CASE(Inherited) CASE(Column) - CASE(File) + CASE(FileID) CASE(FilePath) + CASE(FileIDSpelledAsFile) + CASE(FilePathSpelledAsFile) CASE(Line) CASE(Function) CASE(DSOHandle) diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 942f14939c439..2d726292d3a12 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -288,6 +288,9 @@ if(SWIFT_STDLIB_ENABLE_STDLIBCORE_EXCLUSIVITY_CHECKING) list(APPEND swift_stdlib_compile_flags "-enforce-exclusivity=checked") endif() +# STAGING: Temporarily avoids having to write #fileID in Swift.swiftinterface. +list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-experimental-concise-pound-file") + if(SWIFT_CHECK_ESSENTIAL_STDLIB) add_swift_target_library(swift_stdlib_essential ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STDLIB_CORE INSTALL_IN_COMPONENT never_install diff --git a/test/IDE/complete_pound_expr.swift b/test/IDE/complete_pound_expr.swift index 53f4af643c55a..66466ed5237c6 100644 --- a/test/IDE/complete_pound_expr.swift +++ b/test/IDE/complete_pound_expr.swift @@ -15,26 +15,32 @@ func test1() { let _ = useSelector(##^POUND_EXPR_3^#) } -// POUND_EXPR_INTCONTEXT: Begin completions, 5 items +// POUND_EXPR_INTCONTEXT: Begin completions, 7 items // POUND_EXPR_INTCONTEXT-DAG: Keyword[#function]/None: function[#String#]; name=function // POUND_EXPR_INTCONTEXT-DAG: Keyword[#file]/None: file[#String#]; name=file +// POUND_EXPR_INTCONTEXT-DAG: Keyword[#fileID]/None: fileID[#String#]; name=fileID +// POUND_EXPR_INTCONTEXT-DAG: Keyword[#filePath]/None: filePath[#String#]; name=filePath // POUND_EXPR_INTCONTEXT-DAG: Keyword[#line]/None/TypeRelation[Identical]: line[#Int#]; name=line // POUND_EXPR_INTCONTEXT-DAG: Keyword[#column]/None/TypeRelation[Identical]: column[#Int#]; name=column // POUND_EXPR_INTCONTEXT-DAG: Keyword[#dsohandle]/None: dsohandle[#UnsafeRawPointer#]; name=dsohandle // POUND_EXPR_INTCONTEXT: End completions -// POUND_EXPR_STRINGCONTEXT: Begin completions, 6 items +// POUND_EXPR_STRINGCONTEXT: Begin completions, 8 items // POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#function]/None/TypeRelation[Identical]: function[#String#]; // POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#file]/None/TypeRelation[Identical]: file[#String#]; +// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#fileID]/None/TypeRelation[Identical]: fileID[#String#]; +// POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#filePath]/None/TypeRelation[Identical]: filePath[#String#]; // POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#line]/None: line[#Int#]; // POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#column]/None: column[#Int#]; // POUND_EXPR_STRINGCONTEXT-DAG: Keyword[#dsohandle]/None: dsohandle[#UnsafeRawPointer#]; // POUND_EXPR_STRINGCONTEXT-DAG: Keyword/None/TypeRelation[Identical]: keyPath({#@objc property sequence#})[#String#]; // POUND_EXPR_STRINGCONTEXT: End completions -// POUND_EXPR_SELECTORCONTEXT: Begin completions, 6 items +// POUND_EXPR_SELECTORCONTEXT: Begin completions, 8 items // POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#function]/None/TypeRelation[Identical]: function[#Selector#]; // POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#file]/None/TypeRelation[Identical]: file[#Selector#]; +// POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#fileID]/None/TypeRelation[Identical]: fileID[#Selector#]; +// POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#filePath]/None/TypeRelation[Identical]: filePath[#Selector#]; // POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#line]/None: line[#Int#]; // POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#column]/None: column[#Int#]; // POUND_EXPR_SELECTORCONTEXT-DAG: Keyword[#dsohandle]/None: dsohandle[#UnsafeRawPointer#]; diff --git a/test/SILGen/Inputs/MagicIdentifierFileSwift.swift b/test/SILGen/Inputs/MagicIdentifierFileSwift.swift new file mode 100644 index 0000000000000..69e25ce3b8d35 --- /dev/null +++ b/test/SILGen/Inputs/MagicIdentifierFileSwift.swift @@ -0,0 +1 @@ +public func useLibrary(file: String = #file) {} diff --git a/test/SILGen/Inputs/magic_identifier_file_conflicting_other.swift b/test/SILGen/Inputs/magic_identifier_file_conflicting_other.swift index 602b96c9b589a..d3d884dc20d33 100644 --- a/test/SILGen/Inputs/magic_identifier_file_conflicting_other.swift +++ b/test/SILGen/Inputs/magic_identifier_file_conflicting_other.swift @@ -2,7 +2,7 @@ // It should be compiled with -verify. // We should diagnose cross-file conflicts. -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_c.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_c.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to 'first/other_file_c.swift'}} {{23-50="first/other_file_c.swift"}} #sourceLocation(file: "second/other_file_c.swift", line: 1) #sourceLocation() diff --git a/test/SILGen/magic_identifier_file.swift b/test/SILGen/magic_identifier_file.swift index 7e67de96909bc..fb38b28b1fce6 100644 --- a/test/SILGen/magic_identifier_file.swift +++ b/test/SILGen/magic_identifier_file.swift @@ -1,8 +1,28 @@ -// RUN: %target-swift-emit-silgen -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,ABSOLUTE %s -// RUN: %target-swift-emit-silgen -enable-experimental-concise-pound-file -DNEEDS_CONCISE -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,CONCISE %s +// RUN: %empty-directory(%t) -// FIXME: Once this feature becomes non-experimental, we should update existing -// tests and delete this file. +// Build library in Swift 5 mode: +// RUN: %target-build-swift-dylib(%t/%target-library-name(MagicIdentifierFileSwift5)) -module-name MagicIdentifierFileSwift5 -emit-module-path %t/MagicIdentifierFileSwift5.swiftmodule -emit-module-interface-path %t/MagicIdentifierFileSwift5.swiftinterface -swift-version 5 -enable-library-evolution %S/Inputs/MagicIdentifierFileSwift.swift + +// Build library in "Swift 6" mode: +// RUN: %target-build-swift-dylib(%t/%target-library-name(MagicIdentifierFileSwift6)) -module-name MagicIdentifierFileSwift6 -emit-module-path %t/MagicIdentifierFileSwift6.swiftmodule -emit-module-interface-path %t/MagicIdentifierFileSwift6.swiftinterface -swift-version 5 -enable-experimental-concise-pound-file -enable-library-evolution %S/Inputs/MagicIdentifierFileSwift.swift + +// Test in Swift 5 mode: +// RUN: %target-swift-emit-silgen -I %t -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,ABSOLUTE %s + +// Test in "Swift 6" mode: +// RUN: %target-swift-emit-silgen -I %t -enable-experimental-concise-pound-file -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,CONCISE %s + +// Remove compiled modules so we test against interfaces: +// RUN: rm %t/MagicIdentifierFileSwift5.swiftmodule %t/MagicIdentifierFileSwift6.swiftmodule + +// Test in Swift 5 mode: +// RUN: %target-swift-emit-silgen -I %t -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,ABSOLUTE %s + +// Test in "Swift 6" mode: +// RUN: %target-swift-emit-silgen -I %t -enable-experimental-concise-pound-file -module-name Foo %/s | %FileCheck --check-prefixes=BOTH,CONCISE %s + +import MagicIdentifierFileSwift5 +import MagicIdentifierFileSwift6 func directUse() { // BOTH-LABEL: sil {{.*}} @$s3Foo9directUseyyF @@ -13,25 +33,43 @@ func directUse() { func indirectUse() { // BOTH-LABEL: sil {{.*}} @$s3Foo11indirectUseyyF - fatalError() + useIndirectly() // ABSOLUTE: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift" // CONCISE: string_literal utf8 "Foo/magic_identifier_file.swift" } +func swift5LibraryUse() { +// BOTH-LABEL: sil {{.*}} @$s3Foo16swift5LibraryUseyyF + MagicIdentifierFileSwift5.useLibrary() +// BOTH: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift" +} + +func swift6LibraryUse() { +// BOTH-LABEL: sil {{.*}} @$s3Foo16swift6LibraryUseyyF + MagicIdentifierFileSwift6.useLibrary() +// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift" +} + +func stdlibUse() { +// BOTH-LABEL: sil {{.*}} @$s3Foo9stdlibUseyyF + fatalError() +// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift" +} + func forceUnwrap(_ x: ()?) { // BOTH-LABEL: sil {{.*}} @$s3Foo11forceUnwrapyyytSgF _ = x! -// ABSOLUTE: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift" -// CONCISE: string_literal utf8 "Foo/magic_identifier_file.swift" +// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift" } func forceTry(_ fn: () throws -> ()) { // BOTH-LABEL: sil {{.*}} @$s3Foo8forceTryyyyyKXEF try! fn() -// ABSOLUTE: string_literal utf8 "SOURCE_DIR/test/SILGen/magic_identifier_file.swift" -// CONCISE: string_literal utf8 "Foo/magic_identifier_file.swift" +// BOTH: string_literal utf8 "Foo/magic_identifier_file.swift" } -// CONCISE-LABEL: // Mappings from '#file' to '#filePath': +func useIndirectly(file: String = #file) {} + +// CONCISE-LABEL: // Mappings from '#fileID' to '#filePath': // CONCISE: // 'Foo/magic_identifier_file.swift' => 'SOURCE_DIR/test/SILGen/magic_identifier_file.swift' diff --git a/test/SILGen/magic_identifier_file_conflicting.swift.gyb b/test/SILGen/magic_identifier_file_conflicting.swift.gyb index 350304b90936d..9444ecea8b431 100644 --- a/test/SILGen/magic_identifier_file_conflicting.swift.gyb +++ b/test/SILGen/magic_identifier_file_conflicting.swift.gyb @@ -33,12 +33,12 @@ def fixit_loc(start_col, orig_suffix): #sourceLocation(file: "${TEMPDIR_ESC}/magic_identifier_file_conflicting.swift", line: 10) #sourceLocation() -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/magic_identifier_file_conflicting.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/magic_identifier_file_conflicting.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to '${TEMPDIR_ESC}/magic_identifier_file_conflicting.swift'}} {{${fixit_loc(23, "other_path_b/magic_identifier_file_conflicting.swift")}="${TEMPDIR_ESC}/magic_identifier_file_conflicting.swift"}} #sourceLocation(file: "${TEMPDIR_ESC}/other_path_b/magic_identifier_file_conflicting.swift", line: 20) #sourceLocation() -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/magic_identifier_file_conflicting.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/magic_identifier_file_conflicting.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to '${TEMPDIR_ESC}/magic_identifier_file_conflicting.swift'}} {{23-64="${TEMPDIR_ESC}/magic_identifier_file_conflicting.swift"}} #sourceLocation(file: "magic_identifier_file_conflicting.swift", line: 30) #sourceLocation() @@ -60,38 +60,38 @@ def fixit_loc(start_col, orig_suffix): // But there should be warnings for different-path, same-name virtual files. // The lexicographically first path should be treated as canonical--we diagnose // but don't offer a fix-it. -// expected-warning@+1 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_b.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+1 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_b.swift', which conflicts with '#fileID' strings produced by other paths in the module}} #sourceLocation(file: "first/other_file_b.swift", line: 60) #sourceLocation() // Subsequent paths should fix-it to the first one. -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_b.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_b.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to 'first/other_file_b.swift'}} {{23-50="first/other_file_b.swift"}} #sourceLocation(file: "second/other_file_b.swift", line: 70) #sourceLocation() // Even if there's more than one. -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_b.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_b.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to 'first/other_file_b.swift'}} {{23-49="first/other_file_b.swift"}} #sourceLocation(file: "third/other_file_b.swift", line: 80) #sourceLocation() // Even if one is duplicated. -// expected-warning@+2 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_b.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+2 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_b.swift', which conflicts with '#fileID' strings produced by other paths in the module}} // expected-note@+1 {{change file in '#sourceLocation' to 'first/other_file_b.swift'}} {{23-49="first/other_file_b.swift"}} #sourceLocation(file: "third/other_file_b.swift", line: 90) #sourceLocation() // We should diagnose cross-file conflicts. -// expected-warning@+1 {{'#sourceLocation' directive produces '#file' string of 'Foo/other_file_c.swift', which conflicts with '#file' strings produced by other paths in the module}} +// expected-warning@+1 {{'#sourceLocation' directive produces '#fileID' string of 'Foo/other_file_c.swift', which conflicts with '#fileID' strings produced by other paths in the module}} #sourceLocation(file: "first/other_file_c.swift", line: 100) #sourceLocation() // -// Check '#file' => '#filePath' mapping table +// Check '#fileID' => '#filePath' mapping table // -// CHECK-LABEL: // Mappings from '#file' to '#filePath': +// CHECK-LABEL: // Mappings from '#fileID' to '#filePath': // CHECK-NEXT: // 'Foo/magic_identifier_file_conflicting.swift' => 'BUILD_DIR{{[/\\]}}test-{{[^/]+}}{{[/\\]}}SILGen{{[/\\]}}Output{{[/\\]}}magic_identifier_file_conflicting.swift.gyb.tmp{{[/\\]}}magic_identifier_file_conflicting.swift' // CHECK-NEXT: // 'Foo/magic_identifier_file_conflicting.swift' => 'BUILD_DIR{{[/\\]}}test-{{[^/]+}}{{[/\\]}}SILGen{{[/\\]}}Output{{[/\\]}}magic_identifier_file_conflicting.swift.gyb.tmp{{[/\\]}}other_path_b{{[/\\]}}magic_identifier_file_conflicting.swift' (alternate) // CHECK-NEXT: // 'Foo/magic_identifier_file_conflicting.swift' => 'magic_identifier_file_conflicting.swift' (alternate) diff --git a/test/SILGen/optional.swift b/test/SILGen/optional.swift index 7db22ac37dfab..2a771913b6f04 100644 --- a/test/SILGen/optional.swift +++ b/test/SILGen/optional.swift @@ -105,7 +105,7 @@ func crash_on_dealloc(_ dict : [Int : [Int]] = [:]) { func use_unwrapped(_: Int) {} // CHECK-LABEL: sil hidden [ossa] @$s8optional15explicit_unwrap{{[_0-9a-zA-Z]*}}F -// CHECK: [[FILESTR:%.*]] = string_literal utf8 "{{.*}}optional.swift" +// CHECK: [[FILESTR:%.*]] = string_literal utf8 "optional/optional.swift" // CHECK-NEXT: [[FILESIZ:%.*]] = integer_literal $Builtin.Word, // CHECK-NEXT: [[FILEASC:%.*]] = integer_literal $Builtin.Int1, // CHECK-NEXT: [[LINE:%.*]] = integer_literal $Builtin.Word, @@ -118,7 +118,7 @@ func explicit_unwrap(_ value: Int?) { } // CHECK-LABEL: sil hidden [ossa] @$s8optional19explicit_iuo_unwrap{{[_0-9a-zA-Z]*}}F -// CHECK: [[FILESTR:%.*]] = string_literal utf8 "{{.*}}optional.swift" +// CHECK: [[FILESTR:%.*]] = string_literal utf8 "optional/optional.swift" // CHECK-NEXT: [[FILESIZ:%.*]] = integer_literal $Builtin.Word, // CHECK-NEXT: [[FILEASC:%.*]] = integer_literal $Builtin.Int1, // CHECK-NEXT: [[LINE:%.*]] = integer_literal $Builtin.Word, @@ -131,7 +131,7 @@ func explicit_iuo_unwrap(_ value: Int!) { } // CHECK-LABEL: sil hidden [ossa] @$s8optional19implicit_iuo_unwrap{{[_0-9a-zA-Z]*}}F -// CHECK: [[FILESTR:%.*]] = string_literal utf8 "{{.*}}optional.swift" +// CHECK: [[FILESTR:%.*]] = string_literal utf8 "optional/optional.swift" // CHECK-NEXT: [[FILESIZ:%.*]] = integer_literal $Builtin.Word, // CHECK-NEXT: [[FILEASC:%.*]] = integer_literal $Builtin.Int1, // CHECK-NEXT: [[LINE:%.*]] = integer_literal $Builtin.Word, @@ -144,7 +144,7 @@ func implicit_iuo_unwrap(_ value: Int!) { } // CHECK-LABEL: sil hidden [ossa] @$s8optional34implicit_iuo_unwrap_sourceLocation{{[_0-9a-zA-Z]*}}F -// CHECK: [[FILESTR:%.*]] = string_literal utf8 "custom.swuft" +// CHECK: [[FILESTR:%.*]] = string_literal utf8 "optional/custom.swuft" // CHECK-NEXT: [[FILESIZ:%.*]] = integer_literal $Builtin.Word, // CHECK-NEXT: [[FILEASC:%.*]] = integer_literal $Builtin.Int1, // CHECK-NEXT: [[LINE:%.*]] = integer_literal $Builtin.Word, 2000 diff --git a/test/SILOptimizer/Inputs/specialize_inherited_multifile.swift b/test/SILOptimizer/Inputs/specialize_inherited_multifile_other.swift similarity index 100% rename from test/SILOptimizer/Inputs/specialize_inherited_multifile.swift rename to test/SILOptimizer/Inputs/specialize_inherited_multifile_other.swift diff --git a/test/SILOptimizer/specialize_inherited_multifile.swift b/test/SILOptimizer/specialize_inherited_multifile.swift index d00de25e890bc..c39947a8fbba9 100644 --- a/test/SILOptimizer/specialize_inherited_multifile.swift +++ b/test/SILOptimizer/specialize_inherited_multifile.swift @@ -1,5 +1,5 @@ -// RUN: %target-swift-frontend -module-name specialize_inherited_multifile -primary-file %s %S/Inputs/specialize_inherited_multifile.swift -O -emit-sil -sil-verify-all | %FileCheck %s +// RUN: %target-swift-frontend -module-name specialize_inherited_multifile -primary-file %s %S/Inputs/specialize_inherited_multifile_other.swift -O -emit-sil -sil-verify-all | %FileCheck %s @_optimize(none) func takesBase(t: T) {} diff --git a/test/Sema/diag_mismatched_magic_literals.swift b/test/Sema/diag_mismatched_magic_literals.swift index 2701e39b6472b..e06caaf7ce8c9 100644 --- a/test/Sema/diag_mismatched_magic_literals.swift +++ b/test/Sema/diag_mismatched_magic_literals.swift @@ -1,7 +1,13 @@ // RUN: %target-typecheck-verify-swift +// RUN: %target-typecheck-verify-swift -enable-experimental-concise-pound-file + +// The test cases in this file work the same in both Swift 5 and "Swift 6" mode. +// See the _swift5 and _swift6 files for version-specific test cases. func callee(file: String = #file) {} // expected-note {{'file' declared here}} func callee(optFile: String? = #file) {} // expected-note {{'optFile' declared here}} +func callee(fileID: String = #fileID) {} // expected-note {{'fileID' declared here}} +func callee(filePath: String = #filePath) {} // expected-note {{'filePath' declared here}} func callee(arbitrary: String) {} class SomeClass { @@ -22,6 +28,9 @@ class SomeClass { // `#file`-defaulted argument. func bad(function: String = #function) { // expected-note@-1 3{{did you mean for parameter 'function' to default to '#file'?}} {{29-38=#file}} + // expected-note@-2 {{did you mean for parameter 'function' to default to '#fileID'?}} {{29-38=#fileID}} + // expected-note@-3 {{did you mean for parameter 'function' to default to '#filePath'?}} {{29-38=#filePath}} + callee(file: function) // expected-warning@-1 {{parameter 'function' with default argument '#function' passed to parameter 'file', whose default argument is '#file'}} // expected-note@-2 {{add parentheses to silence this warning}} {{16-16=(}} {{24-24=)}} @@ -33,16 +42,28 @@ func bad(function: String = #function) { SomeClass().callee(file: function) // expected-warning@-1 {{parameter 'function' with default argument '#function' passed to parameter 'file', whose default argument is '#file'}} // expected-note@-2 {{add parentheses to silence this warning}} {{28-28=(}} {{36-36=)}} + + callee(fileID: function) + // expected-warning@-1 {{parameter 'function' with default argument '#function' passed to parameter 'fileID', whose default argument is '#fileID'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{18-18=(}} {{26-26=)}} + + callee(filePath: function) + // expected-warning@-1 {{parameter 'function' with default argument '#function' passed to parameter 'filePath', whose default argument is '#filePath'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{20-20=(}} {{28-28=)}} } // We should not warn when we pass a `#file`-defaulted argument to a // `#file`-defaulted argument. -func good(file: String = #file) { +func good(file: String = #file, fileID: String = #fileID, filePath: String = #filePath) { callee(file: file) SomeClass.callee(file: file) SomeClass().callee(file: file) + + callee(fileID: fileID) + + callee(filePath: filePath) } // We should not warn when we surround the `#function`-defaulted argument @@ -53,6 +74,10 @@ func disabled(function: String = #function) { SomeClass.callee(file: (function)) SomeClass().callee(file: (function)) + + callee(fileID: (function)) + + callee(filePath: (function)) } // diff --git a/test/Sema/diag_mismatched_magic_literals_swift5.swift b/test/Sema/diag_mismatched_magic_literals_swift5.swift new file mode 100644 index 0000000000000..807210ac23ee8 --- /dev/null +++ b/test/Sema/diag_mismatched_magic_literals_swift5.swift @@ -0,0 +1,37 @@ +// RUN: %target-typecheck-verify-swift + +func callee(file: String = #file) {} +func callee(fileID: String = #fileID) {} // expected-note {{'fileID' declared here}} +func callee(filePath: String = #filePath) {} // expected-note {{'filePath' declared here}} + +// +// #file equivalence +// +// These cases vary depending on -enable-experimental-concise-pound-file. +// + +func passingToFile(fileID: String = #fileID, filePath: String = #filePath) { + callee(file: fileID) + + callee(file: filePath) +} + +func passingToFileID(file: String = #file, filePath: String = #filePath) { + // expected-note@-1 {{did you mean for parameter 'filePath' to default to '#fileID'?}} {{63-72=#fileID}} + + callee(fileID: file) + + callee(fileID: filePath) + // expected-warning@-1 {{parameter 'filePath' with default argument '#filePath' passed to parameter 'fileID', whose default argument is '#fileID'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{18-18=(}} {{26-26=)}} +} + +func passingToFilePath(file: String = #file, fileID: String = #fileID) { + // expected-note@-1 {{did you mean for parameter 'fileID' to default to '#filePath'?}} {{63-70=#filePath}} + + callee(filePath: file) + + callee(filePath: fileID) + // expected-warning@-1 {{parameter 'fileID' with default argument '#fileID' passed to parameter 'filePath', whose default argument is '#filePath'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{20-20=(}} {{26-26=)}} +} diff --git a/test/Sema/diag_mismatched_magic_literals_swift6.swift b/test/Sema/diag_mismatched_magic_literals_swift6.swift new file mode 100644 index 0000000000000..763f21d70eeee --- /dev/null +++ b/test/Sema/diag_mismatched_magic_literals_swift6.swift @@ -0,0 +1,45 @@ +// The future "Swift 6 mode" behavior is staged in behind `-enable-experimental-concise-pound-file`. +// RUN: %target-typecheck-verify-swift -enable-experimental-concise-pound-file + +func callee(file: String = #file) {} // expected-note {{'file' declared here}} +func callee(fileID: String = #fileID) {} // expected-note {{'fileID' declared here}} +func callee(filePath: String = #filePath) {} // expected-note 2 {{'filePath' declared here}} + +// +// #file equivalence +// +// These cases vary depending on -enable-experimental-concise-pound-file. +// + +func passingToFile(fileID: String = #fileID, filePath: String = #filePath) { + // expected-note@-1 {{did you mean for parameter 'filePath' to default to '#file'?}} {{65-74=#file}} + + callee(file: fileID) + + callee(file: filePath) + // expected-warning@-1 {{parameter 'filePath' with default argument '#filePath' passed to parameter 'file', whose default argument is '#file'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{16-16=(}} {{24-24=)}} +} + +func passingToFileID(file: String = #file, filePath: String = #filePath) { + // expected-note@-1 {{did you mean for parameter 'filePath' to default to '#fileID'?}} {{63-72=#fileID}} + + callee(fileID: file) + + callee(fileID: filePath) + // expected-warning@-1 {{parameter 'filePath' with default argument '#filePath' passed to parameter 'fileID', whose default argument is '#fileID'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{18-18=(}} {{26-26=)}} +} + +func passingToFilePath(file: String = #file, fileID: String = #fileID) { + // expected-note@-1 {{did you mean for parameter 'fileID' to default to '#filePath'?}} {{63-70=#filePath}} + // expected-note@-2 {{did you mean for parameter 'file' to default to '#filePath'?}} {{39-44=#filePath}} + + callee(filePath: file) + // expected-warning@-1 {{parameter 'file' with default argument '#file' passed to parameter 'filePath', whose default argument is '#filePath'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{20-20=(}} {{24-24=)}} + + callee(filePath: fileID) + // expected-warning@-1 {{parameter 'fileID' with default argument '#fileID' passed to parameter 'filePath', whose default argument is '#filePath'}} + // expected-note@-2 {{add parentheses to silence this warning}} {{20-20=(}} {{26-26=)}} +} diff --git a/test/Serialization/Inputs/multi-file-type-eraser.swift b/test/Serialization/Inputs/multi-file-type-eraser-other.swift similarity index 100% rename from test/Serialization/Inputs/multi-file-type-eraser.swift rename to test/Serialization/Inputs/multi-file-type-eraser-other.swift diff --git a/test/Serialization/multi-file-type-eraser.swift b/test/Serialization/multi-file-type-eraser.swift index 9272cfe4400d7..ee2eb7ad9d636 100644 --- a/test/Serialization/multi-file-type-eraser.swift +++ b/test/Serialization/multi-file-type-eraser.swift @@ -1,7 +1,7 @@ // REQUIRES: asserts // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -module-name Multi -o %t/multi-file.swiftmodule -primary-file %s %S/Inputs/multi-file-type-eraser.swift -// RUN: %target-swift-frontend -emit-module -module-name Multi -o %t/multi-file-2.swiftmodule %s -primary-file %S/Inputs/multi-file-type-eraser.swift +// RUN: %target-swift-frontend -emit-module -module-name Multi -o %t/multi-file.swiftmodule -primary-file %s %S/Inputs/multi-file-type-eraser-other.swift +// RUN: %target-swift-frontend -emit-module -module-name Multi -o %t/multi-file-2.swiftmodule %s -primary-file %S/Inputs/multi-file-type-eraser-other.swift // RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file.swiftmodule %t/multi-file-2.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s // RUN: %target-swift-frontend -emit-module -module-name Multi %t/multi-file-2.swiftmodule %t/multi-file.swiftmodule -o %t -print-stats 2>&1 | %FileCheck %s diff --git a/test/stdlib/Error.swift b/test/stdlib/Error.swift index fc40c77b061f3..1f3f20a623f5b 100644 --- a/test/stdlib/Error.swift +++ b/test/stdlib/Error.swift @@ -121,7 +121,7 @@ ErrorTests.test("try!/location") .skip(.custom({ _isFastAssertConfiguration() }, reason: "trap is not guaranteed to happen in -Ounchecked")) .crashOutputMatches(_isDebugAssertConfiguration() - ? "test/stdlib/Error.swift, line 128" + ? "main/Error.swift, line 128" : "") .code { expectCrashLater() diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index c5ebc8a4b976b..d0d68d1c7cab8 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -130,6 +130,12 @@ Child('PoundFile', kind='PoundFileToken'), ]), + # A #fileID expression. + Node('PoundFileIDExpr', kind='Expr', + children=[ + Child('PoundFileID', kind='PoundFileIDToken'), + ]), + # A #filePath expression. Node('PoundFilePathExpr', kind='Expr', children=[ diff --git a/utils/gyb_syntax_support/NodeSerializationCodes.py b/utils/gyb_syntax_support/NodeSerializationCodes.py index eeea90df395eb..92d63b345c48c 100644 --- a/utils/gyb_syntax_support/NodeSerializationCodes.py +++ b/utils/gyb_syntax_support/NodeSerializationCodes.py @@ -248,6 +248,7 @@ 'CatchItemList': 244, 'MultipleTrailingClosureElementList': 245, 'MultipleTrailingClosureElement': 246, + 'PoundFileIDExpr': 247, } diff --git a/utils/gyb_syntax_support/Token.py b/utils/gyb_syntax_support/Token.py index aaacc4fcfeb33..5f15579bef3e0 100644 --- a/utils/gyb_syntax_support/Token.py +++ b/utils/gyb_syntax_support/Token.py @@ -265,6 +265,8 @@ def macro_name(self): serialization_code=73), PoundKeyword('PoundFile', 'file', text='#file', serialization_code=68), + PoundKeyword('PoundFileID', 'fileID', text='#fileID', + serialization_code=122), PoundKeyword('PoundFilePath', 'filePath', text='#filePath', serialization_code=121), PoundKeyword('PoundColumn', 'column', text='#column',