blob: 4b67a9435f1fd5d6d661184c9840b5b29c85d886 [file] [log] [blame]
Gabor Marton3c72fe12019-05-13 10:06:25 +00001//===- unittest/AST/ASTImporterFixtures.h - AST unit test support ---------===//
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/// \file
10/// Fixture classes for testing the ASTImporter.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_UNITTESTS_AST_IMPORTER_FIXTURES_H
15#define LLVM_CLANG_UNITTESTS_AST_IMPORTER_FIXTURES_H
16
17#include "gmock/gmock.h"
18
19#include "clang/AST/ASTImporter.h"
Gabor Marton3c72fe12019-05-13 10:06:25 +000020#include "clang/Frontend/ASTUnit.h"
Gabor Marton2afbfb62019-07-01 15:37:07 +000021#include "clang/AST/ASTImporterSharedState.h"
Gabor Marton3c72fe12019-05-13 10:06:25 +000022
23#include "DeclMatcher.h"
24#include "Language.h"
25
26namespace clang {
27
28class ASTImporter;
Gabor Marton2afbfb62019-07-01 15:37:07 +000029class ASTImporterSharedState;
Gabor Marton3c72fe12019-05-13 10:06:25 +000030class ASTUnit;
31
32namespace ast_matchers {
33
34const StringRef DeclToImportID = "declToImport";
35const StringRef DeclToVerifyID = "declToVerify";
36
37// Creates a virtual file and assigns that to the context of given AST. If the
38// file already exists then the file will not be created again as a duplicate.
39void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
40 std::unique_ptr<llvm::MemoryBuffer> &&Buffer);
41
42void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
43 StringRef Code);
44
45// Common base for the different families of ASTImporter tests that are
46// parameterized on the compiler options which may result a different AST. E.g.
47// -fms-compatibility or -fdelayed-template-parsing.
48class CompilerOptionSpecificTest : public ::testing::Test {
49protected:
50 // Return the extra arguments appended to runtime options at compilation.
51 virtual ArgVector getExtraArgs() const { return ArgVector(); }
52
53 // Returns the argument vector used for a specific language option, this set
54 // can be tweaked by the test parameters.
55 ArgVector getArgVectorForLanguage(Language Lang) const {
56 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
57 ArgVector ExtraArgs = getExtraArgs();
58 for (const auto &Arg : ExtraArgs) {
59 Args.push_back(Arg);
60 }
61 return Args;
62 }
63};
64
65const auto DefaultTestValuesForRunOptions = ::testing::Values(
66 ArgVector(), ArgVector{"-fdelayed-template-parsing"},
67 ArgVector{"-fms-compatibility"},
68 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
69
70// This class provides generic methods to write tests which can check internal
71// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
72// this fixture makes it possible to import from several "From" contexts.
73class ASTImporterTestBase : public CompilerOptionSpecificTest {
74
75 const char *const InputFileName = "input.cc";
76 const char *const OutputFileName = "output.cc";
77
78public:
79 /// Allocates an ASTImporter (or one of its subclasses).
Gabor Marton2afbfb62019-07-01 15:37:07 +000080 typedef std::function<ASTImporter *(
81 ASTContext &, FileManager &, ASTContext &, FileManager &, bool,
82 const std::shared_ptr<ASTImporterSharedState> &SharedState)>
Gabor Marton3c72fe12019-05-13 10:06:25 +000083 ImporterConstructor;
84
85 // The lambda that constructs the ASTImporter we use in this test.
86 ImporterConstructor Creator;
87
88private:
89 // Buffer for the To context, must live in the test scope.
90 std::string ToCode;
91
92 // Represents a "From" translation unit and holds an importer object which we
93 // use to import from this translation unit.
94 struct TU {
95 // Buffer for the context, must live in the test scope.
96 std::string Code;
97 std::string FileName;
98 std::unique_ptr<ASTUnit> Unit;
99 TranslationUnitDecl *TUDecl = nullptr;
100 std::unique_ptr<ASTImporter> Importer;
101 ImporterConstructor Creator;
102
103 TU(StringRef Code, StringRef FileName, ArgVector Args,
104 ImporterConstructor C = ImporterConstructor());
105 ~TU();
106
Gabor Marton2afbfb62019-07-01 15:37:07 +0000107 void
108 lazyInitImporter(const std::shared_ptr<ASTImporterSharedState> &SharedState,
109 ASTUnit *ToAST);
110 Decl *import(const std::shared_ptr<ASTImporterSharedState> &SharedState,
111 ASTUnit *ToAST, Decl *FromDecl);
112 QualType import(const std::shared_ptr<ASTImporterSharedState> &SharedState,
113 ASTUnit *ToAST, QualType FromType);
Gabor Marton3c72fe12019-05-13 10:06:25 +0000114 };
115
116 // We may have several From contexts and related translation units. In each
117 // AST, the buffers for the source are handled via references and are set
118 // during the creation of the AST. These references must point to a valid
119 // buffer until the AST is alive. Thus, we must use a list in order to avoid
120 // moving of the stored objects because that would mean breaking the
121 // references in the AST. By using a vector a move could happen when the
122 // vector is expanding, with the list we won't have these issues.
123 std::list<TU> FromTUs;
124
Gabor Marton2afbfb62019-07-01 15:37:07 +0000125 // Initialize the shared state if not initialized already.
126 void lazyInitSharedState(TranslationUnitDecl *ToTU);
Gabor Marton3c72fe12019-05-13 10:06:25 +0000127
128 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName);
Gabor Marton3c72fe12019-05-13 10:06:25 +0000129
130protected:
Gabor Marton2afbfb62019-07-01 15:37:07 +0000131 std::shared_ptr<ASTImporterSharedState> SharedStatePtr;
Gabor Marton3c72fe12019-05-13 10:06:25 +0000132
133public:
134 // We may have several From context but only one To context.
135 std::unique_ptr<ASTUnit> ToAST;
136
Gabor Marton303c98612019-06-25 08:00:51 +0000137 // Returns with the TU associated with the given Decl.
138 TU *findFromTU(Decl *From);
139
Gabor Marton3c72fe12019-05-13 10:06:25 +0000140 // Creates an AST both for the From and To source code and imports the Decl
141 // of the identifier into the To context.
142 // Must not be called more than once within the same test.
143 std::tuple<Decl *, Decl *>
144 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
145 Language ToLang, StringRef Identifier = DeclToImportID);
146
147 // Creates a TU decl for the given source code which can be used as a From
148 // context. May be called several times in a given test (with different file
149 // name).
150 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
151 StringRef FileName = "input.cc");
152
153 // Creates the To context with the given source code and returns the TU decl.
154 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang);
155
156 // Import the given Decl into the ToCtx.
157 // May be called several times in a given test.
158 // The different instances of the param From may have different ASTContext.
159 Decl *Import(Decl *From, Language ToLang);
160
161 template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
162 return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
163 }
164
165 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang);
166
167 ~ASTImporterTestBase();
168};
169
170class ASTImporterOptionSpecificTestBase
171 : public ASTImporterTestBase,
172 public ::testing::WithParamInterface<ArgVector> {
173protected:
174 ArgVector getExtraArgs() const override { return GetParam(); }
175};
176
177} // end namespace ast_matchers
178} // end namespace clang
179
180#endif