xref: /aosp_15_r20/build/bazel/toolchains/clang/host/linux-x86/cc_toolchain_features_ubsan_test.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1"""Copyright (C) 2022 The Android Open Source Project
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7     http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14"""
15
16load("@bazel_skylib//lib:paths.bzl", "paths")
17load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
18load(
19    "//build/bazel/rules/test_common:flags.bzl",
20    "action_flags_absent_for_mnemonic_test",
21    "action_flags_present_only_for_mnemonic_test",
22)
23load(
24    ":cc_toolchain_constants.bzl",
25    "libclang_ubsan_minimal_rt_prebuilt_map",
26    _generated_sanitizer_constants = "generated_sanitizer_constants",
27)
28load(
29    ":cc_toolchain_features.bzl",
30    "int_overflow_ignorelist_filename",
31    "int_overflow_ignorelist_path",
32)
33
34compile_action_mnemonic = "CppCompile"
35link_action_mnemonic = "CppLink"
36ubsan_prefix_format = "-fsanitize=%s"
37
38def _ubsan_sanitizer_test(
39        name,
40        target_under_test,
41        expected_sanitizers):
42    action_flags_present_only_for_mnemonic_test(
43        name = name,
44        target_under_test = target_under_test,
45        mnemonics = [compile_action_mnemonic, link_action_mnemonic],
46        expected_flags = [
47            ubsan_prefix_format % sanitizer
48            for sanitizer in expected_sanitizers
49        ],
50    )
51
52# Include these different file types to make sure that all actions types are
53# triggered
54test_srcs = [
55    "foo.cpp",
56    "bar.c",
57]
58
59all_test_srcs = test_srcs + [
60    "baz.s",
61    "blah.S",
62]
63
64def _test_ubsan_integer_overflow_feature():
65    name = "ubsan_integer_overflow"
66    native.cc_binary(
67        name = name,
68        srcs = test_srcs,
69        features = ["ubsan_integer_overflow"],
70        tags = ["manual"],
71    )
72
73    int_overflow_test_name = name + "_test"
74    test_names = [int_overflow_test_name]
75    _ubsan_sanitizer_test(
76        name = int_overflow_test_name,
77        target_under_test = name,
78        expected_sanitizers = [
79            "signed-integer-overflow",
80            "unsigned-integer-overflow",
81        ],
82    )
83
84    ignorelist_test_name = name + "_ignorelist_flag_test"
85    test_names += [ignorelist_test_name]
86    action_flags_present_only_for_mnemonic_test(
87        name = ignorelist_test_name,
88        target_under_test = name,
89        mnemonics = [compile_action_mnemonic],
90        expected_flags = ["-fsanitize-ignorelist=%s/%s" % (
91            int_overflow_ignorelist_path,
92            int_overflow_ignorelist_filename,
93        )],
94    )
95    return test_names
96
97def _test_ubsan_misc_undefined_feature():
98    name = "ubsan_misc_undefined"
99    test_name = name + "_test"
100    native.cc_binary(
101        name = name,
102        srcs = all_test_srcs,
103        features = ["ubsan_undefined"],  # Just pick one; doesn't matter which
104        tags = ["manual"],
105    )
106    _ubsan_sanitizer_test(
107        name = test_name,
108        target_under_test = name,
109        expected_sanitizers = ["undefined"],
110    )
111    return test_name
112
113def _ubsan_disablement_test(
114        name,
115        target_under_test,
116        expected_disabled_sanitizer,
117        disabled,
118        target_compatible_with):
119    no_sanitize_flag_prefix_format = "-fno-sanitize=%s"
120    if disabled:
121        action_flags_present_only_for_mnemonic_test(
122            name = name,
123            target_under_test = target_under_test,
124            mnemonics = [compile_action_mnemonic],
125            expected_flags = [
126                no_sanitize_flag_prefix_format % expected_disabled_sanitizer,
127            ],
128            target_compatible_with = target_compatible_with,
129        )
130    else:
131        action_flags_absent_for_mnemonic_test(
132            name = name,
133            target_under_test = target_under_test,
134            mnemonics = [compile_action_mnemonic],
135            expected_absent_flags = [
136                no_sanitize_flag_prefix_format % expected_disabled_sanitizer,
137            ],
138            target_compatible_with = target_compatible_with,
139        )
140
141def ubsan_disablement_linux_test(
142        name,
143        target_under_test,
144        expected_disabled_sanitizer,
145        disabled):
146    _ubsan_disablement_test(
147        name = name,
148        target_under_test = target_under_test,
149        expected_disabled_sanitizer = expected_disabled_sanitizer,
150        disabled = disabled,
151        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux"],
152    )
153
154def ubsan_disablement_linux_bionic_test(
155        name,
156        target_under_test,
157        expected_disabled_sanitizer,
158        disabled):
159    _ubsan_disablement_test(
160        name = name,
161        target_under_test = target_under_test,
162        expected_disabled_sanitizer = expected_disabled_sanitizer,
163        disabled = disabled,
164        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux_bionic"],
165    )
166
167def ubsan_disablement_android_test(
168        name,
169        target_under_test,
170        expected_disabled_sanitizer,
171        disabled):
172    _ubsan_disablement_test(
173        name = name,
174        target_under_test = target_under_test,
175        expected_disabled_sanitizer = expected_disabled_sanitizer,
176        disabled = disabled,
177        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:android"],
178    )
179
180def _test_ubsan_implicit_integer_sign_change_disabled_when_linux_with_integer():
181    name = "ubsan_implicit_integer_sign_change_disabled_when_linux_with_integer"
182    test_name = name + "_test"
183
184    native.cc_binary(
185        name = name,
186        srcs = test_srcs,
187        features = ["ubsan_integer"],
188        tags = ["manual"],
189    )
190    ubsan_disablement_linux_test(
191        name = test_name,
192        target_under_test = name,
193        expected_disabled_sanitizer = "implicit-integer-sign-change",
194        disabled = True,
195    )
196
197    return test_name
198
199def _test_ubsan_implicit_integer_sign_change_not_disabled_when_specified():
200    name = "ubsan_implicit_integer_sign_change_not_disabled_when_specified"
201    test_name = name + "_test"
202
203    native.cc_binary(
204        name = name,
205        srcs = test_srcs,
206        features = [
207            "ubsan_integer",
208            "ubsan_implicit-integer-sign-change",
209        ],
210        tags = ["manual"],
211    )
212    ubsan_disablement_linux_test(
213        name = test_name,
214        target_under_test = name,
215        expected_disabled_sanitizer = "implicit-integer-sign-change",
216        disabled = False,
217    )
218
219    return test_name
220
221def _test_ubsan_implicit_integer_sign_change_not_disabled_without_integer():
222    name = "ubsan_implicit_integer_sign_change_not_disabled_without_integer"
223    test_name = name + "_test"
224
225    native.cc_binary(
226        name = name,
227        srcs = test_srcs,
228        tags = ["manual"],
229    )
230    ubsan_disablement_linux_test(
231        name = test_name,
232        target_under_test = name,
233        expected_disabled_sanitizer = "implicit-integer-sign-change",
234        disabled = False,
235    )
236
237    return test_name
238
239def _test_ubsan_unsigned_shift_base_disabled_when_linux_with_integer():
240    name = "ubsan_unsigned_shift_base_disabled_when_linux_with_integer"
241    test_name = name + "_test"
242
243    native.cc_binary(
244        name = name,
245        srcs = test_srcs,
246        features = ["ubsan_integer"],
247        tags = ["manual"],
248    )
249    ubsan_disablement_linux_test(
250        name = test_name,
251        target_under_test = name,
252        expected_disabled_sanitizer = "unsigned-shift-base",
253        disabled = True,
254    )
255
256    return test_name
257
258def _test_ubsan_unsigned_shift_base_not_disabled_when_specified():
259    name = "ubsan_unsigned_shift_base_not_disabled_when_specified"
260    test_name = name + "_test"
261
262    native.cc_binary(
263        name = name,
264        srcs = test_srcs,
265        features = [
266            "ubsan_integer",
267            "ubsan_unsigned-shift-base",
268        ],
269        tags = ["manual"],
270    )
271    ubsan_disablement_linux_test(
272        name = test_name,
273        target_under_test = name,
274        expected_disabled_sanitizer = "unsigned-shift-base",
275        disabled = False,
276    )
277
278    return test_name
279
280def _test_ubsan_unsigned_shift_base_not_disabled_without_integer():
281    name = "ubsan_unsigned_shift_base_not_disabled_without_integer"
282    test_name = name + "_test"
283
284    native.cc_binary(
285        name = name,
286        srcs = test_srcs,
287        tags = ["manual"],
288    )
289    ubsan_disablement_linux_test(
290        name = test_name,
291        target_under_test = name,
292        expected_disabled_sanitizer = "unsigned-shift-base",
293        disabled = False,
294    )
295
296    return test_name
297
298def _test_ubsan_unsupported_non_bionic_checks_disabled_when_linux():
299    name = "ubsan_unsupported_non_bionic_checks_disabled_when_linux"
300    test_name = name + "_test"
301
302    native.cc_binary(
303        name = name,
304        srcs = test_srcs,
305        features = ["ubsan_undefined"],
306        tags = ["manual"],
307    )
308
309    ubsan_disablement_linux_test(
310        name = test_name,
311        target_under_test = name,
312        expected_disabled_sanitizer = "function,vptr",
313        disabled = True,
314    )
315
316    return test_name
317
318# TODO(b/263787980): Uncomment when bionic toolchain is implemented
319#def _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_linux_bionic():
320#    name = "ubsan_unsupported_non_bionic_checks_not_disabled_when_linux_bionic"
321#    test_name = name + "_test"
322#
323#    native.cc_binary(
324#        name = name,
325#        srcs = test_srcs,
326#        features = ["ubsan_undefined"],
327#        tags = ["manual"],
328#    )
329#
330#    ubsan_disablement_linux_bionic_test(
331#        name = test_name,
332#        target_under_test = name,
333#        expected_disabled_sanitizer = "function,vptr",
334#        disabled = False,
335#    )
336#
337#    return test_name
338
339def _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_android():
340    name = "ubsan_unsupported_non_bionic_checks_not_disabled_when_android"
341    test_name = name + "_test"
342
343    native.cc_binary(
344        name = name,
345        srcs = test_srcs,
346        features = ["ubsan_undefined"],
347        tags = ["manual"],
348    )
349
350    ubsan_disablement_android_test(
351        name = test_name,
352        target_under_test = name,
353        expected_disabled_sanitizer = "function,vptr",
354        disabled = False,
355    )
356
357    return test_name
358
359def _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_no_ubsan():
360    name = "ubsan_unsupported_non_bionic_checks_not_disabled_when_no_ubsan"
361    test_name = name + "_test"
362
363    native.cc_binary(
364        name = name,
365        srcs = test_srcs,
366        tags = ["manual"],
367    )
368
369    ubsan_disablement_linux_test(
370        name = test_name,
371        target_under_test = name,
372        expected_disabled_sanitizer = "function,vptr",
373        disabled = False,
374    )
375
376    return test_name
377
378def _test_ubsan_no_link_runtime():
379    name = "ubsan_no_link_runtime"
380
381    native.cc_binary(
382        name = name,
383        srcs = test_srcs,
384        features = ["ubsan_undefined"],
385        tags = ["manual"],
386    )
387
388    android_test_name = name + "_when_android_test"
389    test_names = [android_test_name]
390    action_flags_present_android_test(
391        name = android_test_name,
392        target_under_test = name,
393        mnemonics = [link_action_mnemonic],
394        expected_flags = [_generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag],
395    )
396
397    # TODO(b/263787980): Uncomment when bionic toolchain is implemented
398    #    bionic_test_name = name + "_when_bionic_test"
399    #    action_flags_linux_bionic_test(
400    #        name = bionic_test_name,
401    #        target_under_test = name,
402    #        mnemonics = [link_action_mnemonic],
403    #        expected_flags = [_generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag],
404    #    )
405    #    test_names += [bionic_test_name]
406
407    # TODO(b/263787526): Uncomment when musl toolchain is implemented
408    #    musl_test_name = name + "_when_musl_test"
409    #    action_flags_musl_test(
410    #        name = musl_test_name,
411    #        target_under_test = name,
412    #        mnemonics = [link_action_mnemonic],
413    #        expected_flags = [_generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag],
414    #    )
415    #    test_names += [musl_test_name]
416
417    return test_names
418
419def action_flags_present_linux_test(**kwargs):
420    action_flags_present_only_for_mnemonic_test(
421        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux"],
422        **kwargs
423    )
424
425def action_flags_present_android_test(**kwargs):
426    action_flags_present_only_for_mnemonic_test(
427        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:android"],
428        **kwargs
429    )
430
431# TODO(b/263787980): Uncomment when bionic toolchain is implemented
432#def action_flags_present_linux_bionic_test(**kwargs):
433#    action_flags_present_only_for_mnemonic_test(
434#        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux_bionic"],
435#        **kwargs
436#    )
437
438# TODO(b/263787526): Uncomment when musl toolchain is implemented
439#def action_flags_present_linux_musl_test(**kwargs):
440#    action_flags_present_only_for_mnemonic_test(
441#        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux_musl"],
442#        **kwargs
443#    )
444
445def action_flags_absent_linux_test(**kwargs):
446    action_flags_absent_for_mnemonic_test(
447        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux"],
448        **kwargs
449    )
450
451def action_flags_absent_android_test(**kwargs):
452    action_flags_absent_for_mnemonic_test(
453        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:android"],
454        **kwargs
455    )
456
457# TODO(b/263787980): Uncomment when bionic toolchain is implemented
458#def action_flags_absent_linux_bionic_test(**kwargs):
459#    action_flags_absent_for_mnemonic_test(
460#        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux_bionic"],
461#        **kwargs
462#    )
463
464# TODO(b/263787526): Uncomment when musl toolchain is implemented
465#def action_flags_absent_linux_musl_test(**kwargs):
466#    action_flags_absent_for_mnemonic_test(
467#        target_compatible_with = ["@//build/bazel_common_rules/platforms/os:linux_musl"],
468#        **kwargs
469#    )
470
471def _test_ubsan_link_runtime_when_not_bionic_or_musl():
472    name = "ubsan_link_runtime_when_not_bionic_or_musl"
473    test_name = name + "_test"
474
475    native.cc_binary(
476        name = name,
477        srcs = test_srcs,
478        tags = ["manual"],
479    )
480
481    action_flags_absent_linux_test(
482        name = test_name,
483        target_under_test = name,
484        mnemonics = [link_action_mnemonic],
485        expected_absent_flags = [_generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag],
486    )
487
488    return test_name
489
490no_undefined_flag = "-Wl,--no-undefined"
491
492def _test_no_undefined_flag_present_when_bionic_or_musl():
493    name = "no_undefined_flag_present_when_bionic_or_musl"
494
495    native.cc_binary(
496        name = name,
497        srcs = test_srcs,
498        features = ["ubsan_undefined"],
499        tags = ["manual"],
500    )
501
502    android_test_name = name + "_when_android_test"
503    test_names = [android_test_name]
504    action_flags_present_android_test(
505        name = android_test_name,
506        target_under_test = name,
507        mnemonics = [link_action_mnemonic],
508        expected_flags = [no_undefined_flag],
509    )
510
511    # TODO(b/263787980): Uncomment when bionic toolchain is implemented
512    #    bionic_test_name = name + "_when_bionic_test"
513    #    test_names += [bionic_test_name]
514    #    action_flags_present_linux_bionic_test(
515    #        name = bionic_test_name,
516    #        target_under_test = name,
517    #        mnemonics = [link_action_mnemonic],
518    #        expected_flags = [no_undefined_flag],
519    #    )
520
521    # TODO(b/263787526): Uncomment when musl toolchain is implemented
522    #    musl_test_name = name + "_when_musl_test"
523    #    test_names += [musl_test_name]
524    #    action_flags_present_musl_test(
525    #        name = musl_test_name,
526    #        target_under_test = name,
527    #        mnemonics = [link_action_mnemonic],
528    #        expected_flags = [no_undefined_flag],
529    #    )
530
531    return test_names
532
533# TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
534#def _test_undefined_flag_absent_when_windows_or_darwin():
535#    name = "no_undefined_flag_absent_when_windows_or_darwin"
536#
537#    native.cc_binary(
538#        name = name,
539#        srcs = test_srcs,
540#        features = ["ubsan_undefined"],
541#        tags = ["manual"],
542#    )
543#
544#    test_name = name + "_test"
545#    action_flags_absent_for_mnemonic_test(
546#        name = test_name,
547#        target_under_test = name,
548#        mnemonics = [compile_action_mnemonic],
549#        expected_absent_flags = [ubsan_prefix_format % "undefined"]
550#        target_compatible_with = [
551#            "//build/bazel_common_rules/platforms/os:darwin",
552#            "//build/bazel_common_rules/platforms/os:windows",
553#        ]
554#    )
555#
556#    return test_name
557
558def _test_no_undefined_flag_absent_when_not_bionic_or_musl():
559    name = "no_undefined_flag_absent_when_not_bionic_or_musl"
560    test_name = name + "_test"
561
562    native.cc_binary(
563        name = name,
564        srcs = test_srcs,
565        features = ["ubsan_undefined"],
566        tags = ["manual"],
567    )
568
569    action_flags_absent_linux_test(
570        name = test_name,
571        target_under_test = name,
572        mnemonics = [link_action_mnemonic],
573        expected_absent_flags = [no_undefined_flag],
574    )
575
576    return test_name
577
578host_only_flags = ["-fno-sanitize-recover=all"]
579
580def _test_host_only_features():
581    name = "host_only_features"
582    test_names = []
583
584    native.cc_binary(
585        name = name,
586        srcs = test_srcs,
587        features = ["ubsan_undefined"],
588        tags = ["manual"],
589    )
590
591    host_test_name = name + "_present_when_host_test"
592    test_names += [host_test_name]
593    action_flags_present_linux_test(
594        name = host_test_name,
595        target_under_test = name,
596        mnemonics = [compile_action_mnemonic],
597        expected_flags = host_only_flags,
598    )
599
600    device_test_name = name + "_absent_when_device_test"
601    test_names += [device_test_name]
602    action_flags_absent_android_test(
603        name = device_test_name,
604        target_under_test = name,
605        mnemonics = [compile_action_mnemonic],
606        expected_absent_flags = host_only_flags,
607    )
608
609    return test_names
610
611device_only_flags = [
612    "-fsanitize-trap=all",
613]
614
615def _test_device_only_features():
616    name = "device_only_features"
617    test_names = []
618
619    native.cc_binary(
620        name = name,
621        srcs = test_srcs,
622        features = ["ubsan_undefined"],
623        tags = ["manual"],
624    )
625
626    device_test_name = name + "_present_when_device_test"
627    test_names += [device_test_name]
628    action_flags_present_android_test(
629        name = device_test_name,
630        target_under_test = name,
631        mnemonics = [compile_action_mnemonic],
632        expected_flags = device_only_flags,
633    )
634
635    host_test_name = name + "_absent_when_host_test"
636    test_names += [host_test_name]
637    action_flags_absent_linux_test(
638        name = host_test_name,
639        target_under_test = name,
640        mnemonics = [compile_action_mnemonic],
641        expected_absent_flags = device_only_flags,
642    )
643
644    return test_names
645
646def _test_device_only_and_host_only_features_absent_when_ubsan_disabled():
647    name = "device_only_and_host_only_features_absent_when_ubsan_disabled"
648    test_names = []
649
650    native.cc_binary(
651        name = name,
652        srcs = test_srcs,
653        tags = ["manual"],
654    )
655
656    host_test_name = name + "_host_test"
657    test_names += [host_test_name]
658    action_flags_absent_linux_test(
659        name = host_test_name,
660        target_under_test = name,
661        mnemonics = [compile_action_mnemonic],
662        expected_absent_flags = host_only_flags,
663    )
664
665    device_test_name = name + "_device_test"
666    test_names += [device_test_name]
667    action_flags_absent_android_test(
668        name = device_test_name,
669        target_under_test = name,
670        mnemonics = [compile_action_mnemonic],
671        expected_absent_flags = device_only_flags,
672    )
673
674    return test_names
675
676def _test_minimal_runtime_flags_added_to_compilation():
677    name = "minimal_runtime_flags_added_to_compilation"
678
679    native.cc_binary(
680        name = name,
681        srcs = test_srcs,
682        features = ["ubsan_undefined"],
683        tags = ["manual"],
684    )
685
686    test_name = name + "_test"
687    action_flags_present_only_for_mnemonic_test(
688        name = test_name,
689        target_under_test = name,
690        mnemonics = [compile_action_mnemonic],
691        expected_flags = _generated_sanitizer_constants.MinimalRuntimeFlags,
692    )
693
694    return test_name
695
696def _exclude_rt_test_for_os_arch(target_name, os, arch, flag):
697    test_name = "%s_%s_test" % (
698        target_name,
699        os + "_" + arch,
700    )
701
702    action_flags_present_only_for_mnemonic_test(
703        name = test_name,
704        target_under_test = target_name,
705        mnemonics = [link_action_mnemonic],
706        expected_flags = [flag],
707        target_compatible_with = [
708            "//build/bazel_common_rules/platforms/os:" + os,
709            "//build/bazel_common_rules/platforms/arch:" + arch,
710        ],
711    )
712
713    return test_name
714
715def _test_exclude_ubsan_rt():
716    _exclude_ubsan_rt_name = "ubsan_exclude_rt"
717    native.cc_binary(
718        name = _exclude_ubsan_rt_name,
719        srcs = test_srcs,
720        features = ["ubsan_undefined"],
721        tags = ["manual"],
722    )
723    test_cases = [
724        {
725            "os": "android",
726            "arch": "arm",
727            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-arm-android.a",
728        },
729        {
730            "os": "android",
731            "arch": "arm64",
732            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-aarch64-android.a",
733        },
734        {
735            "os": "android",
736            "arch": "x86",
737            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-i686-android.a",
738        },
739        {
740            "os": "android",
741            "arch": "x86_64",
742            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-x86_64-android.a",
743        },
744        {
745            "os": "linux_bionic",
746            "arch": "x86_64",
747            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-x86_64-android.a",
748        },
749        {
750            "os": "linux",
751            "arch": "x86",
752            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-i386.a",
753        },
754        {
755            "os": "linux",
756            "arch": "x86_64",
757            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-x86_64.a",
758        },
759        {
760            "os": "linux_musl",
761            "arch": "x86",
762            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-i386.a",
763        },
764        {
765            "os": "linux_musl",
766            "arch": "x86_64",
767            "flag": "-Wl,--exclude-libs=libclang_rt.ubsan_minimal-x86_64.a",
768        },
769    ]
770    return [
771        _exclude_rt_test_for_os_arch(_exclude_ubsan_rt_name, **tc)
772        for tc in test_cases
773    ]
774
775def _test_exclude_builtins_rt():
776    _exclude_builtins_rt_name = "builtins_exclude_rt"
777    native.cc_binary(
778        name = _exclude_builtins_rt_name,
779        srcs = test_srcs,
780        tags = ["manual"],
781    )
782    test_cases = [
783        {
784            "os": "android",
785            "arch": "arm",
786            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
787        },
788        {
789            "os": "android",
790            "arch": "arm64",
791            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
792        },
793        {
794            "os": "android",
795            "arch": "x86",
796            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
797        },
798        {
799            "os": "android",
800            "arch": "x86_64",
801            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
802        },
803        {
804            "os": "linux_bionic",
805            "arch": "x86_64",
806            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
807        },
808        {
809            "os": "linux",
810            "arch": "x86",
811            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-i386.a",
812        },
813        {
814            "os": "linux",
815            "arch": "x86_64",
816            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-x86_64.a",
817        },
818        {
819            "os": "linux_musl",
820            "arch": "x86",
821            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-i386.a",
822        },
823        {
824            "os": "linux_musl",
825            "arch": "x86_64",
826            "flag": "-Wl,--exclude-libs=libclang_rt.builtins-x86_64.a",
827        },
828    ]
829    return [
830        _exclude_rt_test_for_os_arch(_exclude_builtins_rt_name, **tc)
831        for tc in test_cases
832    ]
833
834def cc_toolchain_features_ubsan_test_suite(name):
835    individual_tests = [
836        _test_ubsan_misc_undefined_feature(),
837        _test_ubsan_implicit_integer_sign_change_disabled_when_linux_with_integer(),
838        _test_ubsan_implicit_integer_sign_change_not_disabled_when_specified(),
839        _test_ubsan_implicit_integer_sign_change_not_disabled_without_integer(),
840        _test_ubsan_unsigned_shift_base_disabled_when_linux_with_integer(),
841        _test_ubsan_unsigned_shift_base_not_disabled_when_specified(),
842        _test_ubsan_unsigned_shift_base_not_disabled_without_integer(),
843        _test_ubsan_unsupported_non_bionic_checks_disabled_when_linux(),
844        # TODO(b/263787980): Uncomment when bionic toolchain is implemented
845        # _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_linux_bionic(),
846        _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_android(),
847        _test_ubsan_unsupported_non_bionic_checks_not_disabled_when_no_ubsan(),
848        _test_ubsan_link_runtime_when_not_bionic_or_musl(),
849        _test_minimal_runtime_flags_added_to_compilation(),
850        # TODO(b/274924237): Uncomment after Darwin and Windows have toolchains
851        #        _test_undefined_flag_absent_when_windows_or_darwin(),
852    ]
853    native.test_suite(
854        name = name,
855        tests = individual_tests +
856                _test_ubsan_no_link_runtime() +
857                _test_no_undefined_flag_present_when_bionic_or_musl() +
858                _test_ubsan_integer_overflow_feature() +
859                _test_host_only_features() +
860                _test_device_only_features() +
861                _test_device_only_and_host_only_features_absent_when_ubsan_disabled() +
862                _test_exclude_ubsan_rt() +
863                _test_exclude_builtins_rt(),
864    )
865