@@ -98,6 +98,13 @@ struct CompilerBuildConfiguration: BuildConfiguration {
98
98
99
99
func isActiveTargetRuntime( name: String ) throws -> Bool {
100
100
var name = name
101
+
102
+ // Complain if the provided runtime isn't one of the known values.
103
+ switch name {
104
+ case " _Native " , " _ObjC " , " _multithreaded " : break
105
+ default : throw IfConfigError . unexpectedRuntimeCondition
106
+ }
107
+
101
108
return name. withBridgedString { nameRef in
102
109
ctx. langOptsIsActiveTargetRuntime ( nameRef)
103
110
}
@@ -150,6 +157,18 @@ struct CompilerBuildConfiguration: BuildConfiguration {
150
157
}
151
158
}
152
159
160
+ enum IfConfigError : Error , CustomStringConvertible {
161
+ case unexpectedRuntimeCondition
162
+
163
+ var description : String {
164
+ switch self {
165
+ case . unexpectedRuntimeCondition:
166
+ return " unexpected argument for the '_runtime' condition; expected '_Native' or '_ObjC' "
167
+ }
168
+ }
169
+ }
170
+
171
+
153
172
/// Extract the #if clause range information for the given source file.
154
173
@_cdecl ( " swift_ASTGen_configuredRegions " )
155
174
public func configuredRegions(
@@ -290,3 +309,53 @@ public func freeConfiguredRegions(
290
309
) {
291
310
UnsafeMutableBufferPointer ( start: regions, count: numRegions) . deallocate ( )
292
311
}
312
+
313
+ /// Evaluate the #if condition at ifClauseLocationPtr.
314
+ @_cdecl ( " swift_ASTGen_evaluatePoundIfCondition " )
315
+ public func evaluatePoundIfCondition(
316
+ astContext: BridgedASTContext ,
317
+ diagEnginePtr: UnsafeMutableRawPointer ,
318
+ sourceFileBuffer: BridgedStringRef ,
319
+ ifConditionText: BridgedStringRef ,
320
+ shouldEvaluate: Bool
321
+ ) -> Int {
322
+ // Retrieve the #if condition that we're evaluating here.
323
+ // FIXME: Use 'ExportedSourceFile' when C++ parser is replaced.
324
+ let textBuffer = UnsafeBufferPointer < UInt8 > ( start: ifConditionText. data, count: ifConditionText. count)
325
+ var parser = Parser ( textBuffer)
326
+ let conditionExpr = ExprSyntax . parse ( from: & parser)
327
+
328
+ let isActive : Bool
329
+ let syntaxErrorsAllowed : Bool
330
+ let diagnostics : [ Diagnostic ]
331
+ if shouldEvaluate {
332
+ // Evaluate the condition against the compiler's build configuration.
333
+ let configuration = CompilerBuildConfiguration (
334
+ ctx: astContext,
335
+ conditionLoc: BridgedSourceLoc ( raw: ifConditionText. data)
336
+ )
337
+
338
+ let state : IfConfigRegionState
339
+ ( state, syntaxErrorsAllowed, diagnostics) = IfConfigRegionState . evaluating ( conditionExpr, in: configuration)
340
+ isActive = ( state == . active)
341
+ } else {
342
+ // Don't evaluate the condition, because we know it's inactive. Determine
343
+ // whether syntax errors are permitted within this region according to the
344
+ // condition.
345
+ isActive = false
346
+ ( syntaxErrorsAllowed, diagnostics) = IfConfigClauseSyntax . syntaxErrorsAllowed ( conditionExpr)
347
+ }
348
+
349
+ // Render the diagnostics.
350
+ for diagnostic in diagnostics {
351
+ emitDiagnostic (
352
+ diagnosticEngine: BridgedDiagnosticEngine ( raw: diagEnginePtr) ,
353
+ sourceFileBuffer: UnsafeBufferPointer ( start: sourceFileBuffer. data, count: sourceFileBuffer. count) ,
354
+ sourceFileBufferOffset: ifConditionText. data! - sourceFileBuffer. data!,
355
+ diagnostic: diagnostic,
356
+ diagnosticSeverity: diagnostic. diagMessage. severity
357
+ )
358
+ }
359
+
360
+ return ( isActive ? 0x1 : 0 ) | ( syntaxErrorsAllowed ? 0x2 : 0 )
361
+ }
0 commit comments