Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/AST/DiagnosticEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ namespace swift {
ignoredDiagnostics[(unsigned)id] = ignored;
}

bool isIgnoredDiagnostic(DiagID id) const {
return ignoredDiagnostics[(unsigned)id];
}

void swap(DiagnosticState &other) {
std::swap(showDiagnosticsAfterFatalError, other.showDiagnosticsAfterFatalError);
std::swap(suppressWarnings, other.suppressWarnings);
Expand Down Expand Up @@ -947,6 +951,10 @@ namespace swift {
state.setIgnoredDiagnostic(id, true);
}

bool isIgnoredDiagnostic(DiagID id) const {
return state.isIgnoredDiagnostic(id);
}

void resetHadAnyError() {
state.resetHadAnyError();
}
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/DiagnosticGroups.def
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GROUP(ClangDeclarationImport, "clang-declaration-import")
GROUP(ConformanceIsolation, "conformance-isolation")
GROUP(DeprecatedDeclaration, "deprecated-declaration")
GROUP(DynamicCallable, "dynamic-callable-requirements")
GROUP(EmbeddedRestrictions, "embedded-restrictions")
GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
GROUP(ExclusivityViolation, "exclusivity-violation")
GROUP(ExistentialAny, "existential-any")
Expand Down
15 changes: 12 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2234,9 +2234,6 @@ ERROR(attr_only_at_non_generic_scope, none,
ERROR(attr_only_on_static_properties, none,
"properties with attribute %0 must be static", (DeclAttribute))

ERROR(weak_unowned_in_embedded_swift, none,
"attribute %0 cannot be used in embedded Swift", (ReferenceOwnership))

ERROR(access_control_in_protocol,none,
"%0 modifier cannot be used in protocols", (DeclAttribute))
NOTE(access_control_in_protocol_detail,none,
Expand Down Expand Up @@ -8606,6 +8603,18 @@ ERROR(inlinearray_literal_incorrect_count,none,
ERROR(inline_array_type_backwards,none,
"element count must precede inline array element type", ())

//===----------------------------------------------------------------------===//
// MARK: Embedded Swift
//===----------------------------------------------------------------------===//

GROUPED_ERROR(weak_unowned_in_embedded_swift, EmbeddedRestrictions, none,
"attribute %0 cannot be used in Embedded Swift",
(ReferenceOwnership))

GROUPED_WARNING(untyped_throws_in_embedded_swift, EmbeddedRestrictions,
DefaultIgnore,
"untyped throws is not available in Embedded Swift; add a thrown error type with '(type)'", ())

//===----------------------------------------------------------------------===//
// MARK: @abi Attribute
//===----------------------------------------------------------------------===//
Expand Down
5 changes: 5 additions & 0 deletions include/swift/Bridging/ASTGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ intptr_t swift_ASTGen_configuredRegions(
void swift_ASTGen_freeConfiguredRegions(
BridgedIfConfigClauseRangeInfo *_Nullable regions, intptr_t numRegions);

intptr_t swift_ASTGen_activeInEmbeddedSwift(
BridgedASTContext astContext,
void *_Nonnull sourceFile,
swift::SourceLoc location);

bool swift_ASTGen_validateUnqualifiedLookup(
void *_Nonnull sourceFile,
BridgedASTContext astContext,
Expand Down
1 change: 1 addition & 0 deletions lib/ASTGen/Sources/ASTGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_pure_swift_host_library(swiftASTGen STATIC CXX_INTEROP
Decls.swift
Diagnostics.swift
DiagnosticsBridge.swift
EmbeddedSupport.swift
Exprs.swift
Fingerprint.swift
Generics.swift
Expand Down
142 changes: 142 additions & 0 deletions lib/ASTGen/Sources/ASTGen/EmbeddedSupport.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//===--- EmbeddedSupport.swift --------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022-2025 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
//
//===----------------------------------------------------------------------===//

import ASTBridging
import BasicBridging
import SwiftIfConfig
import SwiftSyntax

extension ExportedSourceFile {
/// Return the configured regions for this source file.
mutating func configuredRegionsIfEmbedded(astContext: BridgedASTContext) -> ConfiguredRegions {
if let _configuredRegionsIfEmbedded {
return _configuredRegionsIfEmbedded
}

// Ensure that we've already computed the configured regions, which can
// emit diagnostics.
_ = configuredRegions(astContext: astContext)

let configuration = EmbeddedBuildConfiguration(
ctx: astContext,
sourceBuffer: buffer
)

let regions = syntax.configuredRegions(in: configuration)
_configuredRegionsIfEmbedded = regions
return regions
}
}

/// Determine whether the given source location is active when this source
/// file is compiled in Embedded Swift.
@_cdecl("swift_ASTGen_activeInEmbeddedSwift")
public func activeInEmbeddedSwift(
astContext: BridgedASTContext,
sourceFilePtr: UnsafeMutableRawPointer,
at location: SourceLoc
) -> Int {
guard let token = findToken(
in: UnsafeRawPointer(sourceFilePtr),
at: location.raw?.assumingMemoryBound(to: UInt8.self)
) else {
return 0
}

let sourceFile = sourceFilePtr.assumingMemoryBound(to: ExportedSourceFile.self)
let regions = sourceFile.pointee.configuredRegionsIfEmbedded(astContext: astContext)
return regions.isActive(token) == .active ? 1 : 0
}

/// A build configuration that is a thin shim over the
/// CompilerBuildConfiguration that enables the Embedded language feature,
/// allowing the compiler to determine whether code we're in will be available
/// in an embedded context or not.
struct EmbeddedBuildConfiguration: BuildConfiguration {
let configuration: CompilerBuildConfiguration

init(ctx: BridgedASTContext, sourceBuffer: UnsafeBufferPointer<UInt8>) {
self.configuration = .init(ctx: ctx, sourceBuffer: sourceBuffer)
}

func isCustomConditionSet(name: String) throws -> Bool {
// $Embedded is set when building Embedded Swift
if name == "$Embedded" {
return true
}

return try configuration.isCustomConditionSet(name: name)
}

func hasFeature(name: String) throws -> Bool {
// The "Embedded" feature is set when building Embedded Swift.
if name == "Embedded" {
return true
}

return try configuration.hasFeature(name: name)
}

func hasAttribute(name: String) throws -> Bool {
return try configuration.hasAttribute(name: name)
}

func canImport(
importPath: [(TokenSyntax, String)],
version: CanImportVersion
) throws -> Bool {
// FIXME: We would prefer to call the underlying canImport in some kind of
// "replay" mode that is not allowed to produce diagnostics or trigger any
// loading.
return false
}

func isActiveTargetOS(name: String) throws -> Bool {
return try configuration.isActiveTargetOS(name: name)
}

func isActiveTargetArchitecture(name: String) throws -> Bool {
return try configuration.isActiveTargetArchitecture(name: name)
}

func isActiveTargetEnvironment(name: String) throws -> Bool {
return try configuration.isActiveTargetEnvironment(name: name)
}

func isActiveTargetRuntime(name: String) throws -> Bool {
return try configuration.isActiveTargetRuntime(name: name)
}

func isActiveTargetPointerAuthentication(name: String) throws -> Bool {
return try configuration.isActiveTargetPointerAuthentication(name: name)
}

var targetPointerBitWidth: Int {
return configuration.targetPointerBitWidth
}

var targetAtomicBitWidths: [Int] {
return configuration.targetAtomicBitWidths
}

var endianness: Endianness {
return configuration.endianness
}

var languageVersion: VersionTuple {
return configuration.languageVersion
}

var compilerVersion: VersionTuple {
return configuration.compilerVersion
}
}
8 changes: 8 additions & 0 deletions lib/ASTGen/Sources/ASTGen/SourceFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ public struct ExportedSourceFile {
/// This is a cached value; access via configuredRegions(astContext:).
var _configuredRegions: ConfiguredRegions? = nil

/// Configured regions for this source file assuming if it were being treated
/// as Embedded Swift. This is used only when we are compiling non-Embedded
/// Swift but diagnosing uses of constructs that aren't allowed in Embedded
/// Swift.
///
/// This is a cached value; access via configuredRegionsAsEmbedded(astContext:).
var _configuredRegionsIfEmbedded: ConfiguredRegions? = nil

public func position(of location: SourceLoc) -> AbsolutePosition? {
let sourceFileBaseAddress = UnsafeRawPointer(buffer.baseAddress!)
guard let rawAddress = location.raw else {
Expand Down
1 change: 1 addition & 0 deletions lib/Sema/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ add_swift_host_library(swiftSema STATIC
TypeCheckEffects.cpp
TypeCheckExpr.cpp
TypeCheckExprObjC.cpp
TypeCheckEmbedded.cpp
TypeCheckGeneric.cpp
TypeCheckInvertible.cpp
TypeCheckMacros.cpp
Expand Down
4 changes: 4 additions & 0 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "OpenedExistentials.h"
#include "TypeCheckAvailability.h"
#include "TypeCheckConcurrency.h"
#include "TypeCheckEmbedded.h"
#include "TypeCheckMacros.h"
#include "TypeCheckType.h"
#include "TypeChecker.h"
Expand Down Expand Up @@ -1456,6 +1457,9 @@ FunctionType::ExtInfo ClosureEffectsRequest::evaluate(
bool sendable = expr->getAttrs().hasAttribute<SendableAttr>();

if (throws || async) {
if (expr->getThrowsLoc().isValid() && !expr->getExplicitThrownTypeRepr())
diagnoseUntypedThrowsInEmbedded(expr, expr->getThrowsLoc());

return ASTExtInfoBuilder()
.withThrows(throws, /*FIXME:*/Type())
.withAsync(async)
Expand Down
9 changes: 6 additions & 3 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "TypeCheckAvailability.h"
#include "TypeCheckConcurrency.h"
#include "TypeCheckDistributed.h"
#include "TypeCheckEmbedded.h"
#include "TypeCheckMacros.h"
#include "TypeCheckObjC.h"
#include "TypeCheckType.h"
Expand Down Expand Up @@ -5501,12 +5502,14 @@ Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
}

// Embedded Swift prohibits weak/unowned but allows unowned(unsafe).
if (ctx.LangOpts.hasFeature(Feature::Embedded)) {
if (auto behavior = shouldDiagnoseEmbeddedLimitations(
dc, attr->getLocation(),
/*wasAlwaysEmbeddedError=*/true)) {
if (ownershipKind == ReferenceOwnership::Weak ||
ownershipKind == ReferenceOwnership::Unowned) {
Diags.diagnose(attr->getLocation(), diag::weak_unowned_in_embedded_swift,
ownershipKind);
attr->setInvalid();
ownershipKind)
.limitBehavior(*behavior);
}
}

Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "TypeCheckAvailability.h"
#include "TypeCheckConcurrency.h"
#include "TypeCheckDecl.h"
#include "TypeCheckEmbedded.h"
#include "TypeCheckMacros.h"
#include "TypeCheckObjC.h"
#include "TypeCheckType.h"
Expand Down Expand Up @@ -3535,6 +3536,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {

TypeChecker::checkDeclAttributes(FD);
TypeChecker::checkDistributedFunc(FD);
checkEmbeddedRestrictionsInSignature(FD);

if (!checkOverrides(FD)) {
// If a method has an 'override' keyword but does not
Expand Down Expand Up @@ -3920,6 +3922,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {

TypeChecker::checkDeclAttributes(CD);
TypeChecker::checkParameterList(CD->getParameters(), CD);
checkEmbeddedRestrictionsInSignature(CD);

if (CD->getAsyncLoc().isValid())
TypeChecker::checkConcurrencyAvailability(CD->getAsyncLoc(), CD);
Expand Down
Loading