| 1 | module builder |
| 2 | |
| 3 | import os |
| 4 | import v2.ast |
| 5 | import v2.pref |
| 6 | |
| 7 | fn collect_cflags_for_test_source(source string, mut prefs pref.Preferences) string { |
| 8 | tmp_dir := os.join_path(os.vtmp_dir(), 'v2_builder_flag_target_${os.getpid()}') |
| 9 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 10 | defer { |
| 11 | os.rmdir_all(tmp_dir) or {} |
| 12 | } |
| 13 | source_path := os.join_path(tmp_dir, 'main.v') |
| 14 | os.write_file(source_path, source) or { panic(err) } |
| 15 | prefs.skip_builtin = true |
| 16 | mut b := new_builder(&prefs) |
| 17 | b.files = [ |
| 18 | ast.File{ |
| 19 | name: source_path |
| 20 | }, |
| 21 | ] |
| 22 | return b.collect_cflags_from_sources() |
| 23 | } |
| 24 | |
| 25 | fn collect_cflags_for_flat_only_test_source(source string, mut prefs pref.Preferences) string { |
| 26 | tmp_dir := os.join_path(os.vtmp_dir(), 'v2_builder_flag_target_flat_${os.getpid()}') |
| 27 | os.mkdir_all(tmp_dir) or { panic(err) } |
| 28 | defer { |
| 29 | os.rmdir_all(tmp_dir) or {} |
| 30 | } |
| 31 | source_path := os.join_path(tmp_dir, 'main.v') |
| 32 | os.write_file(source_path, source) or { panic(err) } |
| 33 | prefs.skip_builtin = true |
| 34 | mut b := new_builder(&prefs) |
| 35 | b.flat = ast.flatten_files([ |
| 36 | ast.File{ |
| 37 | name: source_path |
| 38 | mod: 'main' |
| 39 | }, |
| 40 | ]) |
| 41 | b.files = []ast.File{} |
| 42 | return b.collect_cflags_from_sources() |
| 43 | } |
| 44 | |
| 45 | fn freestanding_test_call_name(name string, user_defines []string) string { |
| 46 | return freestanding_test_call_name_with_hooks(name, user_defines, []) |
| 47 | } |
| 48 | |
| 49 | fn freestanding_test_call_name_with_hooks(name string, user_defines []string, hooks []string) string { |
| 50 | return freestanding_restricted_call_in_expr(ast.Expr(ast.CallExpr{ |
| 51 | lhs: ast.Expr(ast.Ident{ |
| 52 | name: name |
| 53 | }) |
| 54 | }), FreestandingScanContext{ |
| 55 | user_defines: user_defines |
| 56 | target_os: 'linux' |
| 57 | freestanding_hooks: hooks |
| 58 | }) |
| 59 | } |
| 60 | |
| 61 | fn test_flag_directives_match_cross_and_freestanding_preferences() { |
| 62 | mut cross_prefs := pref.new_preferences() |
| 63 | cross_prefs.target_os = 'cross' |
| 64 | cross_prefs.user_defines = ['cross'] |
| 65 | cross_flag := parse_flag_directive_line_with_pref('#flag cross -DCROSS_DIRECT', |
| 66 | '/tmp/source.v', &cross_prefs) or { '' } |
| 67 | linux_flag := parse_flag_directive_line_with_pref('#flag linux -DLINUX_DIRECT', |
| 68 | '/tmp/source.v', &cross_prefs) or { '' } |
| 69 | assert cross_flag == '-DCROSS_DIRECT' |
| 70 | assert linux_flag == '' |
| 71 | |
| 72 | mut free_prefs := pref.new_preferences() |
| 73 | free_prefs.target_os = 'linux' |
| 74 | free_prefs.user_defines = ['freestanding'] |
| 75 | free_flag := parse_flag_directive_line_with_pref('#flag freestanding -DFREE_DIRECT', |
| 76 | '/tmp/source.v', &free_prefs) or { '' } |
| 77 | linux_in_free_flag := parse_flag_directive_line_with_pref('#flag linux -DLINUX_DIRECT', |
| 78 | '/tmp/source.v', &free_prefs) or { '' } |
| 79 | assert free_flag == '-DFREE_DIRECT' |
| 80 | assert linux_in_free_flag == '-DLINUX_DIRECT' |
| 81 | } |
| 82 | |
| 83 | fn test_comptime_flag_blocks_match_cross_and_freestanding_preferences() { |
| 84 | mut cross_prefs := pref.new_preferences() |
| 85 | cross_prefs.target_os = 'cross' |
| 86 | cross_prefs.user_defines = ['cross'] |
| 87 | assert comptime_cond_matches_with_pref('cross', &cross_prefs) |
| 88 | assert !comptime_cond_matches_with_pref('linux', &cross_prefs) |
| 89 | assert !comptime_cond_matches_with_pref('linux ?', &cross_prefs) |
| 90 | assert comptime_cond_matches_with_pref('cross && !linux', &cross_prefs) |
| 91 | |
| 92 | mut optional_linux_prefs := pref.new_preferences() |
| 93 | optional_linux_prefs.target_os = 'cross' |
| 94 | optional_linux_prefs.user_defines = ['cross', 'linux'] |
| 95 | optional_linux_prefs.explicit_user_defines = ['linux'] |
| 96 | assert comptime_cond_matches_with_pref('linux ?', &optional_linux_prefs) |
| 97 | |
| 98 | mut linux_prefs := pref.new_preferences() |
| 99 | linux_prefs.target_os = 'linux' |
| 100 | assert comptime_cond_matches_with_pref('linux', &linux_prefs) |
| 101 | assert !comptime_cond_matches_with_pref('linux ?', &linux_prefs) |
| 102 | assert !comptime_cond_matches_with_pref('linux ? || windows', &linux_prefs) |
| 103 | linux_prefs.user_defines = ['linux'] |
| 104 | linux_prefs.explicit_user_defines = ['linux'] |
| 105 | assert comptime_cond_matches_with_pref('linux ?', &linux_prefs) |
| 106 | assert comptime_cond_matches_with_pref('linux ? || windows', &linux_prefs) |
| 107 | |
| 108 | mut termux_prefs := pref.new_preferences() |
| 109 | termux_prefs.target_os = 'termux' |
| 110 | assert comptime_cond_matches_with_pref('termux', &termux_prefs) |
| 111 | assert comptime_cond_matches_with_pref('linux || termux', &termux_prefs) |
| 112 | assert !comptime_cond_matches_with_pref('android', &termux_prefs) |
| 113 | assert !comptime_cond_matches_with_pref('android && !termux', &termux_prefs) |
| 114 | |
| 115 | mut free_prefs := pref.new_preferences() |
| 116 | free_prefs.target_os = 'linux' |
| 117 | free_prefs.user_defines = ['freestanding'] |
| 118 | assert comptime_cond_matches_with_pref('freestanding', &free_prefs) |
| 119 | assert !comptime_cond_matches_with_pref('freestanding ?', &free_prefs) |
| 120 | assert comptime_cond_matches_with_pref('linux', &free_prefs) |
| 121 | assert comptime_cond_matches_with_pref('freestanding && linux', &free_prefs) |
| 122 | } |
| 123 | |
| 124 | fn test_comptime_pkgconfig_condition_matches_available_package() { |
| 125 | mut prefs := pref.new_preferences() |
| 126 | prefs.target_os = os.user_os() |
| 127 | assert !comptime_cond_matches_with_pref(r"$pkgconfig('__v2_definitely_missing_pkgconfig_test_package__')", |
| 128 | &prefs) |
| 129 | if pref.comptime_pkgconfig_value('sqlite3') { |
| 130 | assert comptime_cond_matches_with_pref(r"$pkgconfig('sqlite3')", &prefs) |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | fn test_pkgconfig_directive_collects_flags_for_active_native_branch() { |
| 135 | mut prefs := pref.new_preferences() |
| 136 | prefs.target_os = os.user_os() |
| 137 | if pref.comptime_pkgconfig_value('sqlite3') { |
| 138 | flag := parse_flag_directive_line_with_pref('#pkgconfig sqlite3', '/tmp/source.v', &prefs) or { |
| 139 | '' |
| 140 | } |
| 141 | assert flag.contains('sqlite3') |
| 142 | } |
| 143 | |
| 144 | mut cross_prefs := pref.new_preferences() |
| 145 | cross_prefs.target_os = 'cross' |
| 146 | cross_prefs.output_cross_c = true |
| 147 | flag := parse_flag_directive_line_with_pref('#pkgconfig sqlite3', '/tmp/source.v', &cross_prefs) or { |
| 148 | '' |
| 149 | } |
| 150 | assert flag == '' |
| 151 | } |
| 152 | |
| 153 | fn test_comptime_optional_target_mode_flags_require_explicit_define() { |
| 154 | mut cross_prefs := pref.new_preferences() |
| 155 | cross_prefs.target_os = 'cross' |
| 156 | cross_prefs.user_defines = ['cross'] |
| 157 | assert comptime_cond_matches_with_pref('cross', &cross_prefs) |
| 158 | assert !comptime_cond_matches_with_pref('cross ?', &cross_prefs) |
| 159 | cross_prefs.explicit_user_defines = ['cross'] |
| 160 | assert comptime_cond_matches_with_pref('cross ?', &cross_prefs) |
| 161 | |
| 162 | mut free_prefs := pref.new_preferences() |
| 163 | free_prefs.target_os = 'linux' |
| 164 | free_prefs.user_defines = ['freestanding'] |
| 165 | assert comptime_cond_matches_with_pref('freestanding', &free_prefs) |
| 166 | assert !comptime_cond_matches_with_pref('freestanding ?', &free_prefs) |
| 167 | free_prefs.explicit_user_defines = ['freestanding'] |
| 168 | assert comptime_cond_matches_with_pref('freestanding ?', &free_prefs) |
| 169 | |
| 170 | mut none_prefs := pref.new_preferences() |
| 171 | none_prefs.target_os = 'none' |
| 172 | none_prefs.user_defines = ['freestanding'] |
| 173 | assert comptime_cond_matches_with_pref('none', &none_prefs) |
| 174 | assert !comptime_cond_matches_with_pref('none ?', &none_prefs) |
| 175 | none_prefs.explicit_user_defines = ['none'] |
| 176 | assert comptime_cond_matches_with_pref('none ?', &none_prefs) |
| 177 | } |
| 178 | |
| 179 | fn test_comptime_flag_blocks_use_or_and_not_precedence() { |
| 180 | mut linux_prefs := pref.new_preferences() |
| 181 | linux_prefs.target_os = 'linux' |
| 182 | assert comptime_cond_matches_with_pref('!windows && linux', &linux_prefs) |
| 183 | assert comptime_cond_matches_with_pref('linux || windows && macos', &linux_prefs) |
| 184 | |
| 185 | mut macos_prefs := pref.new_preferences() |
| 186 | macos_prefs.target_os = 'macos' |
| 187 | assert !comptime_cond_matches_with_pref('!windows && linux', &macos_prefs) |
| 188 | assert !comptime_cond_matches_with_pref('linux || windows && macos', &macos_prefs) |
| 189 | |
| 190 | mut windows_prefs := pref.new_preferences() |
| 191 | windows_prefs.target_os = 'windows' |
| 192 | assert !comptime_cond_matches_with_pref('!windows && linux', &windows_prefs) |
| 193 | assert !comptime_cond_matches_with_pref('linux || windows && macos', &windows_prefs) |
| 194 | } |
| 195 | |
| 196 | fn test_parser_level_comptime_flags_match_cross_and_accepted_targets() { |
| 197 | assert ast_comptime_flag_matches('cross', [], 'cross') |
| 198 | assert ast_comptime_flag_matches('solaris', [], 'solaris') |
| 199 | assert ast_comptime_flag_matches('qnx', [], 'qnx') |
| 200 | assert ast_comptime_flag_matches('serenity', [], 'serenity') |
| 201 | assert ast_comptime_flag_matches('plan9', [], 'plan9') |
| 202 | assert ast_comptime_flag_matches('vinix', [], 'vinix') |
| 203 | assert ast_comptime_flag_matches('ios', [], 'ios') |
| 204 | assert ast_comptime_flag_matches('termux', [], 'termux') |
| 205 | assert ast_comptime_flag_matches('none', [], 'none') |
| 206 | assert !ast_comptime_flag_matches('linux', [], 'cross') |
| 207 | assert !ast_comptime_flag_matches('linux', ['linux'], 'windows') |
| 208 | assert !ast_comptime_flag_matches('none', ['none'], 'linux') |
| 209 | } |
| 210 | |
| 211 | fn test_flag_directives_match_all_accepted_target_os_names() { |
| 212 | for target in ['android', 'termux', 'ios', 'solaris', 'qnx', 'serenity', 'plan9', 'vinix'] { |
| 213 | flag := parse_flag_directive_line('#flag ${target} -D${target.to_upper()}', |
| 214 | '/tmp/source.v', target) or { '' } |
| 215 | assert flag == '-D${target.to_upper()}' |
| 216 | assert comptime_cond_matches(target, target) |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | fn test_collect_cflags_from_sources_matches_cross_and_freestanding_blocks() { |
| 221 | cross_source := 'module main |
| 222 | |
| 223 | $if cross { |
| 224 | #flag -DCROSS_BLOCK |
| 225 | } |
| 226 | $if cross ? { |
| 227 | #flag -DOPTIONAL_CROSS_BLOCK |
| 228 | } |
| 229 | $if linux { |
| 230 | #flag -DLINUX_BLOCK |
| 231 | } |
| 232 | $if linux ? { |
| 233 | #flag -DOPTIONAL_LINUX_BLOCK |
| 234 | } |
| 235 | $if macos { |
| 236 | #flag -DMACOS_BLOCK |
| 237 | } |
| 238 | $if windows { |
| 239 | #flag -DWINDOWS_BLOCK |
| 240 | } |
| 241 | #flag cross -DCROSS_DIRECT |
| 242 | #flag linux -DLINUX_DIRECT |
| 243 | #flag macos -DMACOS_DIRECT |
| 244 | #flag windows -DWINDOWS_DIRECT |
| 245 | ' |
| 246 | mut cross_prefs := pref.new_preferences() |
| 247 | cross_prefs.target_os = 'cross' |
| 248 | cross_prefs.user_defines = ['cross'] |
| 249 | cross_flags := collect_cflags_for_test_source(cross_source, mut cross_prefs) |
| 250 | assert cross_flags.contains('-DCROSS_BLOCK') |
| 251 | assert cross_flags.contains('-DCROSS_DIRECT') |
| 252 | assert !cross_flags.contains('-DOPTIONAL_CROSS_BLOCK') |
| 253 | assert !cross_flags.contains('-DOPTIONAL_LINUX_BLOCK') |
| 254 | host_os := normalize_target_os_name(os.user_os()) |
| 255 | if host_os in ['linux', 'macos', 'windows'] { |
| 256 | assert cross_flags.contains(match host_os { |
| 257 | 'macos' { '-DMACOS_BLOCK' } |
| 258 | 'windows' { '-DWINDOWS_BLOCK' } |
| 259 | else { '-DLINUX_BLOCK' } |
| 260 | }) |
| 261 | assert cross_flags.contains(match host_os { |
| 262 | 'macos' { '-DMACOS_DIRECT' } |
| 263 | 'windows' { '-DWINDOWS_DIRECT' } |
| 264 | else { '-DLINUX_DIRECT' } |
| 265 | }) |
| 266 | } |
| 267 | if host_os != 'linux' { |
| 268 | assert !cross_flags.contains('-DLINUX_BLOCK') |
| 269 | assert !cross_flags.contains('-DLINUX_DIRECT') |
| 270 | } |
| 271 | if host_os != 'macos' { |
| 272 | assert !cross_flags.contains('-DMACOS_BLOCK') |
| 273 | assert !cross_flags.contains('-DMACOS_DIRECT') |
| 274 | } |
| 275 | if host_os != 'windows' { |
| 276 | assert !cross_flags.contains('-DWINDOWS_BLOCK') |
| 277 | assert !cross_flags.contains('-DWINDOWS_DIRECT') |
| 278 | } |
| 279 | mut cross_with_optional_linux_prefs := pref.new_preferences() |
| 280 | cross_with_optional_linux_prefs.target_os = 'cross' |
| 281 | cross_with_optional_linux_prefs.user_defines = ['cross', 'linux'] |
| 282 | cross_with_optional_linux_prefs.explicit_user_defines = ['linux'] |
| 283 | cross_with_optional_linux_flags := collect_cflags_for_test_source(cross_source, mut |
| 284 | cross_with_optional_linux_prefs) |
| 285 | assert cross_with_optional_linux_flags.contains('-DOPTIONAL_LINUX_BLOCK') |
| 286 | assert !cross_with_optional_linux_flags.contains('-DOPTIONAL_CROSS_BLOCK') |
| 287 | |
| 288 | mut cross_explicit_prefs := pref.new_preferences() |
| 289 | cross_explicit_prefs.target_os = 'cross' |
| 290 | cross_explicit_prefs.user_defines = ['cross'] |
| 291 | cross_explicit_prefs.explicit_user_defines = ['cross'] |
| 292 | cross_explicit_flags := collect_cflags_for_test_source(cross_source, mut cross_explicit_prefs) |
| 293 | assert cross_explicit_flags.contains('-DOPTIONAL_CROSS_BLOCK') |
| 294 | |
| 295 | free_source := 'module main |
| 296 | |
| 297 | $if freestanding { |
| 298 | #flag -DFREE_BLOCK |
| 299 | } |
| 300 | $if freestanding ? { |
| 301 | #flag -DOPTIONAL_FREE_BLOCK |
| 302 | } |
| 303 | $if linux { |
| 304 | #flag -DLINUX_BLOCK |
| 305 | } |
| 306 | #flag freestanding -DFREE_DIRECT |
| 307 | #flag linux -DLINUX_DIRECT |
| 308 | ' |
| 309 | mut free_prefs := pref.new_preferences() |
| 310 | free_prefs.target_os = 'linux' |
| 311 | free_prefs.user_defines = ['freestanding'] |
| 312 | free_flags := collect_cflags_for_test_source(free_source, mut free_prefs) |
| 313 | assert free_flags.contains('-DFREE_BLOCK') |
| 314 | assert !free_flags.contains('-DOPTIONAL_FREE_BLOCK') |
| 315 | assert free_flags.contains('-DFREE_DIRECT') |
| 316 | assert free_flags.contains('-DLINUX_BLOCK') |
| 317 | assert free_flags.contains('-DLINUX_DIRECT') |
| 318 | |
| 319 | mut free_explicit_prefs := pref.new_preferences() |
| 320 | free_explicit_prefs.target_os = 'linux' |
| 321 | free_explicit_prefs.user_defines = ['freestanding'] |
| 322 | free_explicit_prefs.explicit_user_defines = ['freestanding'] |
| 323 | free_explicit_flags := collect_cflags_for_test_source(free_source, mut free_explicit_prefs) |
| 324 | assert free_explicit_flags.contains('-DOPTIONAL_FREE_BLOCK') |
| 325 | } |
| 326 | |
| 327 | fn test_collect_cflags_from_sources_reads_flat_file_names() { |
| 328 | source := 'module main |
| 329 | |
| 330 | #flag -DFLAT_ONLY_FLAG |
| 331 | ' |
| 332 | mut prefs := pref.new_preferences() |
| 333 | flags := collect_cflags_for_flat_only_test_source(source, mut prefs) |
| 334 | assert flags.contains('-DFLAT_ONLY_FLAG') |
| 335 | } |
| 336 | |
| 337 | fn test_collect_cflags_from_sources_keeps_optional_os_flags_custom_only() { |
| 338 | source := 'module main |
| 339 | |
| 340 | $if linux { |
| 341 | #flag -DLINUX_BLOCK |
| 342 | } |
| 343 | $if linux ? { |
| 344 | #flag -DOPTIONAL_LINUX_BLOCK |
| 345 | } |
| 346 | $if linux ? || windows { |
| 347 | #flag -DOPTIONAL_LINUX_OR_WINDOWS_BLOCK |
| 348 | } |
| 349 | ' |
| 350 | mut linux_prefs := pref.new_preferences() |
| 351 | linux_prefs.target_os = 'linux' |
| 352 | linux_flags := collect_cflags_for_test_source(source, mut linux_prefs) |
| 353 | assert linux_flags.contains('-DLINUX_BLOCK') |
| 354 | assert !linux_flags.contains('-DOPTIONAL_LINUX_BLOCK') |
| 355 | assert !linux_flags.contains('-DOPTIONAL_LINUX_OR_WINDOWS_BLOCK') |
| 356 | |
| 357 | mut linux_defined_prefs := pref.new_preferences() |
| 358 | linux_defined_prefs.target_os = 'linux' |
| 359 | linux_defined_prefs.user_defines = ['linux'] |
| 360 | linux_defined_prefs.explicit_user_defines = ['linux'] |
| 361 | linux_defined_flags := collect_cflags_for_test_source(source, mut linux_defined_prefs) |
| 362 | assert linux_defined_flags.contains('-DLINUX_BLOCK') |
| 363 | assert linux_defined_flags.contains('-DOPTIONAL_LINUX_BLOCK') |
| 364 | assert linux_defined_flags.contains('-DOPTIONAL_LINUX_OR_WINDOWS_BLOCK') |
| 365 | |
| 366 | mut windows_prefs := pref.new_preferences() |
| 367 | windows_prefs.target_os = 'windows' |
| 368 | windows_flags := collect_cflags_for_test_source(source, mut windows_prefs) |
| 369 | assert !windows_flags.contains('-DLINUX_BLOCK') |
| 370 | assert !windows_flags.contains('-DOPTIONAL_LINUX_BLOCK') |
| 371 | assert windows_flags.contains('-DOPTIONAL_LINUX_OR_WINDOWS_BLOCK') |
| 372 | } |
| 373 | |
| 374 | fn test_collect_cflags_from_sources_keeps_optional_none_custom_only() { |
| 375 | source := 'module main |
| 376 | |
| 377 | $if none { |
| 378 | #flag -DNONE_BLOCK |
| 379 | } |
| 380 | $if none ? { |
| 381 | #flag -DOPTIONAL_NONE_BLOCK |
| 382 | } |
| 383 | ' |
| 384 | mut none_prefs := pref.new_preferences() |
| 385 | none_prefs.target_os = 'none' |
| 386 | none_prefs.user_defines = ['freestanding'] |
| 387 | none_flags := collect_cflags_for_test_source(source, mut none_prefs) |
| 388 | assert none_flags.contains('-DNONE_BLOCK') |
| 389 | assert !none_flags.contains('-DOPTIONAL_NONE_BLOCK') |
| 390 | |
| 391 | mut none_explicit_prefs := pref.new_preferences() |
| 392 | none_explicit_prefs.target_os = 'none' |
| 393 | none_explicit_prefs.user_defines = ['freestanding'] |
| 394 | none_explicit_prefs.explicit_user_defines = ['none'] |
| 395 | none_explicit_flags := collect_cflags_for_test_source(source, mut none_explicit_prefs) |
| 396 | assert none_explicit_flags.contains('-DOPTIONAL_NONE_BLOCK') |
| 397 | } |
| 398 | |
| 399 | fn test_collect_cflags_from_sources_matches_termux_blocks_and_directives() { |
| 400 | source := 'module main |
| 401 | |
| 402 | $if termux { |
| 403 | #flag -DTERMUX_BLOCK |
| 404 | } |
| 405 | $if linux || termux { |
| 406 | #flag -DTERMUX_OR_LINUX_BLOCK |
| 407 | } |
| 408 | $if android && !termux { |
| 409 | #flag -DANDROID_OUTSIDE_TERMUX_BLOCK |
| 410 | } |
| 411 | #flag termux -DTERMUX_DIRECT |
| 412 | #flag android -DANDROID_DIRECT |
| 413 | ' |
| 414 | mut termux_prefs := pref.new_preferences() |
| 415 | termux_prefs.target_os = 'termux' |
| 416 | flags := collect_cflags_for_test_source(source, mut termux_prefs) |
| 417 | assert flags.contains('-DTERMUX_BLOCK') |
| 418 | assert flags.contains('-DTERMUX_OR_LINUX_BLOCK') |
| 419 | assert flags.contains('-DTERMUX_DIRECT') |
| 420 | assert !flags.contains('-DANDROID_OUTSIDE_TERMUX_BLOCK') |
| 421 | assert !flags.contains('-DANDROID_DIRECT') |
| 422 | } |
| 423 | |
| 424 | fn test_freestanding_diagnostics_gate_direct_builtins_by_capability() { |
| 425 | for name in ['print', 'println', 'eprint', 'eprintln'] { |
| 426 | assert freestanding_test_call_name(name, ['freestanding_hooks']) == name |
| 427 | assert freestanding_test_call_name_with_hooks(name, ['freestanding_hooks', |
| 428 | 'freestanding_output'], ['output']) == '' |
| 429 | } |
| 430 | assert freestanding_test_call_name('panic', ['freestanding_hooks']) == 'panic' |
| 431 | assert freestanding_test_call_name_with_hooks('panic', ['freestanding_hooks', |
| 432 | 'freestanding_panic'], ['panic']) == '' |
| 433 | } |
| 434 | |
| 435 | fn test_freestanding_diagnostics_leave_runtime_helpers_to_cleanc() { |
| 436 | for name in ['_write_buf_to_fd', '_writeln_to_fd', 'flush_stdout', 'flush_stderr'] { |
| 437 | assert freestanding_test_call_name(name, ['freestanding_hooks']) == '' |
| 438 | } |
| 439 | |
| 440 | assert freestanding_test_call_name_with_hooks('arguments', ['freestanding_hooks', |
| 441 | 'freestanding_output'], ['output']) == '' |
| 442 | assert freestanding_test_call_name_with_hooks('arguments', ['freestanding_hooks', |
| 443 | 'freestanding_alloc'], ['alloc']) == '' |
| 444 | assert freestanding_test_call_name('malloc_noscan', |
| 445 | ['freestanding_hooks', 'freestanding_alloc']) == '' |
| 446 | assert freestanding_test_call_name_with_hooks('malloc_noscan', [ |
| 447 | 'freestanding_hooks', |
| 448 | 'freestanding_alloc', |
| 449 | ], ['alloc']) == '' |
| 450 | assert freestanding_restricted_call_in_expr(ast.Expr(ast.CallExpr{ |
| 451 | lhs: ast.Expr(ast.Ident{ |
| 452 | name: 'println' |
| 453 | }) |
| 454 | args: [ |
| 455 | ast.Expr(ast.BasicLiteral{ |
| 456 | kind: .number |
| 457 | value: '123' |
| 458 | }), |
| 459 | ] |
| 460 | }), FreestandingScanContext{ |
| 461 | user_defines: ['freestanding_hooks', 'freestanding_output'] |
| 462 | target_os: 'linux' |
| 463 | freestanding_hooks: ['output'] |
| 464 | }) == '' |
| 465 | assert freestanding_restricted_call_in_expr(ast.Expr(ast.CallExpr{ |
| 466 | lhs: ast.Expr(ast.Ident{ |
| 467 | name: 'println' |
| 468 | }) |
| 469 | args: [ |
| 470 | ast.Expr(ast.BasicLiteral{ |
| 471 | kind: .number |
| 472 | value: '123' |
| 473 | }), |
| 474 | ] |
| 475 | }), FreestandingScanContext{ |
| 476 | user_defines: ['freestanding_hooks', 'freestanding_output', 'freestanding_alloc'] |
| 477 | target_os: 'linux' |
| 478 | freestanding_hooks: ['output', 'alloc'] |
| 479 | }) == '' |
| 480 | } |
| 481 | |
| 482 | fn test_freestanding_diagnostics_skip_inactive_conditional_functions() { |
| 483 | ctx := FreestandingScanContext{ |
| 484 | user_defines: ['freestanding'] |
| 485 | target_os: 'linux' |
| 486 | } |
| 487 | hosted_call := ast.Stmt(ast.ExprStmt{ |
| 488 | expr: ast.Expr(ast.CallExpr{ |
| 489 | lhs: ast.Expr(ast.Ident{ |
| 490 | name: 'println' |
| 491 | }) |
| 492 | }) |
| 493 | }) |
| 494 | inactive_windows_fn := ast.Stmt(ast.FnDecl{ |
| 495 | attributes: [ |
| 496 | ast.Attribute{ |
| 497 | comptime_cond: ast.Expr(ast.Ident{ |
| 498 | name: 'windows' |
| 499 | }) |
| 500 | }, |
| 501 | ] |
| 502 | stmts: [hosted_call] |
| 503 | }) |
| 504 | inactive_not_freestanding_fn := ast.Stmt(ast.FnDecl{ |
| 505 | attributes: [ |
| 506 | ast.Attribute{ |
| 507 | comptime_cond: ast.Expr(ast.PrefixExpr{ |
| 508 | op: .not |
| 509 | expr: ast.Expr(ast.Ident{ |
| 510 | name: 'freestanding' |
| 511 | }) |
| 512 | }) |
| 513 | }, |
| 514 | ] |
| 515 | stmts: [hosted_call] |
| 516 | }) |
| 517 | active_fn := ast.Stmt(ast.FnDecl{ |
| 518 | attributes: [ |
| 519 | ast.Attribute{ |
| 520 | comptime_cond: ast.Expr(ast.Ident{ |
| 521 | name: 'freestanding' |
| 522 | }) |
| 523 | }, |
| 524 | ] |
| 525 | stmts: [hosted_call] |
| 526 | }) |
| 527 | assert freestanding_restricted_call_in_stmt(inactive_windows_fn, ctx) == '' |
| 528 | assert freestanding_restricted_call_in_stmt(inactive_not_freestanding_fn, ctx) == '' |
| 529 | assert freestanding_restricted_call_in_stmt(active_fn, ctx) == 'println' |
| 530 | } |
| 531 | |
| 532 | fn test_freestanding_diagnostics_leave_array_allocation_to_cleanc() { |
| 533 | ctx := FreestandingScanContext{ |
| 534 | user_defines: ['freestanding'] |
| 535 | target_os: 'linux' |
| 536 | } |
| 537 | fixed_array := ast.Expr(ast.ArrayInitExpr{ |
| 538 | typ: ast.Expr(ast.Type(ast.ArrayFixedType{ |
| 539 | len: ast.Expr(ast.BasicLiteral{ |
| 540 | kind: .number |
| 541 | value: '3' |
| 542 | }) |
| 543 | elem_type: ast.Expr(ast.Ident{ |
| 544 | name: 'int' |
| 545 | }) |
| 546 | })) |
| 547 | }) |
| 548 | dynamic_array := ast.Expr(ast.ArrayInitExpr{ |
| 549 | typ: ast.Expr(ast.Type(ast.ArrayType{ |
| 550 | elem_type: ast.Expr(ast.Ident{ |
| 551 | name: 'int' |
| 552 | }) |
| 553 | })) |
| 554 | }) |
| 555 | fixed_literal_array := ast.Expr(ast.ArrayInitExpr{ |
| 556 | exprs: [ |
| 557 | ast.Expr(ast.BasicLiteral{ |
| 558 | kind: .number |
| 559 | value: '1' |
| 560 | }), |
| 561 | ast.Expr(ast.BasicLiteral{ |
| 562 | kind: .number |
| 563 | value: '2' |
| 564 | }), |
| 565 | ast.Expr(ast.BasicLiteral{ |
| 566 | kind: .number |
| 567 | value: '3' |
| 568 | }), |
| 569 | ] |
| 570 | len: ast.Expr(ast.PostfixExpr{ |
| 571 | op: .not |
| 572 | expr: ast.empty_expr |
| 573 | }) |
| 574 | }) |
| 575 | assert freestanding_restricted_call_in_expr(fixed_array, ctx) == '' |
| 576 | assert freestanding_restricted_call_in_expr(fixed_literal_array, ctx) == '' |
| 577 | assert freestanding_restricted_call_in_expr(dynamic_array, ctx) == '' |
| 578 | } |
| 579 | |
| 580 | fn test_collect_cflags_from_sources_uses_or_and_not_precedence() { |
| 581 | source := 'module main |
| 582 | |
| 583 | $if !windows && linux { |
| 584 | #flag -DNEGATED_AND_LINUX |
| 585 | } |
| 586 | |
| 587 | $if linux || windows && macos { |
| 588 | #flag -DOR_AND_LINUX |
| 589 | } |
| 590 | ' |
| 591 | mut linux_prefs := pref.new_preferences() |
| 592 | linux_prefs.target_os = 'linux' |
| 593 | linux_flags := collect_cflags_for_test_source(source, mut linux_prefs) |
| 594 | assert linux_flags.contains('-DNEGATED_AND_LINUX') |
| 595 | assert linux_flags.contains('-DOR_AND_LINUX') |
| 596 | |
| 597 | mut macos_prefs := pref.new_preferences() |
| 598 | macos_prefs.target_os = 'macos' |
| 599 | macos_flags := collect_cflags_for_test_source(source, mut macos_prefs) |
| 600 | assert !macos_flags.contains('-DNEGATED_AND_LINUX') |
| 601 | assert !macos_flags.contains('-DOR_AND_LINUX') |
| 602 | |
| 603 | mut windows_prefs := pref.new_preferences() |
| 604 | windows_prefs.target_os = 'windows' |
| 605 | windows_flags := collect_cflags_for_test_source(source, mut windows_prefs) |
| 606 | assert !windows_flags.contains('-DNEGATED_AND_LINUX') |
| 607 | assert !windows_flags.contains('-DOR_AND_LINUX') |
| 608 | } |
| 609 | |