|  | //===-- ModulesTests.cpp  ---------------------------------------*- 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 "Annotations.h" | 
|  | #include "TestFS.h" | 
|  | #include "TestTU.h" | 
|  | #include "gmock/gmock.h" | 
|  | #include "gtest/gtest.h" | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  |  | 
|  | namespace clang { | 
|  | namespace clangd { | 
|  | namespace { | 
|  |  | 
|  | TEST(Modules, TextualIncludeInPreamble) { | 
|  | TestTU TU = TestTU::withCode(R"cpp( | 
|  | #include "Textual.h" | 
|  |  | 
|  | void foo() {} | 
|  | )cpp"); | 
|  | TU.ExtraArgs.push_back("-fmodule-name=M"); | 
|  | TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap")); | 
|  | TU.AdditionalFiles["Textual.h"] = "void foo();"; | 
|  | TU.AdditionalFiles["m.modulemap"] = R"modulemap( | 
|  | module M { | 
|  | module Textual { | 
|  | textual header "Textual.h" | 
|  | } | 
|  | } | 
|  | )modulemap"; | 
|  | // Test that we do not crash. | 
|  | TU.index(); | 
|  | } | 
|  |  | 
|  | // Verify that visibility of AST nodes belonging to modules, but loaded from | 
|  | // preamble PCH, is restored. | 
|  | TEST(Modules, PreambleBuildVisibility) { | 
|  | TestTU TU = TestTU::withCode(R"cpp( | 
|  | #include "module.h" | 
|  |  | 
|  | foo x; | 
|  | )cpp"); | 
|  | TU.OverlayRealFileSystemForModules = true; | 
|  | TU.ExtraArgs.push_back("-fmodules"); | 
|  | TU.ExtraArgs.push_back("-fmodules-strict-decluse"); | 
|  | TU.ExtraArgs.push_back("-Xclang"); | 
|  | TU.ExtraArgs.push_back("-fmodules-local-submodule-visibility"); | 
|  | TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap")); | 
|  | TU.AdditionalFiles["module.h"] = R"cpp( | 
|  | typedef int foo; | 
|  | )cpp"; | 
|  | TU.AdditionalFiles["m.modulemap"] = R"modulemap( | 
|  | module M { | 
|  | header "module.h" | 
|  | } | 
|  | )modulemap"; | 
|  | EXPECT_TRUE(TU.build().getDiagnostics()->empty()); | 
|  | } | 
|  |  | 
|  | TEST(Modules, Diagnostic) { | 
|  | // Produce a diagnostic while building an implicit module. Use | 
|  | // -fmodules-strict-decluse, but any non-silenced diagnostic will do. | 
|  | TestTU TU = TestTU::withCode(R"cpp( | 
|  | /*error-ok*/ | 
|  | #include "modular.h" | 
|  |  | 
|  | void bar() {} | 
|  | )cpp"); | 
|  | TU.OverlayRealFileSystemForModules = true; | 
|  | TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap")); | 
|  | TU.ExtraArgs.push_back("-fmodules"); | 
|  | TU.ExtraArgs.push_back("-fimplicit-modules"); | 
|  | TU.ExtraArgs.push_back("-fmodules-strict-decluse"); | 
|  | TU.AdditionalFiles["modular.h"] = R"cpp( | 
|  | #include "non-modular.h" | 
|  | )cpp"; | 
|  | TU.AdditionalFiles["non-modular.h"] = ""; | 
|  | TU.AdditionalFiles["m.modulemap"] = R"modulemap( | 
|  | module M { | 
|  | header "modular.h" | 
|  | } | 
|  | )modulemap"; | 
|  |  | 
|  | // Test that we do not crash. | 
|  | TU.build(); | 
|  | } | 
|  |  | 
|  | // Unknown module formats are a fatal failure for clang. Ensure we don't crash. | 
|  | TEST(Modules, UnknownFormat) { | 
|  | TestTU TU = TestTU::withCode(R"(#include "modular.h")"); | 
|  | TU.OverlayRealFileSystemForModules = true; | 
|  | TU.ExtraArgs.push_back("-Xclang"); | 
|  | TU.ExtraArgs.push_back("-fmodule-format=obj"); | 
|  | TU.ExtraArgs.push_back("-fmodule-map-file=" + testPath("m.modulemap")); | 
|  | TU.ExtraArgs.push_back("-fmodules"); | 
|  | TU.ExtraArgs.push_back("-fimplicit-modules"); | 
|  | TU.AdditionalFiles["modular.h"] = ""; | 
|  | TU.AdditionalFiles["m.modulemap"] = R"modulemap( | 
|  | module M { | 
|  | header "modular.h" | 
|  | })modulemap"; | 
|  |  | 
|  | // Test that we do not crash. | 
|  | TU.build(); | 
|  | } | 
|  | } // namespace | 
|  | } // namespace clangd | 
|  | } // namespace clang |