1 //===- unittests/Serialization/NoComments.cpp - CI tests -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "clang/ASTMatchers/ASTMatchFinder.h" 10 #include "clang/ASTMatchers/ASTMatchers.h" 11 #include "clang/Basic/FileManager.h" 12 #include "clang/Frontend/CompilerInstance.h" 13 #include "clang/Frontend/CompilerInvocation.h" 14 #include "clang/Frontend/FrontendActions.h" 15 #include "clang/Frontend/Utils.h" 16 #include "clang/Lex/HeaderSearch.h" 17 #include "clang/Tooling/Tooling.h" 18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/Support/FileSystem.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 #include "gtest/gtest.h" 23 24 using namespace llvm; 25 using namespace clang; 26 27 namespace { 28 29 class NoComments : public ::testing::Test { 30 void SetUp() override { 31 ASSERT_FALSE( 32 sys::fs::createUniqueDirectory("modules-no-comments-test", TestDir)); 33 } 34 35 void TearDown() override { sys::fs::remove_directories(TestDir); } 36 37 public: 38 SmallString<256> TestDir; 39 40 void addFile(StringRef Path, StringRef Contents) { 41 ASSERT_FALSE(sys::path::is_absolute(Path)); 42 43 SmallString<256> AbsPath(TestDir); 44 sys::path::append(AbsPath, Path); 45 46 ASSERT_FALSE( 47 sys::fs::create_directories(llvm::sys::path::parent_path(AbsPath))); 48 49 std::error_code EC; 50 llvm::raw_fd_ostream OS(AbsPath, EC); 51 ASSERT_FALSE(EC); 52 OS << Contents; 53 } 54 }; 55 56 TEST_F(NoComments, NonModulesTest) { 57 std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs( 58 R"cpp( 59 /// Any comments 60 void foo() {} 61 )cpp", 62 /*Args=*/{"-std=c++20"}); 63 EXPECT_TRUE(AST); 64 65 ASTContext &Ctx = AST->getASTContext(); 66 67 using namespace clang::ast_matchers; 68 auto *foo = selectFirst<FunctionDecl>( 69 "foo", match(functionDecl(hasName("foo")).bind("foo"), Ctx)); 70 EXPECT_TRUE(foo); 71 72 const RawComment *RC = getCompletionComment(Ctx, foo); 73 EXPECT_TRUE(RC); 74 EXPECT_TRUE(RC->getRawText(Ctx.getSourceManager()).trim() == 75 "/// Any comments"); 76 } 77 78 TEST_F(NoComments, ModulesTest) { 79 addFile("Comments.cppm", R"cpp( 80 export module Comments; 81 82 /// Any comments 83 void foo() {} 84 )cpp"); 85 86 CreateInvocationOptions CIOpts; 87 CIOpts.VFS = llvm::vfs::createPhysicalFileSystem(); 88 IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 89 CompilerInstance::createDiagnostics(*CIOpts.VFS, new DiagnosticOptions()); 90 CIOpts.Diags = Diags; 91 92 std::string CacheBMIPath = llvm::Twine(TestDir + "/Comments.pcm").str(); 93 const char *Args[] = {"clang++", "-std=c++20", 94 "--precompile", "-working-directory", 95 TestDir.c_str(), "Comments.cppm"}; 96 std::shared_ptr<CompilerInvocation> Invocation = 97 createInvocation(Args, CIOpts); 98 ASSERT_TRUE(Invocation); 99 100 CompilerInstance Instance; 101 Instance.setDiagnostics(Diags.get()); 102 Instance.setInvocation(Invocation); 103 Instance.getFrontendOpts().OutputFile = CacheBMIPath; 104 GenerateReducedModuleInterfaceAction Action; 105 ASSERT_TRUE(Instance.ExecuteAction(Action)); 106 ASSERT_FALSE(Diags->hasErrorOccurred()); 107 108 std::string DepArg = 109 llvm::Twine("-fmodule-file=Comments=" + CacheBMIPath).str(); 110 std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs( 111 R"cpp( 112 import Comments; 113 )cpp", 114 /*Args=*/{"-std=c++20", DepArg.c_str()}); 115 EXPECT_TRUE(AST); 116 117 ASTContext &Ctx = AST->getASTContext(); 118 119 using namespace clang::ast_matchers; 120 auto *foo = selectFirst<FunctionDecl>( 121 "foo", match(functionDecl(hasName("foo")).bind("foo"), Ctx)); 122 EXPECT_TRUE(foo); 123 124 const RawComment *RC = getCompletionComment(Ctx, foo); 125 EXPECT_FALSE(RC); 126 } 127 128 } // anonymous namespace 129