1 //===- 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" 20 #include "clang/Frontend/ASTUnit.h" 21 #include "clang/AST/ASTImporterSharedState.h" 22 23 #include "DeclMatcher.h" 24 #include "Language.h" 25 26 namespace clang { 27 28 class ASTImporter; 29 class ASTImporterSharedState; 30 class ASTUnit; 31 32 namespace ast_matchers { 33 34 const StringRef DeclToImportID = "declToImport"; 35 const 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. 39 void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName, 40 std::unique_ptr<llvm::MemoryBuffer> &&Buffer); 41 42 void 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. 48 class CompilerOptionSpecificTest : public ::testing::Test { 49 protected: 50 // Return the extra arguments appended to runtime options at compilation. getExtraArgs()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. getArgVectorForLanguage(Language Lang)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 65 const 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. 73 class ASTImporterTestBase : public CompilerOptionSpecificTest { 74 75 const char *const InputFileName = "input.cc"; 76 const char *const OutputFileName = "output.cc"; 77 78 public: 79 /// Allocates an ASTImporter (or one of its subclasses). 80 typedef std::function<ASTImporter *( 81 ASTContext &, FileManager &, ASTContext &, FileManager &, bool, 82 const std::shared_ptr<ASTImporterSharedState> &SharedState)> 83 ImporterConstructor; 84 85 // The lambda that constructs the ASTImporter we use in this test. 86 ImporterConstructor Creator; 87 88 private: 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 107 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); 114 }; 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 125 // Initialize the shared state if not initialized already. 126 void lazyInitSharedState(TranslationUnitDecl *ToTU); 127 128 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName); 129 130 protected: 131 std::shared_ptr<ASTImporterSharedState> SharedStatePtr; 132 133 public: 134 // We may have several From context but only one To context. 135 std::unique_ptr<ASTUnit> ToAST; 136 137 // Returns with the TU associated with the given Decl. 138 TU *findFromTU(Decl *From); 139 140 // 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 Import(DeclT * From,Language Lang)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 170 class ASTImporterOptionSpecificTestBase 171 : public ASTImporterTestBase, 172 public ::testing::WithParamInterface<ArgVector> { 173 protected: getExtraArgs()174 ArgVector getExtraArgs() const override { return GetParam(); } 175 }; 176 177 } // end namespace ast_matchers 178 } // end namespace clang 179 180 #endif 181