| # Copyright 2011 The Chromium Authors | 
 | # Use of this source code is governed by a BSD-style license that can be | 
 | # found in the LICENSE file. | 
 |  | 
 | # This file is meant to be included into an target to create a unittest that | 
 | # invokes a set of no-compile tests.  A no-compile test is a test that asserts | 
 | # a particular construct will not compile. | 
 | # | 
 | # Usage: | 
 | # | 
 | # 1. Create a GN target: | 
 | # | 
 | #    import("//build/nocompile.gni") | 
 | # | 
 | #    nocompile_source_set("base_nocompile_tests") { | 
 | #      sources = [ | 
 | #        "functional/one_not_equal_two_nocompile.nc", | 
 | #      ] | 
 | #      deps = [ | 
 | #        ":base" | 
 | #      ] | 
 | #    } | 
 | # | 
 | #    Note that by convention, nocompile tests use the `.nc` extension rather | 
 | #    than the standard `.cc` extension: this is because the expectation lines | 
 | #    often exceed 80 characters, which would make clang-format unhappy. | 
 | # | 
 | # 2. Add a dep from a related test binary to the nocompile source set: | 
 | # | 
 | #    test("base_unittests") { | 
 | #      ... | 
 | #      deps += [ ":base_nocompile_tests" ] | 
 | #    } | 
 | # | 
 | # 3. Populate the .nc file with test cases. Expected compile failures should be | 
 | #    annotated with a comment of the form: | 
 | # | 
 | #    // expected-error {{<expected error string here>}} | 
 | # | 
 | #    For example: | 
 | # | 
 | #    void OneDoesNotEqualTwo() { | 
 | #      static_assert(1 == 2);  // expected-error {{static assertion failed due to requirement '1 == 2'}} | 
 | #    } | 
 | # | 
 | #    The verification logic is built as part of clang; full documentation is at | 
 | #    https://clang.llvm.org/docs/InternalsManual.html#specifying-diagnostics. | 
 | # | 
 | # Also see: | 
 | #   http://dev.chromium.org/developers/testing/no-compile-tests | 
 | # | 
 | import("//build/config/clang/clang.gni") | 
 | if (is_win) { | 
 |   import("//build/toolchain/win/win_toolchain_data.gni") | 
 | } | 
 |  | 
 | declare_args() { | 
 |   enable_nocompile_tests = is_clang | 
 | } | 
 |  | 
 | if (enable_nocompile_tests) { | 
 |   template("nocompile_source_set") { | 
 |     action_foreach(target_name) { | 
 |       testonly = true | 
 |  | 
 |       script = "//tools/nocompile/wrapper.py" | 
 |       sources = invoker.sources | 
 |       if (defined(invoker.deps)) { | 
 |         deps = invoker.deps | 
 |       } | 
 |  | 
 |       # An action is not a compiler, so configs is empty until it is explicitly | 
 |       # set. | 
 |       configs = default_compiler_configs | 
 |       if (defined(invoker.configs)) { | 
 |         configs += invoker.configs | 
 |       } | 
 |  | 
 |       configs -= [ | 
 |         # Disable the checks that the Chrome style plugin normally enforces to | 
 |         # reduce the amount of boilerplate needed in nocompile tests. | 
 |         "//build/config/clang:find_bad_constructs", | 
 |       ] | 
 |  | 
 |       if (is_win) { | 
 |         result_path = | 
 |             "$target_out_dir/$target_name/{{source_name_part}}_placeholder.obj" | 
 |       } else { | 
 |         result_path = | 
 |             "$target_out_dir/$target_name/{{source_name_part}}_placeholder.o" | 
 |       } | 
 |       rebased_obj_path = rebase_path(result_path, root_build_dir) | 
 |  | 
 |       depfile = "${result_path}.d" | 
 |       rebased_depfile_path = rebase_path(depfile, root_build_dir) | 
 |       outputs = [ result_path ] | 
 |  | 
 |       if (is_win) { | 
 |         if (host_os == "win") { | 
 |           cxx = "clang-cl.exe" | 
 |         } else { | 
 |           cxx = "clang-cl" | 
 |         } | 
 |       } else { | 
 |         cxx = "clang++" | 
 |       } | 
 |  | 
 |       args = [] | 
 |  | 
 |       if (is_win) { | 
 |         # ninja normally parses /showIncludes output, but the depsformat | 
 |         # variable can only be set in compiler tools, not for custom actions. | 
 |         # Unfortunately, this means the clang wrapper needs to generate the | 
 |         # depfile itself. | 
 |         args += [ "--generate-depfile" ] | 
 |       } | 
 |  | 
 |       args += [ | 
 |         rebase_path("$clang_base_path/bin/$cxx", root_build_dir), | 
 |         "{{source}}", | 
 |         rebased_obj_path, | 
 |         rebased_depfile_path, | 
 |         "--", | 
 |         "{{cflags}}", | 
 |         "{{cflags_cc}}", | 
 |         "{{defines}}", | 
 |         "{{include_dirs}}", | 
 |  | 
 |         # No need to generate an object file for nocompile tests. | 
 |         "-Xclang", | 
 |         "-fsyntax-only", | 
 |  | 
 |         # Enable clang's VerifyDiagnosticConsumer: | 
 |         # https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html | 
 |         "-Xclang", | 
 |         "-verify", | 
 |  | 
 |         # But don't require expected-note comments since that is not the | 
 |         # primary point of the nocompile tests. | 
 |         "-Xclang", | 
 |         "-verify-ignore-unexpected=note", | 
 |  | 
 |         # Disable the error limit so that nocompile tests do not need to be | 
 |         # arbitrarily split up when they hit the default error limit. | 
 |         "-ferror-limit=0", | 
 |  | 
 |         # So funny characters don't show up in error messages. | 
 |         "-fno-color-diagnostics", | 
 |  | 
 |         # Always treat warnings as errors. | 
 |         "-Werror", | 
 |       ] | 
 |  | 
 |       if (!is_win) { | 
 |         args += [ | 
 |           # On non-Windows platforms, clang can generate the depfile. | 
 |           "-MMD", | 
 |           "-MF", | 
 |           rebased_depfile_path, | 
 |           "-MT", | 
 |           rebased_obj_path, | 
 |  | 
 |           # Non-Windows clang uses file extensions to determine how to treat | 
 |           # various inputs, so explicitly tell it to treat all inputs (even | 
 |           # those with weird extensions like .nc) as C++ source files. | 
 |           "-x", | 
 |           "c++", | 
 |         ] | 
 |       } else { | 
 |         # For some reason, the Windows includes are not part of the default | 
 |         # compiler configs. Set it explicitly here, since things like libc++ | 
 |         # depend on the VC runtime. | 
 |         if (target_cpu == "x86") { | 
 |           win_toolchain_data = win_toolchain_data_x86 | 
 |         } else if (target_cpu == "x64") { | 
 |           win_toolchain_data = win_toolchain_data_x64 | 
 |         } else if (target_cpu == "arm64") { | 
 |           win_toolchain_data = win_toolchain_data_arm64 | 
 |         } else { | 
 |           error("Unsupported target_cpu, add it to win_toolchain_data.gni") | 
 |         } | 
 |         args += win_toolchain_data.include_flags_imsvc_list | 
 |         args += [ | 
 |           "/showIncludes:user", | 
 |           "/TP", | 
 |         ] | 
 |       } | 
 |  | 
 |       # Note: for all platforms, the depfile only lists user includes, and not | 
 |       # system includes. If system includes change, the compiler flags are | 
 |       # expected to artificially change in some way to invalidate and force the | 
 |       # nocompile tests to run again. | 
 |     } | 
 |   } | 
 | } |