diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 64af4c84672fee..cb53804d9e4f87 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -657,4 +657,7 @@ def warn_drv_fjmc_for_elf_only : Warning< def err_drv_target_variant_invalid : Error< "unsupported '%0' value '%1'; use 'ios-macabi' instead">; +def err_drv_invalid_directx_shader_module : Error< + "invalid profile : %0">; + } diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 6f24f649ea5449..b33b64cd9e6a2a 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -68,7 +68,8 @@ class Driver { GXXMode, CPPMode, CLMode, - FlangMode + FlangMode, + DXCMode } Mode; enum SaveTempsMode { @@ -195,6 +196,9 @@ class Driver { /// Other modes fall back to calling gcc which in turn calls gfortran. bool IsFlangMode() const { return Mode == FlangMode; } + /// Whether the driver should follow dxc.exe like behavior. + bool IsDXCMode() const { return Mode == DXCMode; } + /// Only print tool bindings, don't build any jobs. unsigned CCCPrintBindings : 1; diff --git a/clang/include/clang/Driver/Options.h b/clang/include/clang/Driver/Options.h index 056660192ac5fa..f9b9632ee7cbe9 100644 --- a/clang/include/clang/Driver/Options.h +++ b/clang/include/clang/Driver/Options.h @@ -35,7 +35,8 @@ enum ClangFlags { FlangOption = (1 << 14), FC1Option = (1 << 15), FlangOnlyOption = (1 << 16), - Ignored = (1 << 17), + DXCOption = (1 << 17), + Ignored = (1 << 18), }; enum ID { diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 104c8ea8483d16..f454bd038ecf8c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -49,6 +49,10 @@ def CC1Option : OptionFlag; // CC1AsOption - This option should be accepted by clang -cc1as. def CC1AsOption : OptionFlag; +// DXCOption - This is a dxc.exe compatibility option. Options with this flag +// are made available when the driver is running in DXC compatibility mode. +def DXCOption : OptionFlag; + // NoDriverOption - This option should not be accepted by the driver. def NoDriverOption : OptionFlag; @@ -6686,3 +6690,33 @@ def _SLASH_Ze : CLFlag<"Ze">; def _SLASH_Zg : CLFlag<"Zg">; def _SLASH_ZI : CLFlag<"ZI">; def _SLASH_ZW : CLJoined<"ZW">; + +//===----------------------------------------------------------------------===// +// clang-dxc Options +//===----------------------------------------------------------------------===// + +def dxc_Group : OptionGroup<"">, Flags<[DXCOption]>, + HelpText<"dxc compatibility options">; + +class DXCJoinedOrSeparate : Option<["/", "-"], name, + KIND_JOINED_OR_SEPARATE>, Group, Flags<[DXCOption, NoXarchOption]>; + +def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>, + Group, Flags<[DXCOption, NoXarchOption]>, Alias, + HelpText<"Display available options">; + + +def Fo : DXCJoinedOrSeparate<"Fo">, Alias, + HelpText<"Output object file.">; + +def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"">, + HelpText<"Set target profile.">, + Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7," + "vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7," + "gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7," + "hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, hs_6_7," + "ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, ds_6_7," + "cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7," + "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x," + "ms_6_5, ms_6_6, ms_6_7," + "as_6_5, as_6_6, as_6_7">; diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index dc6d370810abb2..18c9b2d042f6c6 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -60,6 +60,7 @@ add_clang_library(clangDriver ToolChains/HIPAMD.cpp ToolChains/HIPSPV.cpp ToolChains/Hexagon.cpp + ToolChains/HLSL.cpp ToolChains/Hurd.cpp ToolChains/Linux.cpp ToolChains/MipsLinux.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 8de1a364092dcf..0095e87b6ba008 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -26,6 +26,7 @@ #include "ToolChains/Gnu.h" #include "ToolChains/HIPAMD.h" #include "ToolChains/HIPSPV.h" +#include "ToolChains/HLSL.h" #include "ToolChains/Haiku.h" #include "ToolChains/Hexagon.h" #include "ToolChains/Hurd.h" @@ -232,6 +233,7 @@ void Driver::setDriverMode(StringRef Value) { .Case("cpp", CPPMode) .Case("cl", CLMode) .Case("flang", FlangMode) + .Case("dxc", DXCMode) .Default(None)) Mode = *M; else @@ -1190,7 +1192,14 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { T.setEnvironment(llvm::Triple::MSVC); T.setObjectFormat(llvm::Triple::COFF); TargetTriple = T.str(); + } else if (IsDXCMode()) { + // clang-dxc target is build from target_profile option. + // Just set OS to shader model to select HLSLToolChain. + llvm::Triple T(TargetTriple); + T.setOS(llvm::Triple::ShaderModel); + TargetTriple = T.str(); } + if (const Arg *A = Args.getLastArg(options::OPT_target)) TargetTriple = A->getValue(); if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir)) @@ -5684,6 +5693,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::ZOS: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::ShaderModel: + TC = std::make_unique(*this, Target, Args); + break; default: // Of these targets, Hexagon is the only one that might have // an OS of Linux, in which case it got handled above already. @@ -5902,7 +5914,13 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const { } else { ExcludedFlagsBitmask |= options::CLOption; } - + if (IsDXCMode()) { + // Include DXC and Core options. + IncludedFlagsBitmask |= options::DXCOption; + IncludedFlagsBitmask |= options::CoreOption; + } else { + ExcludedFlagsBitmask |= options::DXCOption; + } return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask); } diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index f4415a30eb9d4c..d45a90048dcbed 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -153,6 +153,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) { {"cl", "--driver-mode=cl"}, {"++", "--driver-mode=g++"}, {"flang", "--driver-mode=flang"}, + {"clang-dxc", "--driver-mode=dxc"}, }; for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) { diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp new file mode 100644 index 00000000000000..a2a2a3a7bf552a --- /dev/null +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -0,0 +1,133 @@ +//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HLSL.h" +#include "CommonArgs.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; +using namespace llvm; + +namespace { + +const unsigned OfflineLibMinor = 0xF; + +bool isLegalShaderModel(Triple &T) { + if (T.getOS() != Triple::OSType::ShaderModel) + return false; + + auto Version = T.getOSVersion(); + if (Version.getBuild()) + return false; + if (Version.getSubminor()) + return false; + + auto Kind = T.getEnvironment(); + + switch (Kind) { + default: + return false; + case Triple::EnvironmentType::Vertex: + case Triple::EnvironmentType::Hull: + case Triple::EnvironmentType::Domain: + case Triple::EnvironmentType::Geometry: + case Triple::EnvironmentType::Pixel: + case Triple::EnvironmentType::Compute: { + VersionTuple MinVer(4, 0); + return MinVer <= Version; + } break; + case Triple::EnvironmentType::Library: { + VersionTuple SM6x(6, OfflineLibMinor); + if (Version == SM6x) + return true; + + VersionTuple MinVer(6, 3); + return MinVer <= Version; + } break; + case Triple::EnvironmentType::Amplification: + case Triple::EnvironmentType::Mesh: { + VersionTuple MinVer(6, 5); + return MinVer <= Version; + } break; + } + return false; +} + +std::string tryParseProfile(StringRef Profile) { + // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] + SmallVector Parts; + Profile.split(Parts, "_"); + if (Parts.size() != 3) + return ""; + + Triple::EnvironmentType Kind = + StringSwitch(Parts[0]) + .Case("ps", Triple::EnvironmentType::Pixel) + .Case("vs", Triple::EnvironmentType::Vertex) + .Case("gs", Triple::EnvironmentType::Geometry) + .Case("hs", Triple::EnvironmentType::Hull) + .Case("ds", Triple::EnvironmentType::Domain) + .Case("cs", Triple::EnvironmentType::Compute) + .Case("lib", Triple::EnvironmentType::Library) + .Case("ms", Triple::EnvironmentType::Mesh) + .Case("as", Triple::EnvironmentType::Amplification) + .Default(Triple::EnvironmentType::UnknownEnvironment); + if (Kind == Triple::EnvironmentType::UnknownEnvironment) + return ""; + + unsigned long long Major = 0; + if (llvm::getAsUnsignedInteger(Parts[1], 0, Major)) + return ""; + + unsigned long long Minor = 0; + if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library) + Minor = OfflineLibMinor; + else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor)) + return ""; + + // dxil-unknown-shadermodel-hull + llvm::Triple T; + T.setArch(Triple::ArchType::dxil); + T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() + + VersionTuple(Major, Minor).getAsString()); + T.setEnvironment(Kind); + if (isLegalShaderModel(T)) + return T.getTriple(); + else + return ""; +} + +} // namespace + +/// DirectX Toolchain +HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : ToolChain(D, Triple, Args) {} + +std::string +HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args, + types::ID InputType) const { + if (Arg *A = Args.getLastArg(options::OPT_target_profile)) { + StringRef Profile = A->getValue(); + std::string Triple = tryParseProfile(Profile); + if (Triple == "") { + getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile; + Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType); + } + A->claim(); + return Triple; + } else { + return ToolChain::ComputeEffectiveClangTriple(Args, InputType); + } +} diff --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h new file mode 100644 index 00000000000000..052003f53ae053 --- /dev/null +++ b/clang/lib/Driver/ToolChains/HLSL.h @@ -0,0 +1,37 @@ +//===--- HLSL.h - HLSL ToolChain Implementations ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H + +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain { +public: + HLSLToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + bool isPICDefault() const override { return false; } + bool isPIEDefault(const llvm::opt::ArgList &Args) const override { + return false; + } + bool isPICDefaultForced() const override { return false; } + + std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args, + types::ID InputType) const override; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index 8f6adc6c2ad1e0..befdc50faa9c50 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -332,6 +332,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) { .Case("c++m", TY_CXXModule) .Case("cppm", TY_CXXModule) .Case("cxxm", TY_CXXModule) + .Case("hlsl", TY_HLSL) .Default(TY_INVALID); } diff --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py index 44b26e7822714a..afc119cd4166d2 100644 --- a/clang/test/lit.cfg.py +++ b/clang/test/lit.cfg.py @@ -67,6 +67,8 @@ 'clang-tblgen', 'clang-scan-deps', 'opt', 'llvm-ifs', 'yaml2obj', ToolSubst('%clang_extdef_map', command=FindTool( 'clang-extdef-mapping'), unresolved='ignore'), + ToolSubst('%clang_dxc', command=config.clang, + extra_args=['--driver-mode=dxc']), ] if config.clang_examples: diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 286ad84e92d67c..3d9d266ef31612 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -300,6 +300,12 @@ TEST(ToolChainTest, GetTargetAndMode) { EXPECT_TRUE(Res.ModeSuffix == "clang-cl"); EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl"); EXPECT_FALSE(Res.TargetIsValid); + + Res = ToolChain::getTargetAndModeFromProgramName("clang-dxc"); + EXPECT_TRUE(Res.TargetPrefix.empty()); + EXPECT_TRUE(Res.ModeSuffix == "clang-dxc"); + EXPECT_STREQ(Res.DriverMode, "--driver-mode=dxc"); + EXPECT_FALSE(Res.TargetIsValid); } TEST(ToolChainTest, CommandOutput) { @@ -361,4 +367,141 @@ TEST(GetDriverMode, PrefersLastDriverMode) { EXPECT_EQ(getDriverMode(Args[0], llvm::makeArrayRef(Args).slice(1)), "bar"); } +TEST(DxcModeTest, TargetProfileValidation) { + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + struct SimpleDiagnosticConsumer : public DiagnosticConsumer { + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const Diagnostic &Info) override { + if (DiagLevel == DiagnosticsEngine::Level::Error) { + Errors.emplace_back(); + Info.FormatDiagnostic(Errors.back()); + } else { + Msgs.emplace_back(); + Info.FormatDiagnostic(Msgs.back()); + } + } + void clear() override { + Msgs.clear(); + Errors.clear(); + DiagnosticConsumer::clear(); + } + std::vector> Msgs; + std::vector> Errors; + }; + + IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + + InMemoryFileSystem->addFile("foo.hlsl", 0, + llvm::MemoryBuffer::getMemBuffer("\n")); + + auto *DiagConsumer = new SimpleDiagnosticConsumer; + IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer); + Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); + std::unique_ptr C( + TheDriver.BuildCompilation({"clang", "--driver-mode=dxc", "foo.hlsl"})); + EXPECT_TRUE(C); + EXPECT_TRUE(!C->containsError()); + + auto &TC = C->getDefaultToolChain(); + bool ContainsError = false; + auto Args = TheDriver.ParseArgStrings({"-Tvs_6_0"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + auto Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.0-vertex"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Ths_6_1"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.1-hull"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tgs_6_3"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.3-geometry"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tps_6_4"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.4-pixel"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tcs_6_5"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.5-compute"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tms_6_6"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.6-mesh"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tas_6_7"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.7-amplification"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + Args = TheDriver.ParseArgStrings({"-Tlib_6_x"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.15-library"); + EXPECT_EQ(Diags.getNumErrors(), 0u); + + // Invalid tests. + Args = TheDriver.ParseArgStrings({"-Tpss_6_1"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); + EXPECT_EQ(Diags.getNumErrors(), 1u); + EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : pss_6_1"); + Diags.Clear(); + DiagConsumer->clear(); + + Args = TheDriver.ParseArgStrings({"-Tps_6_x"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); + EXPECT_EQ(Diags.getNumErrors(), 2u); + EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : ps_6_x"); + Diags.Clear(); + DiagConsumer->clear(); + + Args = TheDriver.ParseArgStrings({"-Tlib_6_1"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); + EXPECT_EQ(Diags.getNumErrors(), 3u); + EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : lib_6_1"); + Diags.Clear(); + DiagConsumer->clear(); + + Args = TheDriver.ParseArgStrings({"-Tfoo"}, false, ContainsError); + EXPECT_FALSE(ContainsError); + Triple = TC.ComputeEffectiveClangTriple(Args); + EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel"); + EXPECT_EQ(Diags.getNumErrors(), 4u); + EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : foo"); + Diags.Clear(); + DiagConsumer->clear(); +} + } // end anonymous namespace.