1 //===- unittests/Frontend/ASTUnitTest.cpp - ASTUnit 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 <fstream>
10 
11 #include "clang/Frontend/ASTUnit.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Frontend/CompilerInvocation.h"
14 #include "clang/Frontend/PCHContainerOperations.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/Path.h"
17 #include "llvm/Support/ToolOutputFile.h"
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 using namespace clang;
22 
23 namespace {
24 
25 class ASTUnitTest : public ::testing::Test {
26 protected:
27   int FD;
28   llvm::SmallString<256> InputFileName;
29   std::unique_ptr<ToolOutputFile> input_file;
30   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
31   std::shared_ptr<CompilerInvocation> CInvok;
32   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
33 
34   std::unique_ptr<ASTUnit> createASTUnit(bool isVolatile) {
35     EXPECT_FALSE(llvm::sys::fs::createTemporaryFile("ast-unit", "cpp", FD,
36                                                     InputFileName));
37     input_file = std::make_unique<ToolOutputFile>(InputFileName, FD);
38     input_file->os() << "";
39 
40     const char *Args[] = {"clang", "-xc++", InputFileName.c_str()};
41 
42     Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
43 
44     CInvok = createInvocationFromCommandLine(Args, Diags);
45 
46     if (!CInvok)
47       return nullptr;
48 
49     FileManager *FileMgr =
50         new FileManager(FileSystemOptions(), vfs::getRealFileSystem());
51     PCHContainerOps = std::make_shared<PCHContainerOperations>();
52 
53     return ASTUnit::LoadFromCompilerInvocation(
54         CInvok, PCHContainerOps, Diags, FileMgr, false, CaptureDiagsKind::None,
55         0, TU_Complete, false, false, isVolatile);
56   }
57 };
58 
59 TEST_F(ASTUnitTest, SaveLoadPreservesLangOptionsInPrintingPolicy) {
60   // Check that the printing policy is restored with the correct language
61   // options when loading an ASTUnit from a file.  To this end, an ASTUnit
62   // for a C++ translation unit is set up and written to a temporary file.
63 
64   // By default `UseVoidForZeroParams` is true for non-C++ language options,
65   // thus we can check this field after loading the ASTUnit to deduce whether
66   // the correct (C++) language options were used when setting up the printing
67   // policy.
68 
69   {
70     PrintingPolicy PolicyWithDefaultLangOpt(LangOptions{});
71     EXPECT_TRUE(PolicyWithDefaultLangOpt.UseVoidForZeroParams);
72   }
73 
74   std::unique_ptr<ASTUnit> AST = createASTUnit(false);
75 
76   if (!AST)
77     FAIL() << "failed to create ASTUnit";
78 
79   EXPECT_FALSE(AST->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
80 
81   llvm::SmallString<256> ASTFileName;
82   ASSERT_FALSE(
83       llvm::sys::fs::createTemporaryFile("ast-unit", "ast", FD, ASTFileName));
84   ToolOutputFile ast_file(ASTFileName, FD);
85   AST->Save(ASTFileName.str());
86 
87   EXPECT_TRUE(llvm::sys::fs::exists(ASTFileName));
88 
89   std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
90       ASTFileName.str(), PCHContainerOps->getRawReader(),
91       ASTUnit::LoadEverything, Diags, FileSystemOptions(),
92       /*UseDebugInfo=*/false);
93 
94   if (!AU)
95     FAIL() << "failed to load ASTUnit";
96 
97   EXPECT_FALSE(AU->getASTContext().getPrintingPolicy().UseVoidForZeroParams);
98 }
99 
100 TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) {
101   std::unique_ptr<ASTUnit> AST = createASTUnit(true);
102 
103   if (!AST)
104     FAIL() << "failed to create ASTUnit";
105 
106   std::unique_ptr<llvm::MemoryBuffer> memoryBuffer =
107       AST->getBufferForFile(InputFileName);
108 
109   EXPECT_NE(memoryBuffer->getBufferKind(),
110             llvm::MemoryBuffer::MemoryBuffer_MMap);
111 }
112 
113 } // anonymous namespace
114