diff --git a/lib/ASTGen/Sources/ASTGen/Availability.swift b/lib/ASTGen/Sources/ASTGen/Availability.swift index fd0b1be95e1fb..fd59b163f4691 100644 --- a/lib/ASTGen/Sources/ASTGen/Availability.swift +++ b/lib/ASTGen/Sources/ASTGen/Availability.swift @@ -21,6 +21,7 @@ import SwiftIfConfig extension ASTGenVisitor { /// Implementation detail for `generateAvailableAttr(attribute:)` and `generateSpecializeAttr(attribute:)`. func generateAvailableAttr( + attribute attrNode: AttributeSyntax, atLoc: BridgedSourceLoc, range: BridgedSourceRange, attrName: SyntaxText, @@ -43,14 +44,15 @@ extension ASTGenVisitor { isShorthand = false } if isShorthand { - return self.generateAvailableAttrShorthand(atLoc: atLoc, range: range, args: args, isSPI: isSPI) + return self.generateAvailableAttrShorthand(attribute: attrNode, atLoc: atLoc, range: range, args: args, isSPI: isSPI) } } // E.g. // @available(macOS, introduced: 10.12, deprecated: 11.2) // @available(*, unavailable, message: "out of service") - let attr = self.generateAvailableAttrExtended(atLoc: atLoc, range: range, args: args, isSPI: isSPI) + let attr = self.generateAvailableAttrExtended(attribute: attrNode, atLoc: atLoc, range: range, args: args, isSPI: isSPI) + if let attr { return [attr] } else { @@ -66,6 +68,7 @@ extension ASTGenVisitor { } func generateAvailableAttrShorthand( + attribute attrNode: AttributeSyntax, atLoc: BridgedSourceLoc, range: BridgedSourceRange, args: AvailabilityArgumentListSyntax, @@ -121,6 +124,7 @@ extension ASTGenVisitor { } func generateAvailableAttrExtended( + attribute attrNode: AttributeSyntax, atLoc: BridgedSourceLoc, range: BridgedSourceRange, args: AvailabilityArgumentListSyntax, @@ -165,16 +169,17 @@ extension ASTGenVisitor { var renamed: BridgedStringRef? = nil func generateVersion(arg: AvailabilityLabeledArgumentSyntax, into target: inout VersionAndRange?) { - guard let versionSytnax = arg.value.as(VersionTupleSyntax.self) else { - // TODO: Diagnose - fatalError("expected version after introduced, deprecated, or obsoleted") - } - guard let version = VersionTuple(parsing: versionSytnax.trimmedDescription) else { - // TODO: Diagnose - fatalError("invalid version string") - } if target != nil { - // TODO: Diagnose duplicated. + diagnose(.duplicatedLabeledArgumentInAttribute(attrNode, argument: arg, name: arg.label.text)) + return + } + guard + let versionSytnax = arg.value.as(VersionTupleSyntax.self), + let version = VersionTuple(parsing: versionSytnax.trimmedDescription) + else { + // FIXME: This is already diagnosed in ParserDiagnostics. + // diagnose(.expectedVersionNumberInAvailableAttr(arg)) + return } target = .init(version: version, range: self.generateSourceRange(versionSytnax)) @@ -195,7 +200,7 @@ extension ASTGenVisitor { case "noasync": attrKind = .noAsync default: - // TODO: Diagnose + diagnose(.unexpectedArgumentInAttribute(attrNode, arg)) continue } @@ -224,31 +229,35 @@ extension ASTGenVisitor { generateVersion(arg: arg, into: &obsoleted) case .message: guard let literal = arg.value.as(SimpleStringLiteralExprSyntax.self) else { - // TODO: Diagnose. - fatalError("invalid argument type for 'message:'") + diagnose(.expectedArgumentValueInAttribute(attrNode, label: "message", value: "string literal", at: arg.value)) + continue } guard let _message = self.generateStringLiteralTextIfNotInterpolated(expr: literal) else { - fatalError("invalid literal value") + diagnose(.stringInterpolationNotAllowedInAttribute(attrNode, at: literal)) + continue } guard message == nil else { - fatalError("duplicated 'message' argument") + diagnose(.duplicatedLabeledArgumentInAttribute(attrNode, argument: arg, name: "message")) + continue } message = _message case .renamed: guard let literal = arg.value.as(SimpleStringLiteralExprSyntax.self) else { - // TODO: Diagnose. - fatalError("invalid argument type for 'renamed:'") + diagnose(.expectedArgumentValueInAttribute(attrNode, label: "renamed", value: "string literal", at: arg.value)) + continue } guard let _renamed = self.generateStringLiteralTextIfNotInterpolated(expr: literal) else { - fatalError("invalid literal value") + diagnose(.stringInterpolationNotAllowedInAttribute(attrNode, at: literal)) + continue } guard renamed == nil else { - fatalError("duplicated 'message' argument") + diagnose(.duplicatedLabeledArgumentInAttribute(attrNode, argument: arg, name: "renamed")) + continue } renamed = _renamed case .invalid: - // TODO: Diagnose - fatalError("invalid labeled argument") + diagnose(.unexpectedArgumentInAttribute(attrNode, arg)) + continue } } } @@ -333,8 +342,8 @@ extension ASTGenVisitor { // Was not a macro, it should be a valid platform name. let platform = self.generateIdentifierAndSourceLoc(domainNode) guard let version = version else { - // TODO: Diagnostics. - fatalError("expected version") + diagnose(.expectedVersionNumberAfterPlatform(domainNode)) + return } // FIXME: Wasting ASTContext memory. // 'AvailabilitySpec' is 'ASTAllocated' but created spec is ephemeral in context of `@available` attributes. @@ -361,8 +370,9 @@ extension ASTGenVisitor { case .availabilityVersionRestriction(let platformVersion): handle(domainNode: platformVersion.platform, versionNode: platformVersion.version) default: - // TODO: Diagnostics. - fatalError("invalid argument kind for availability spec") + // FIXME: This is unreachable? ParserDiagnostics emits 'expected platform name'. + let token = parsed.argument.firstToken(viewMode: .sourceAccurate)! + diagnose(.unexpectedArgumentInAvailabilitySpecList(token)) } } diff --git a/lib/ASTGen/Sources/ASTGen/BuiltinPound.swift b/lib/ASTGen/Sources/ASTGen/BuiltinPound.swift index 8dbe88d23359b..9cb97fe0f6bdb 100644 --- a/lib/ASTGen/Sources/ASTGen/BuiltinPound.swift +++ b/lib/ASTGen/Sources/ASTGen/BuiltinPound.swift @@ -145,18 +145,27 @@ extension ASTGenVisitor { func generatePoundAssertStmt(freestandingMacroExpansion node: some FreestandingMacroExpansionSyntax) -> BridgedPoundAssertStmt? { assert(self.ctx.langOptsHasFeature(.StaticAssert)) var args = node.arguments[...] - let conditionExpr = self.generateConsumingAttrOption(args: &args, label: nil) { conditionNode in - self.generate(expr: conditionNode) - } - guard let conditionExpr else { - return nil + guard let arg = args.popFirst(), arg.label == nil else { + // TODO: Diagnose. + fatalError("expected condition expression in #assert") } + let conditionExpr = self.generate(expr: arg.expression) + let message: BridgedStringRef? - if !args.isEmpty { - message = self.generateConsumingSimpleStringLiteralAttrOption(args: &args) + if let arg = args.popFirst() { + guard arg.label == nil else { + // TODO: Diagnose. + fatalError("unexpected label") + } + message = self.generateStringLiteralTextIfNotInterpolated(expr: arg.expression) + // TODO: Diagnose if nil. } else { message = nil } + guard args.isEmpty else { + // TODO: Diagnose. + fatalError("unexpected label") + } return .createParsed( self.ctx, diff --git a/lib/ASTGen/Sources/ASTGen/CMakeLists.txt b/lib/ASTGen/Sources/ASTGen/CMakeLists.txt index 91271f87e84cb..e52e3697ce0cd 100644 --- a/lib/ASTGen/Sources/ASTGen/CMakeLists.txt +++ b/lib/ASTGen/Sources/ASTGen/CMakeLists.txt @@ -7,6 +7,7 @@ add_pure_swift_host_library(swiftASTGen STATIC CXX_INTEROP CompilerBuildConfiguration.swift DeclAttrs.swift Decls.swift + DiagnosticMessages.swift Diagnostics.swift DiagnosticsBridge.swift Exprs.swift diff --git a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift index 5728ffe0a02ac..09147614d08e2 100644 --- a/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/DeclAttrs.swift @@ -389,10 +389,12 @@ extension ASTGenVisitor { /// @abi(func fn()) /// ``` func generateABIAttr(attribute node: AttributeSyntax) -> BridgedABIAttr? { - guard - let arg = node.arguments?.as(ABIAttributeArgumentsSyntax.self) - else { - // TODO: diagnose + guard let arg = node.arguments else { + self.diagnose(.expectedArgumentsInAttribute(node)) + return nil + } + guard let arg = arg.as(ABIAttributeArgumentsSyntax.self) else { + self.diagnose(.unexpectedArgumentsTypeInAttribute(node, arguments: arg, expected: ABIAttributeArgumentsSyntax.self)) return nil } @@ -435,24 +437,25 @@ extension ASTGenVisitor { /// @_alignment(8) /// ``` func generateAlignmentAttr(attribute node: AttributeSyntax) -> BridgedAlignmentAttr? { - guard - let arg = node.arguments?.as(TokenSyntax.self) - else { - print("Not a token") - // TODO: Diagnose. - return nil - } - let value: Int? = Int(String(syntaxText: arg.rawText)) - guard let value, value > 0 else { - // TODO: Diagnose. - return nil + self.generateWithLabeledExprListArguments(attribute: node) { args in + let value: Int? = self.generateConsumingAttrOption(attribute: node, args: &args, label: nil) { expr in + guard let intExpr = expr.as(IntegerLiteralExprSyntax.self) else { + return nil + } + return intExpr.representedLiteralValue + } + guard let value, value > 0 else { + // TODO: Diagnose. + return nil + } + + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + range: self.generateAttrSourceRange(node), + value: value + ) } - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - range: self.generateAttrSourceRange(node), - value: value - ) } /// E.g.: @@ -512,6 +515,7 @@ extension ASTGenVisitor { } return self.generateAvailableAttr( + attribute: node, atLoc: self.generateSourceLoc(node.atSign), range: self.generateAttrSourceRange(node), attrName: attrName, @@ -556,25 +560,18 @@ extension ASTGenVisitor { /// @_cdecl("c_function_name") /// ``` func generateCDeclAttr(attribute node: AttributeSyntax) -> BridgedCDeclAttr? { - guard - // `@_cdecl` attribute has `.string(StringLiteralExprSyntax)` arguments. - let arg = node.arguments?.as(StringLiteralExprSyntax.self) - else { - // TODO: Diagnose. - return nil - } - guard - let name = self.generateStringLiteralTextIfNotInterpolated(expr: arg) - else { - // TODO: Diagnose. - return nil + self.generateWithLabeledExprListArguments(attribute: node) { args in + guard let name = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) else { + return nil + } + + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + range: self.generateAttrSourceRange(node), + name: name + ) } - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - range: self.generateAttrSourceRange(node), - name: name - ) } struct GeneratedDerivativeOriginalDecl { @@ -924,7 +921,7 @@ extension ASTGenVisitor { // FIXME: SwiftParser should parse the argument as LabeledExprListArguments return self.generateWithLabeledExprListArguments(attribute: node) { args in // Exposure kind. - let kind: BridgedExposureKind? = self.generateConsumingPlainIdentifierAttrOption(args: &args) { + let kind: BridgedExposureKind? = self.generateConsumingPlainIdentifierAttrOption(attribute: node, args: &args) { switch $0.rawText { case "Cxx": return .cxx @@ -939,13 +936,21 @@ extension ASTGenVisitor { } // Name. - let name = self.generateConsumingSimpleStringLiteralAttrOption(args: &args) ?? "" + let name: BridgedStringRef? + if !args.isEmpty { + name = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) ?? "" + guard name != nil else { + return nil + } + } else { + name = nil + } return .createParsed( self.ctx, atLoc: self.generateSourceLoc(node.atSign), range: self.generateAttrSourceRange(node), - name: name, + name: name ?? BridgedStringRef(), kind: kind ) } @@ -959,7 +964,7 @@ extension ASTGenVisitor { /// ``` func generateExternAttr(attribute node: AttributeSyntax) -> BridgedExternAttr? { return self.generateWithLabeledExprListArguments(attribute: node) { args in - let kind: BridgedExternKind? = self.generateConsumingPlainIdentifierAttrOption(args: &args) { + let kind: BridgedExternKind? = self.generateConsumingPlainIdentifierAttrOption(attribute: node, args: &args, example: "c") { switch $0.rawText { case "c": return .C @@ -979,12 +984,12 @@ extension ASTGenVisitor { switch kind { case .C: moduleName = nil - symbolName = args.isEmpty ? nil : self.generateConsumingSimpleStringLiteralAttrOption(args: &args) + symbolName = args.isEmpty ? nil : self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) case .wasm: - guard let _moduleName = self.generateConsumingSimpleStringLiteralAttrOption(args: &args, label: "module") else { + guard let _moduleName = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args, label: "module") else { return nil } - guard let _symbolName = self.generateConsumingSimpleStringLiteralAttrOption(args: &args, label: "name") else { + guard let _symbolName = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args, label: "name") else { return nil } @@ -1011,7 +1016,8 @@ extension ASTGenVisitor { /// ``` func generateSectionAttr(attribute node: AttributeSyntax) -> BridgedSectionAttr? { return self.generateWithLabeledExprListArguments(attribute: node) { args in - guard let name = self.generateConsumingSimpleStringLiteralAttrOption(args: &args) else { + guard let name = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) else { + // TODO: Diagnose if nil. return nil } @@ -1300,7 +1306,7 @@ extension ASTGenVisitor { return self.generateWithLabeledExprListArguments(attribute: node) { args in // Macro role. - let role = self.generateConsumingPlainIdentifierAttrOption(args: &args) { + let role = self.generateConsumingPlainIdentifierAttrOption(attribute: node, args: &args) { BridgedMacroRole(from: $0.rawText.bridged) } guard let role = role else { @@ -1604,27 +1610,21 @@ extension ASTGenVisitor { } func generatePrivateImportAttr(attribute node: AttributeSyntax) -> BridgedPrivateImportAttr? { - guard - // `@_private` has special argument list syntax - let args = node.arguments?.as(UnderscorePrivateAttributeArgumentsSyntax.self) - else { - // TODO: Diagnose - return nil - } + self.generateWithLabeledExprListArguments(attribute: node) { args in + let fileName = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args, label: "sourceFile") + guard let fileName else { + return nil + } - guard let fileName = self.generateStringLiteralTextIfNotInterpolated(expr: args.filename) else { - // TODO: Diagnose - return nil + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + attrNameLoc: self.generateSourceLoc(node.attributeName), + lParenLoc: self.generateSourceLoc(node.leftParen), + fileName: fileName, + rParenLoc: self.generateSourceLoc(node.rightParen) + ) } - - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - attrNameLoc: self.generateSourceLoc(node.attributeName), - lParenLoc: self.generateSourceLoc(node.leftParen), - fileName: fileName, - rParenLoc: self.generateSourceLoc(node.rightParen) - ) } /// E.g.: @@ -1706,7 +1706,7 @@ extension ASTGenVisitor { } func generateScalarLike() -> BridgedRawLayoutAttr? { - let tyR = self.generateConsumingAttrOption(args: &args, label: "like") { + let tyR = self.generateConsumingAttrOption(attribute: node, args: &args, label: "like") { self.generateTypeRepr(expr: $0) } guard let tyR else { @@ -1727,7 +1727,7 @@ extension ASTGenVisitor { } func generateArrayLike() -> BridgedRawLayoutAttr? { - let tyR = self.generateConsumingAttrOption(args: &args, label: "likeArrayOf") { + let tyR = self.generateConsumingAttrOption(attribute: node, args: &args, label: "likeArrayOf") { self.generateTypeRepr(expr: $0) } guard let tyR else { @@ -1735,7 +1735,7 @@ extension ASTGenVisitor { } // 'count:' can be integer literal or a generic parameter. - let count = self.generateConsumingAttrOption(args: &args, label: "count") { + let count = self.generateConsumingAttrOption(attribute: node, args: &args, label: "count") { self.generateValueOrType(expr: $0) } guard let count else { @@ -1757,7 +1757,7 @@ extension ASTGenVisitor { } func generateConsumingIntegerLiteralOption(label: SyntaxText) -> Int? { - self.generateConsumingAttrOption(args: &args, label: label) { + self.generateConsumingAttrOption(attribute: node, args: &args, label: label) { guard let integerExpr = $0.as(IntegerLiteralExprSyntax.self) else { // TODO: Diagnose fatalError("expected integer literal for '\(String(syntaxText: label)):' in @_rawLayout") @@ -1770,7 +1770,7 @@ extension ASTGenVisitor { } func generateConsumingMovesAsLike() -> Bool? { - self.generateConsumingPlainIdentifierAttrOption(args: &args) { + self.generateConsumingPlainIdentifierAttrOption(attribute: node, args: &args) { switch $0.rawText { case "movesAsLike": return true @@ -1819,24 +1819,18 @@ extension ASTGenVisitor { /// ``` /// @semantics("semantics_name") func generateSemanticsAttr(attribute node: AttributeSyntax) -> BridgedSemanticsAttr? { - guard - let arg = node.arguments?.as(StringLiteralExprSyntax.self) - else { - // TODO: Diagnose. - return nil - } - guard - let value = self.generateStringLiteralTextIfNotInterpolated(expr: arg) - else { - // TODO: Diagnose. - return nil + self.generateWithLabeledExprListArguments(attribute: node) { args in + guard let value = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) else { + return nil + } + + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + range: self.generateAttrSourceRange(node), + value: value + ) } - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - range: self.generateAttrSourceRange(node), - value: value - ) } /// E.g.: @@ -1908,6 +1902,7 @@ extension ASTGenVisitor { targetFunction = self.generateDeclNameRef(declReferenceExpr: arg.declName).name case .specializeAvailabilityArgument(let arg): availableAttrs = self.generateAvailableAttr( + attribute: node, atLoc: self.generateSourceLoc(arg.availabilityLabel), range: self.generateSourceRange( start: arg.availabilityArguments.firstToken(viewMode: .all)!, @@ -2159,15 +2154,15 @@ extension ASTGenVisitor { /// @_unavailableFromAsync(message: "use fooBar(_:) instead") /// ``` func generateUnavailableFromAsyncAttr(attribute node: AttributeSyntax) -> BridgedUnavailableFromAsyncAttr? { + var message: BridgedStringRef? = nil if node.arguments != nil { - // FIXME: Should be normal LabeledExprListSyntax arguments. - - guard let args = node.arguments?.as(UnavailableFromAsyncAttributeArgumentsSyntax.self) else { - // TODO: Diagnose. + message = self.generateWithLabeledExprListArguments(attribute: node) { args in + self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args, label: "message") + } + guard message != nil else { return nil } - message = self.generateStringLiteralTextIfNotInterpolated(expr: args.message) } return .createParsed( self.ctx, @@ -2208,7 +2203,7 @@ extension ASTGenVisitor { let initContext: BridgedCustomAttributeInitializer? if let args = node.arguments { guard let args = args.as(LabeledExprListSyntax.self) else { - // TODO: Diagnose? + self.diagnose(.unexpectedArgumentsTypeInAttribute(node, arguments: args, expected: LabeledExprListSyntax.self)) return nil } @@ -2255,9 +2250,8 @@ extension ASTGenVisitor { { return extractRawText(segments).bridged } - // TODO: Diagnose. - fatalError("expected string literal without interpolation") - // return nil + // Caller should diagnose. + return nil } /// Convenient method for processing an attribute with `LabeledExprListSyntax`. @@ -2279,22 +2273,39 @@ extension ASTGenVisitor { return nil } if let extra = args.popFirst() { - self.diagnose(.extraneousArgumentsInAttribute(node, extra)) + self.diagnose(.unexpectedArgumentInAttribute(node, extra)) } return result } func generateConsumingAttrOption( + attribute: AttributeSyntax, args: inout Slice, label: SyntaxText?, + example: String? = nil, _ valueGeneratorFunction: (ExprSyntax) -> R? ) -> R? { guard let arg = args.first else { + if let example { + self.diagnose(.expectedOptionForAttribute(attribute, suchAs: example)) + } else if let label { + self.diagnose(.expectedArgumentLabelInAttribute( + attribute, + label: String(syntaxText: label), + at: Syntax(attribute.rightParen) ?? Syntax(attribute) + )) + } else { + self.diagnose(.expectedArgumentsInAttribute(attribute)) + } // TODO: Diagnose. return nil } guard arg.label?.rawText == label else { - // TODO: Diagnose. + if arg.label != nil { + self.diagnose(.unexpectedArgumentLabelInAttribute(attribute, at: arg)) + } else { + self.diagnose(.expectedArgumentLabelInAttribute(attribute, label: String(syntaxText: label!), at: arg)) + } return nil } // Label matched. Consume the argument even if the value is not valid. @@ -2304,26 +2315,29 @@ extension ASTGenVisitor { } func generateConsumingPlainIdentifierAttrOption( + attribute: AttributeSyntax, args: inout Slice, + example: String? = nil, _ valueGeneratorFunction: (TokenSyntax) -> R? ) -> R? { - return generateConsumingAttrOption(args: &args, label: nil) { - guard - let declRefExpr = $0.as(DeclReferenceExprSyntax.self), - declRefExpr.argumentNames == nil - else { - // TODO: Diagnose. - return nil + return generateConsumingAttrOption(attribute: attribute, args: &args, label: nil, example: example) { + if let declRefExpr = $0.as(DeclReferenceExprSyntax.self), declRefExpr.argumentNames == nil { + return valueGeneratorFunction(declRefExpr.baseName) + } else if let discardExpr = $0.as(DiscardAssignmentExprSyntax.self) { + return valueGeneratorFunction(discardExpr.wildcard) } - return valueGeneratorFunction(declRefExpr.baseName) + self.diagnose(.expectedIdentifierOptionForAttribute(attribute, at: $0)) + return nil } } func generateConsumingSimpleStringLiteralAttrOption( + attribute: AttributeSyntax, args: inout Slice, label: SyntaxText? = nil ) -> BridgedStringRef? { - return self.generateConsumingAttrOption(args: &args, label: label) { + return self.generateConsumingAttrOption(attribute: attribute, args: &args, label: label) { + // TODO: Diagnose if 'nil' self.generateStringLiteralTextIfNotInterpolated(expr: $0) } } @@ -2340,7 +2354,7 @@ extension ASTGenVisitor { _ valueGeneratorFunction: (TokenSyntax) -> Result?, valueIfOmitted: Result? = nil ) -> Result? { - guard node.leftParen != nil, let arguments = node.arguments else { + guard node.arguments != nil else { if let valueIfOmitted { return valueIfOmitted } @@ -2348,13 +2362,9 @@ extension ASTGenVisitor { return nil } - if case .token(let tok) = arguments { - // Special case: was parsed as a token, not an an argument list - return valueGeneratorFunction(tok) - } - return self.generateWithLabeledExprListArguments(attribute: node) { args in self.generateConsumingPlainIdentifierAttrOption( + attribute: node, args: &args, valueGeneratorFunction ) diff --git a/lib/ASTGen/Sources/ASTGen/DiagnosticMessages.swift b/lib/ASTGen/Sources/ASTGen/DiagnosticMessages.swift new file mode 100644 index 0000000000000..458bc351592ec --- /dev/null +++ b/lib/ASTGen/Sources/ASTGen/DiagnosticMessages.swift @@ -0,0 +1,257 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2023-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 SwiftSyntax +import SwiftDiagnostics + +//===----------------------------------------------------------------------===// +// MARK: Decl diagnostics +//===----------------------------------------------------------------------===// + +extension ASTGenDiagnostic { + static func nonTrivialPatternForAccessor(_ pattern: some SyntaxProtocol) -> Self { + Self( + node: pattern, + message: "getter/setter can only be defined for a single variable" + ) + } + + static func unknownAccessorSpecifier(_ specifier: TokenSyntax) -> Self { + Self( + node: specifier, + message: "unknown accessor specifier '\(specifier.text)'" + ) + } +} + +//===----------------------------------------------------------------------===// +// MARK: Decl attribute diagnostics +//===----------------------------------------------------------------------===// + +extension ASTGenDiagnostic { + static func expectedArgumentsInAttribute(_ attribute: AttributeSyntax) -> Self { + Self( + node: attribute, + position: attribute.rightParen?.positionAfterSkippingLeadingTrivia ?? attribute.endPositionBeforeTrailingTrivia, + message: "expected arguments in '@\(attribute.attributeName.trimmedDescription)' attribute" + ) + } + + static func unexpectedArgumentInAttribute(_ attribute: AttributeSyntax, _ extra: some SyntaxProtocol) -> Self { + Self( + node: extra, + message: "unexpected arguments in '@\(attribute.attributeName.trimmedDescription)' attribute" + ) + } + + static func expectedOptionForAttribute(_ attribute: AttributeSyntax, suchAs example: String) -> Self { + Self( + node: attribute, + position: attribute.rightParen?.positionAfterSkippingLeadingTrivia ?? attribute.endPositionBeforeTrailingTrivia, + message: "expected option in '@\(attribute.attributeName)' attribute such as '\(example)'" + ) + } + + static func expectedIdentifierOptionForAttribute(_ attribute: AttributeSyntax, at arg: some SyntaxProtocol) -> Self { + Self( + node: arg, + message: "expected an identifier in '@\(attribute.attributeName)' attribute" + ) + } + + static func expectedArgumentLabelInAttribute(_ attribute: AttributeSyntax, label: String, at arg: some SyntaxProtocol) -> Self { + Self( + node: arg, + message: "expected '\(label)' argument in '@\(attribute.attributeName)' attribute" + ) + } + + static func expectedArgumentValueInAttribute(_ attribute: AttributeSyntax, label: String, value: String, at arg: some SyntaxProtocol) -> Self { + Self( + node: arg, + message: "expected \(value) for '\(label)' argument in '@\(attribute.attributeName)' attribute" + ) + } + + + static func unexpectedArgumentLabelInAttribute(_ attribute: AttributeSyntax, at arg: LabeledExprSyntax) -> Self { + Self( + node: arg, + message: "unexpected argument label '\(arg.label!):' in '@\(attribute.attributeName)' attribute" + ) + } + + static func unexpectedArgumentsTypeInAttribute(_ attribute: AttributeSyntax, arguments: AttributeSyntax.Arguments, expected: any SyntaxProtocol.Type) -> Self { + Self( + node: attribute.arguments!, + message: "(compiler bug) unexpected argument type for @\(attribute.attributeName): \(arguments.kind.syntaxNodeType), expected: \(expected)" + ) + } + + static func duplicatedLabeledArgumentInAttribute(_ attribute: AttributeSyntax, argument: some SyntaxProtocol, name: String) -> Self { + Self( + node: argument, + message: "duplicated argument '\(name)' in '@\(attribute.attributeName)' attribute" + ) + } + + static func stringInterpolationNotAllowedInAttribute(_ attribute: AttributeSyntax, at node: some ExprSyntaxProtocol) -> Self { + Self( + node: Syntax(node), + message: "string interpolation is not accepted in '@\(attribute.attributeName)' attribute" + ) + } +} + +//===----------------------------------------------------------------------===// +// MARK: Availability diagnostics +//===----------------------------------------------------------------------===// + +extension ASTGenDiagnostic { + static func expectedVersionNumberInAvailableAttr(_ node: AvailabilityLabeledArgumentSyntax) -> Self { + Self( + node: node.value, + message: "expected version number for '\(node.label.text):' argument" + ) + } + + static func expectedVersionNumberAfterPlatform(_ node: TokenSyntax) -> Self { + Self( + node: node, + position: node.endPositionBeforeTrailingTrivia, + message: "expected version number after '\(node.text)'" + ) + } + + static func unexpectedArgumentInAvailabilitySpecList(_ node: TokenSyntax) -> Self { + Self( + node: node, + message: "expected platform name" + ) + } +} + +//===----------------------------------------------------------------------===// +// MARK: Type diagnostics +//===----------------------------------------------------------------------===// + +// TODO + +//===----------------------------------------------------------------------===// +// MARK: Misc diagnostics +//===----------------------------------------------------------------------===// + +extension ASTGenDiagnostic { + static func illegalTopLevelStmt(_ stmt: some SyntaxProtocol) -> Self { + Self( + node: stmt, + message: "statements are not allowed at the top level" + ) + } + + static func illegalTopLevelExpr(_ expr: some SyntaxProtocol) -> Self { + Self( + node: expr, + message: "expressions are not allowed at the top level" + ) + } + + static func poundDiagnostic(_ node: StringLiteralExprSyntax, message: String, isError: Bool) -> Self { + Self( + node: node, + message: node.representedLiteralValue!, + severity: isError ? .error : .warning + ) + } +} + +extension ASTGenDiagnostic { + /// An error emitted when a token is of an unexpected kind. + static func unexpectedTokenKind(token: TokenSyntax) -> Self { + guard let parent = token.parent else { + preconditionFailure("Expected a child (not a root) token") + } + + return Self( + node: token, + message: """ + unexpected token kind for token: + \(token.debugDescription) + in parent: + \(parent.debugDescription(indentString: " ")) + """ + ) + } + + /// An error emitted when an optional child token is unexpectedly nil. + static func missingChildToken(parent: some SyntaxProtocol, kindOfTokenMissing: TokenKind) -> Self { + Self( + node: parent, + message: """ + missing child token of kind '\(kindOfTokenMissing)' in: + \(parent.debugDescription(indentString: " ")) + """ + ) + } + + /// An error emitted when a syntax collection entry is encountered that is + /// considered a duplicate of a previous entry per the language grammar. + static func duplicateSyntax(duplicate: some SyntaxProtocol, original: some SyntaxProtocol) -> Self { + precondition(duplicate.kind == original.kind, "Expected duplicate and original to be of same kind") + + guard let duplicateParent = duplicate.parent, let originalParent = original.parent, + duplicateParent == originalParent, duplicateParent.kind.isSyntaxCollection + else { + preconditionFailure("Expected a shared syntax collection parent") + } + + return Self( + node: duplicate, + message: """ + unexpected duplicate syntax in list: + \(duplicate.debugDescription(indentString: " ")) + previous syntax: + \(original.debugDescription(indentString: " ")) + """ + ) + } +} + +//===----------------------------------------------------------------------===// +// MARK: Convenient message construction methods +//===----------------------------------------------------------------------===// + +extension ASTGenDiagnostic { + fileprivate init(node: some SyntaxProtocol, position: AbsolutePosition? = nil, message: String, severity: DiagnosticSeverity = .error, function: String = #function) { + // Derive messageID from the function name. + let messageID = String(function.prefix(while: { $0 != "(" })) + self.init(id: messageID, node: Syntax(node), position: position, message: message, severity: severity) + } + + fileprivate func withNote(node: some SyntaxProtocol, message: String) -> Self { + let messageID = "\(self.diagnosticID)_node\(self.fixIts.count)" + var copy = self + copy.notes.append( + Note(node: Syntax(node), message: message, messageID: messageID) + ) + return copy + } + + fileprivate func withFixIt(message: String, changes: FixIt.Change...) -> Self { + let messageID = "\(self.diagnosticID)_fixit\(self.fixIts.count)" + var copy = self + copy.fixIts.append( + FixIt(message: message, messageID: messageID, changes: changes) + ) + return copy + } +} diff --git a/lib/ASTGen/Sources/ASTGen/Diagnostics.swift b/lib/ASTGen/Sources/ASTGen/Diagnostics.swift index 3d578d51d2456..6fd991226e800 100644 --- a/lib/ASTGen/Sources/ASTGen/Diagnostics.swift +++ b/lib/ASTGen/Sources/ASTGen/Diagnostics.swift @@ -2,7 +2,7 @@ // // This source file is part of the Swift.org open source project // -// Copyright (c) 2023 Apple Inc. and the Swift project authors +// Copyright (c) 2023-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 @@ -13,15 +13,20 @@ import SwiftDiagnostics import SwiftSyntax +//===----------------------------------------------------------------------===// +// MARK: Diagnostic infrastructures +//===----------------------------------------------------------------------===// + extension ASTGenVisitor { /// Emits the given ASTGen diagnostic via the C++ diagnostic engine. - func diagnose(_ message: ASTGenDiagnostic, highlights: [Syntax]? = nil, notes: [Note] = [], fixIts: [FixIt] = []) { + func diagnose(_ diag: ASTGenDiagnostic) { self.diagnose(Diagnostic( - node: message.node, - message: message, - highlights: highlights, - notes: notes, - fixIts: fixIts + node: diag.node, + position: diag.position, + message: diag, + highlights: diag.highlights, + notes: diag.notes.map { Note(node: $0.node, message: $0) }, + fixIts: diag.fixIts.map { FixIt(message: $0, changes: $0.changes) } )) } @@ -42,136 +47,61 @@ extension ASTGenVisitor { } struct ASTGenDiagnostic: DiagnosticMessage { - var node: Syntax - var message: String - var severity: DiagnosticSeverity - var messageID: String - - var diagnosticID: MessageID { - MessageID(domain: "ASTGen", id: messageID) - } - - init(node: some SyntaxProtocol, message: String, severity: DiagnosticSeverity = .error, messageID: String) { - self.node = Syntax(node) - self.message = message - self.severity = severity - self.messageID = messageID - } - - fileprivate init(node: some SyntaxProtocol, message: String, severity: DiagnosticSeverity = .error, function: String = #function) { - // Extract messageID from the function name. - let messageID = String(function.prefix(while: { $0 != "(" })) - self.init(node: node, message: message, severity: severity, messageID: messageID) - } -} - -extension ASTGenDiagnostic { - /// An error emitted when a token is of an unexpected kind. - static func unexpectedTokenKind(token: TokenSyntax) -> Self { - guard let parent = token.parent else { - preconditionFailure("Expected a child (not a root) token") + struct Note: NoteMessage { + var node: Syntax + var message: String + var noteID: MessageID + + init(node: Syntax, message: String, messageID: String) { + self.node = node + self.message = message + self.noteID = MessageID(domain: "ASTGen", id: messageID) } - - return Self( - node: token, - message: """ - unexpected token kind for token: - \(token.debugDescription) - in parent: - \(parent.debugDescription(indentString: " ")) - """ - ) } - /// An error emitted when an optional child token is unexpectedly nil. - static func missingChildToken(parent: some SyntaxProtocol, kindOfTokenMissing: TokenKind) -> Self { - Self( - node: parent, - message: """ - missing child token of kind '\(kindOfTokenMissing)' in: - \(parent.debugDescription(indentString: " ")) - """ - ) - } + struct FixIt: FixItMessage { + typealias Change = SwiftDiagnostics.FixIt.Change - /// An error emitted when a syntax collection entry is encountered that is - /// considered a duplicate of a previous entry per the language grammar. - static func duplicateSyntax(duplicate: some SyntaxProtocol, original: some SyntaxProtocol) -> Self { - precondition(duplicate.kind == original.kind, "Expected duplicate and original to be of same kind") + var message: String + var fixItID: MessageID + var changes: [Change] - guard let duplicateParent = duplicate.parent, let originalParent = original.parent, - duplicateParent == originalParent, duplicateParent.kind.isSyntaxCollection - else { - preconditionFailure("Expected a shared syntax collection parent") + init(message: String, messageID: String, changes: [Change]) { + self.fixItID = MessageID(domain: "ASTGen", id: messageID) + self.message = message + self.changes = changes } - - return Self( - node: duplicate, - message: """ - unexpected duplicate syntax in list: - \(duplicate.debugDescription(indentString: " ")) - previous syntax: - \(original.debugDescription(indentString: " ")) - """ - ) - } - - static func nonTrivialPatternForAccessor(_ pattern: some SyntaxProtocol) -> Self { - Self( - node: pattern, - message: "getter/setter can only be defined for a single variable" - ) } - static func unknownAccessorSpecifier(_ specifier: TokenSyntax) -> Self { - Self( - node: specifier, - message: "unknown accessor specifier '\(specifier.text)'" - ) - } -} + var node: Syntax + var position: AbsolutePosition? + var message: String + var severity: DiagnosticSeverity + var messageID: String + var highlights: [Syntax] = [] + var notes: [Note] = [] + var fixIts: [FixIt] = [] -/// Decl diagnostics -extension ASTGenDiagnostic { - static func illegalTopLevelStmt(_ stmt: some SyntaxProtocol) -> Self { - Self( - node: stmt, - message: "statements are not allowed at the top level" - ) + var diagnosticID: MessageID { + MessageID(domain: "ASTGen", id: messageID) } - static func illegalTopLevelExpr(_ expr: some SyntaxProtocol) -> Self { - Self( - node: expr, - message: "expressions are not allowed at the top level" - ) + init(id: String, node: Syntax, position: AbsolutePosition? = nil, message: String, severity: DiagnosticSeverity) { + self.node = node + self.position = position + self.message = message + self.severity = severity + self.messageID = id } } -/// DeclAttributes diagnostics -extension ASTGenDiagnostic { - static func expectedArgumentsInAttribute(_ attribute: AttributeSyntax) -> Self { - // FIXME: The diagnostic position should be at the and of the attribute name. - Self( - node: attribute, - message: "expected arguments for '\(attribute.attributeName.trimmedDescription)' attribute" - ) +// Convenient methods. +extension FixIt.Change { + static func replace(_ oldNode: some SyntaxProtocol, with newNode: some SyntaxProtocol) -> Self { + .replace(oldNode: Syntax(oldNode), newNode: Syntax(newNode)) } - static func extraneousArgumentsInAttribute(_ attribute: AttributeSyntax, _ extra: some SyntaxProtocol) -> Self { - Self( - node: extra, - message: "unexpected arguments in '\(attribute.attributeName.trimmedDescription)' attribute" - ) - } -} - -extension ASTGenDiagnostic { - static func poundDiagnostic(_ node: StringLiteralExprSyntax, message: String, isError: Bool) -> Self { - Self( - node: node, - message: node.representedLiteralValue!, - severity: isError ? .error : .warning - ) + static func replaceTokenText(_ token: TokenSyntax, with tokenKind: TokenKind) -> Self { + .replace(oldNode: Syntax(token), newNode: Syntax(token.detached.with(\.tokenKind, tokenKind))) } } diff --git a/lib/ASTGen/Sources/ASTGen/TypeAttrs.swift b/lib/ASTGen/Sources/ASTGen/TypeAttrs.swift index 8a4e355f11e35..3e76ad8e90ac9 100644 --- a/lib/ASTGen/Sources/ASTGen/TypeAttrs.swift +++ b/lib/ASTGen/Sources/ASTGen/TypeAttrs.swift @@ -142,38 +142,48 @@ extension ASTGenVisitor { nameLoc: self.generateSourceLoc(node.attributeName) ) } - + + /// E.g. + /// ``` + /// @convention(c) + /// @convention(c, cType: "size_t (*)(size_t)") + /// ``` func generateConventionTypeAttr(attribute node: AttributeSyntax) -> BridgedConventionTypeAttr? { - // FIXME: This doesn't need custom attribute arguments syntax. - // FIXME: Support 'witness_method' argument. - guard let args = node.arguments?.as(ConventionAttributeArgumentsSyntax.self) else { - // TODO: Diangose. - return nil - } - - let cTypeName: BridgedStringRef? - let cTypeNameLoc: BridgedSourceLoc? - if let ctypeString = args.cTypeString { - cTypeName = self.generateStringLiteralTextIfNotInterpolated(expr: ctypeString) - cTypeNameLoc = cTypeName != nil ? self.generateSourceLoc(ctypeString) : nil - } else { - cTypeName = nil - cTypeNameLoc = nil + self.generateWithLabeledExprListArguments(attribute: node) { args in + let nameAndLoc: (name: BridgedStringRef, loc: BridgedSourceLoc)? = self.generateConsumingPlainIdentifierAttrOption(attribute: node, args: &args, example: "c") { + ($0.rawText.bridged, self.generateSourceLoc($0)) + } + guard let nameAndLoc else { + return nil + } + + let cTypeNameLoc: BridgedSourceLoc? + let cTypeName: BridgedStringRef? + if !args.isEmpty { + cTypeNameLoc = self.generateSourceLoc(args.first?.expression) + cTypeName = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args, label: "cType") + guard cTypeName != nil else { + return nil + } + } else { + cTypeNameLoc = nil + cTypeName = nil + } + + let witnessMethodProtocol: BridgedDeclNameRef = BridgedDeclNameRef() + + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + nameLoc: self.generateSourceLoc(node.attributeName), + parensRange: self.generateAttrParensRange(attribute: node), + name: ctx.allocateCopy(string: nameAndLoc.name), + nameLoc: nameAndLoc.loc, + witnessMethodProtocol: witnessMethodProtocol, + clangType: cTypeName ?? BridgedStringRef(), + clangTypeLoc: cTypeNameLoc ?? BridgedSourceLoc() + ) } - - let witnessMethodProtocol: BridgedDeclNameRef = BridgedDeclNameRef() - - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - nameLoc: self.generateSourceLoc(node.attributeName), - parensRange: self.generateAttrParensRange(attribute: node), - name: ctx.allocateCopy(string: args.conventionLabel.rawText.bridged), - nameLoc: self.generateSourceLoc(args.conventionLabel), - witnessMethodProtocol: witnessMethodProtocol, - clangType: cTypeName ?? BridgedStringRef(), - clangTypeLoc: cTypeNameLoc ?? BridgedSourceLoc() - ) } func generateDifferentiableTypeAttr(attribute node: AttributeSyntax) -> BridgedDifferentiableTypeAttr? { @@ -284,35 +294,43 @@ extension ASTGenVisitor { ) } + /// E.g. + /// ``` + /// @_opaqueReturnTypeOf("$sMangledName", 4) + /// ``` func generateOpaqueReturnTypeOfTypeAttr(attribute node: AttributeSyntax) -> BridgedOpaqueReturnTypeOfTypeAttr? { - // FIXME: This doesn't need custom attribute arguments syntax. - guard let args = node.arguments?.as(OpaqueReturnTypeOfAttributeArgumentsSyntax.self) else { - // TODO: Diagnose - fatalError("expected arguments for @_opaqueReturnTypeOfType type attribute") - } + self.generateWithLabeledExprListArguments(attribute: node) { args in + let mangledLoc = self.generateSourceLoc(args.first?.expression) + let mangledName = self.generateConsumingSimpleStringLiteralAttrOption(attribute: node, args: &args) + guard let mangledName else { + return nil + } - let mangledLoc = self.generateSourceLoc(args.mangledName) - guard let mangled = self.generateStringLiteralTextIfNotInterpolated(expr: args.mangledName) else { - // TODO: Diagnose - fatalError("expected string literal for @_opaqueReturnTypeOfType type attribute") - } - - let indexLoc = self.generateSourceLoc(args.ordinal) - let index = Int(args.ordinal.text, radix: 10) - guard let index else { - // TODO: Diagnose - fatalError("expected integer literal for @_opaqueReturnTypeOfType type attribute") + let indexLoc = self.generateSourceLoc(args.first?.expression) + let index: Int? = self.generateConsumingAttrOption(attribute: node, args: &args, label: nil) { expr in + guard let intExpr = expr.as(IntegerLiteralExprSyntax.self) else { + // TODO: Diagnostics. + fatalError("expected integer literal") + // return nil + } + return intExpr.representedLiteralValue + } + guard let index else { + return nil + } + + return .createParsed( + self.ctx, + atLoc: self.generateSourceLoc(node.atSign), + nameLoc: self.generateSourceLoc(node.attributeName), + parensRange: self.generateAttrParensRange(attribute: node), + mangled: mangledName, + mangledLoc: mangledLoc, + index: index, + indexLoc: indexLoc + ) } - return .createParsed( - self.ctx, - atLoc: self.generateSourceLoc(node.atSign), - nameLoc: self.generateSourceLoc(node.attributeName), - parensRange: self.generateAttrParensRange(attribute: node), - mangled: mangled, - mangledLoc: mangledLoc, - index: index, indexLoc: indexLoc - ) } func generateAttrParensRange(attribute node: AttributeSyntax) -> BridgedSourceRange { diff --git a/lib/ASTGen/Sources/ASTGen/Types.swift b/lib/ASTGen/Sources/ASTGen/Types.swift index a0cd884131f0b..ddbe4ee8b2ecb 100644 --- a/lib/ASTGen/Sources/ASTGen/Types.swift +++ b/lib/ASTGen/Sources/ASTGen/Types.swift @@ -314,16 +314,12 @@ extension ASTGenVisitor { } func generate(classRestrictionType node: ClassRestrictionTypeSyntax) -> BridgedUnqualifiedIdentTypeRepr { - // TODO: diagnostics. - // warning: using 'class' keyword to define a class-constrained protocol is deprecated; use 'AnyObject' instead return .createParsed( self.ctx, loc: self.generateSourceLoc(node.classKeyword), name: self.ctx.getIdentifier("AnyObject") ) } - - // NOTE: When implementing new `generate(type:)`, please update `isTypeMigrated(_:)`. } // MARK: - SpecifierTypeRepr/AttributedTypeRepr diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index a65755018c10e..6f30fa13fbafd 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -56,6 +56,9 @@ LangOptions::LangOptions() { enableFeature(Feature::BorrowingSwitch); enableFeature(Feature::MoveOnlyPartialConsumption); + // ASTGen. + enableFeature(Feature::ParserASTGen); + // Enable any playground options that are enabled by default. #define PLAYGROUND_OPTION(OptionName, Description, DefaultOn, HighPerfOn) \ if (DefaultOn) \ diff --git a/test/ASTGen/diagnostics.swift b/test/ASTGen/diagnostics.swift index 58f9fafe5cbfe..e560f506b40a6 100644 --- a/test/ASTGen/diagnostics.swift +++ b/test/ASTGen/diagnostics.swift @@ -23,12 +23,6 @@ _ = [(Int) -> async throws Int]() // expected-error@-1{{'async throws' must precede '->'}} // expected-note@-2{{move 'async throws' in front of '->'}}{{15-21=}} {{21-28=}} {{12-12=async }} {{12-12=throws }} -@freestanding // expected-error {{expected arguments for 'freestanding' attribute}} -func dummy() {} - -@_silgen_name("whatever", extra) // expected-error@:27 {{unexpected arguments in '_silgen_name' attribute}} -func _whatever() - struct S { subscript(x: Int) { _ = 1 } // expected-error@:23 {{expected '->' and return type in subscript}} // expected-note@-1:23 {{insert '->' and return type}} diff --git a/test/ASTGen/diagnostics_attrs.swift b/test/ASTGen/diagnostics_attrs.swift new file mode 100644 index 0000000000000..df90bf0252518 --- /dev/null +++ b/test/ASTGen/diagnostics_attrs.swift @@ -0,0 +1,32 @@ +// RUN: %target-typecheck-verify-swift \ +// RUN: -enable-experimental-feature ParserASTGen + +// REQUIRES: swift_swift_parser +// REQUIRES: swift_feature_ParserASTGen + +@freestanding // expected-error {{expected arguments in '@freestanding' attribute}} +func dummy() {} + +@_extern(lang: c) // expected-error@:10 {{unexpected argument label 'lang:' in '@_extern' attribute}} +func c_func() {} + +@_extern() // expected-error@:10 {{expected option in '@_extern' attribute such as 'c'}} +func unknown_func() {} + +@_extern("C") // expected-error@:10 {{expected an identifier in '@_extern' attribute}} +func unknown_func_str() {} + +@implementation() // expected-error@:17 {{expected arguments in '@implementation' attribute}} +func implementaiton_func() {} + +@_silgen_name("whatever", extra) // expected-error@:27 {{unexpected arguments in '@_silgen_name' attribute}} +func _whatever() + +@available(*, unavailable, message: "foo", message: "bar") // expected-error@:44 {{duplicated argument 'message' in '@available' attribute}} +func unavailable_func() {} + +@available(swift) // expected-error@:17 {{expected version number after 'swift'}} +func unavailable_swift() {} + +@available(swift 99, message: "foo") // expected-error@:22 {{expected platform name}} +func unavailable_swift99() {} diff --git a/test/ASTGen/types.swift b/test/ASTGen/types.swift index 1ee9cd362392d..00bf9c45dc169 100644 --- a/test/ASTGen/types.swift +++ b/test/ASTGen/types.swift @@ -12,6 +12,7 @@ // RUN: %diff -u %t/astgen.ast %t/cpp-parser.ast // RUN: %target-typecheck-verify-swift -enable-experimental-feature ParserASTGen \ +// RUN: -swift-version 5 \ // RUN: -enable-experimental-feature NamedOpaqueTypes \ // RUN: -enable-experimental-feature InlineArrayTypeSugar @@ -67,8 +68,8 @@ struct FileDescriptor: ~Copyable { var fd = 1 } -// FIXME: warning for 'class' protocol ClassOnly: class {} +// expected-warning@-1 {{using 'class' keyword to define a class-constrained protocol is deprecated}} {{21-26=AnyObject}} actor SomeActor { } @globalActor