Merge pull request #80070 from gottesmm/swift-settings-only-once

[swift-settings] Only allow for a setting to be passed exactly once to #SwiftSettings.
This commit is contained in:
Michael Gottesman
2025-03-17 19:12:00 -07:00
committed by GitHub
4 changed files with 71 additions and 4 deletions

View File

@@ -61,6 +61,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -4195,11 +4196,19 @@ version::Version ModuleDecl::getLanguageVersionBuiltWith() const {
// MARK: SwiftSettings
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool> AllowForDuplicateSwiftSettings(
"swift-settings-allow-duplicates",
llvm::cl::desc("Option that allows for duplicate SwiftSettings. Just for "
"compiler testing"),
llvm::cl::Hidden);
namespace {
enum class SwiftSettingKind {
Unknown = 0,
DefaultIsolation,
LastKind = DefaultIsolation,
};
struct SwiftSettingsWalker : ASTWalker {
@@ -4207,8 +4216,21 @@ struct SwiftSettingsWalker : ASTWalker {
ASTContext &ctx;
SourceFileLangOptions result;
SmallVector<Expr *, 1> swiftSettingIndexToOriginalExprMap;
SwiftSettingsWalker(SourceFile &sf, ASTContext &ctx)
: sf(sf), ctx(ctx), result() {}
: sf(sf), ctx(ctx), result() {
// NOTE: We do not store a value for Unknown.
for (unsigned i : range(unsigned(SwiftSettingKind::LastKind))) {
(void)i;
swiftSettingIndexToOriginalExprMap.push_back(nullptr);
}
}
Expr *&getOriginalSwiftSetting(SwiftSettingKind kind) {
assert(kind != SwiftSettingKind::Unknown);
return swiftSettingIndexToOriginalExprMap[unsigned(kind) - 1];
}
/// Given a specific CallExpr, pattern matches the CallExpr's first argument
/// to validate it is MainActor.self. Returns CanType() if the CallExpr has
@@ -4267,13 +4289,30 @@ struct SwiftSettingsWalker : ASTWalker {
continue;
case SwiftSettingKind::DefaultIsolation:
auto *&expr =
getOriginalSwiftSetting(SwiftSettingKind::DefaultIsolation);
// If we already have an expr, emit an error and continue.
if (!AllowForDuplicateSwiftSettings && expr) {
ctx.Diags.diagnose(arg.getStartLoc(),
diag::swift_settings_duplicate_setting);
ctx.Diags.diagnose(
expr->getLoc(),
diag::swift_settings_duplicate_setting_original_loc);
foundValidArg = true;
continue;
}
// Otherwise, set things up appropriately.
if (auto actor = patternMatchDefaultIsolationMainActor(callExpr)) {
expr = callExpr;
result.defaultIsolation = actor;
foundValidArg = true;
continue;
}
if (isa<NilLiteralExpr>(callExpr->getArgs()->getExpr(0))) {
expr = callExpr;
result.defaultIsolation = {Type()};
foundValidArg = true;
continue;
@@ -4344,7 +4383,7 @@ SwiftSettingsWalker::getSwiftSettingArgDecl(Argument arg) {
return {};
// Now lookup our swiftSettingDecl.
NominalTypeDecl *swiftSettingsDecl;
NominalTypeDecl *swiftSettingsDecl = nullptr;
{
SmallVector<ValueDecl *, 1> decls;
ctx.lookupInSwiftModule("SwiftSetting", decls);