blob: aaadeb0b9d6bce2c2816d0d0b6fb227f3f0331be [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for the correct import of AST nodes from one AST context to another.
11//
12//===----------------------------------------------------------------------===//
13
Gabor Marton7df342a2018-12-17 12:42:12 +000014#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000015#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000016#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000017#include "clang/AST/DeclContextInternals.h"
Gabor Marton54058b52018-12-17 13:53:12 +000018#include "clang/AST/ASTImporter.h"
19#include "clang/AST/ASTImporterLookupTable.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000020#include "clang/ASTMatchers/ASTMatchFinder.h"
21#include "clang/ASTMatchers/ASTMatchers.h"
22#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000023
24#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000025#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000026#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000027#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000028
29namespace clang {
30namespace ast_matchers {
31
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000032using internal::Matcher;
33using internal::BindableMatcher;
34using llvm::StringMap;
35
Peter Szecsidedda6f2018-03-30 22:03:29 +000036// Creates a virtual file and assigns that to the context of given AST. If the
37// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000038static void
39createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
40 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000041 assert(ToAST);
42 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000043 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000044 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
Jonas Devliegherefc514902018-10-10 13:27:25 +000045 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
46 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000048}
49
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000050static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
51 StringRef Code) {
52 return createVirtualFileIfNeeded(ToAST, FileName,
53 llvm::MemoryBuffer::getMemBuffer(Code));
54}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000055
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000056const StringRef DeclToImportID = "declToImport";
57const StringRef DeclToVerifyID = "declToVerify";
58
Gabor Marton19f4f392018-06-25 13:04:37 +000059// Common base for the different families of ASTImporter tests that are
60// parameterized on the compiler options which may result a different AST. E.g.
61// -fms-compatibility or -fdelayed-template-parsing.
62struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000063
Gabor Marton19f4f392018-06-25 13:04:37 +000064 // Returns the argument vector used for a specific language option, this set
65 // can be tweaked by the test parameters.
66 ArgVector getArgVectorForLanguage(Language Lang) const {
67 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
68 ArgVector ExtraArgs = GetParam();
69 for (const auto &Arg : ExtraArgs) {
70 Args.push_back(Arg);
71 }
72 return Args;
73 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000074
Gabor Marton19f4f392018-06-25 13:04:37 +000075};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000076
Gabor Marton19f4f392018-06-25 13:04:37 +000077// Base class for those tests which use the family of `testImport` functions.
78class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000079
Gabor Marton19f4f392018-06-25 13:04:37 +000080 template <typename NodeType>
81 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
82 NodeType Node) {
83 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000084
Gabor Marton19f4f392018-06-25 13:04:37 +000085 // Add 'From' file to virtual file system so importer can 'find' it
86 // while importing SourceLocations. It is safe to add same file multiple
87 // times - it just isn't replaced.
88 StringRef FromFileName = From->getMainFileName();
89 createVirtualFileIfNeeded(To, FromFileName,
90 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000091
Gabor Marton19f4f392018-06-25 13:04:37 +000092 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000093
Gabor Marton19f4f392018-06-25 13:04:37 +000094 // This should dump source locations and assert if some source locations
95 // were not imported.
96 SmallString<1024> ImportChecker;
97 llvm::raw_svector_ostream ToNothing(ImportChecker);
98 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000099
Gabor Marton19f4f392018-06-25 13:04:37 +0000100 // This traverses the AST to catch certain bugs like poorly or not
101 // implemented subtrees.
102 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000103
Gabor Marton19f4f392018-06-25 13:04:37 +0000104 return Imported;
105 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000106
Gabor Marton19f4f392018-06-25 13:04:37 +0000107 template <typename NodeType>
108 testing::AssertionResult
109 testImport(const std::string &FromCode, const ArgVector &FromArgs,
110 const std::string &ToCode, const ArgVector &ToArgs,
111 MatchVerifier<NodeType> &Verifier,
112 const BindableMatcher<NodeType> &SearchMatcher,
113 const BindableMatcher<NodeType> &VerificationMatcher) {
114 const char *const InputFileName = "input.cc";
115 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000116
Gabor Marton19f4f392018-06-25 13:04:37 +0000117 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
118 FromCode, FromArgs, InputFileName),
119 ToAST = tooling::buildASTFromCodeWithArgs(
120 ToCode, ToArgs, OutputFileName);
121
122 ASTContext &FromCtx = FromAST->getASTContext(),
123 &ToCtx = ToAST->getASTContext();
124
125 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
126 FromAST->getFileManager(), false);
127
128 auto FoundNodes = match(SearchMatcher, FromCtx);
129 if (FoundNodes.size() != 1)
130 return testing::AssertionFailure()
131 << "Multiple potential nodes were found!";
132
133 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
134 if (!ToImport)
135 return testing::AssertionFailure() << "Node type mismatch!";
136
137 // Sanity check: the node being imported should match in the same way as
138 // the result node.
139 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
140 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
141
142 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
143 if (!Imported)
144 return testing::AssertionFailure() << "Import failed, nullptr returned!";
145
Bill Wendling8003edc2018-11-09 00:41:36 +0000146
Gabor Marton19f4f392018-06-25 13:04:37 +0000147 return Verifier.match(Imported, WrapperMatcher);
148 }
149
150 template <typename NodeType>
151 testing::AssertionResult
152 testImport(const std::string &FromCode, const ArgVector &FromArgs,
153 const std::string &ToCode, const ArgVector &ToArgs,
154 MatchVerifier<NodeType> &Verifier,
155 const BindableMatcher<NodeType> &VerificationMatcher) {
156 return testImport(
157 FromCode, FromArgs, ToCode, ToArgs, Verifier,
158 translationUnitDecl(
159 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
160 VerificationMatcher);
161 }
162
163public:
164
165 /// Test how AST node named "declToImport" located in the translation unit
166 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
167 /// The verification is done by running AMatcher over the imported node.
168 template <typename NodeType, typename MatcherType>
169 void testImport(const std::string &FromCode, Language FromLang,
170 const std::string &ToCode, Language ToLang,
171 MatchVerifier<NodeType> &Verifier,
172 const MatcherType &AMatcher) {
173 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
174 ToArgs = getArgVectorForLanguage(ToLang);
175 EXPECT_TRUE(
176 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
177 }
178
179 struct ImportAction {
180 StringRef FromFilename;
181 StringRef ToFilename;
182 // FIXME: Generalize this to support other node kinds.
183 BindableMatcher<Decl> ImportPredicate;
184
185 ImportAction(StringRef FromFilename, StringRef ToFilename,
186 DeclarationMatcher ImportPredicate)
187 : FromFilename(FromFilename), ToFilename(ToFilename),
188 ImportPredicate(ImportPredicate) {}
189
190 ImportAction(StringRef FromFilename, StringRef ToFilename,
191 const std::string &DeclName)
192 : FromFilename(FromFilename), ToFilename(ToFilename),
193 ImportPredicate(namedDecl(hasName(DeclName))) {}
194 };
195
196 using SingleASTUnit = std::unique_ptr<ASTUnit>;
197 using AllASTUnits = StringMap<SingleASTUnit>;
198
199 struct CodeEntry {
200 std::string CodeSample;
201 Language Lang;
202 };
203
204 using CodeFiles = StringMap<CodeEntry>;
205
206 /// Builds an ASTUnit for one potential compile options set.
207 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
208 ArgVector Args = getArgVectorForLanguage(CE.Lang);
209 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
210 EXPECT_TRUE(AST.get());
211 return AST;
212 }
213
214 /// Test an arbitrary sequence of imports for a set of given in-memory files.
215 /// The verification is done by running VerificationMatcher against a
216 /// specified AST node inside of one of given files.
217 /// \param CodeSamples Map whose key is the file name and the value is the
218 /// file content.
219 /// \param ImportActions Sequence of imports. Each import in sequence
220 /// specifies "from file" and "to file" and a matcher that is used for
221 /// searching a declaration for import in "from file".
222 /// \param FileForFinalCheck Name of virtual file for which the final check is
223 /// applied.
224 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
225 /// FileForFinalCheck for which the verification will be done.
226 /// \param VerificationMatcher Matcher that will be used for verification
227 /// after all imports in sequence are done.
228 void testImportSequence(const CodeFiles &CodeSamples,
229 const std::vector<ImportAction> &ImportActions,
230 StringRef FileForFinalCheck,
231 BindableMatcher<Decl> FinalSelectPredicate,
232 BindableMatcher<Decl> VerificationMatcher) {
233 AllASTUnits AllASTs;
234 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
235 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
236
237 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
238 if (!AllASTs.count(Filename)) {
239 auto Found = CodeSamples.find(Filename);
240 assert(Found != CodeSamples.end() && "Wrong file for import!");
241 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
242 }
243 };
244
245 for (const ImportAction &Action : ImportActions) {
246 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
247 GenASTsIfNeeded(FromFile);
248 GenASTsIfNeeded(ToFile);
249
250 ASTUnit *From = AllASTs[FromFile].get();
251 ASTUnit *To = AllASTs[ToFile].get();
252
253 // Create a new importer if needed.
254 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
255 if (!ImporterRef)
256 ImporterRef.reset(new ASTImporter(
257 To->getASTContext(), To->getFileManager(), From->getASTContext(),
258 From->getFileManager(), false));
259
260 // Find the declaration and import it.
261 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
262 From->getASTContext());
263 EXPECT_TRUE(FoundDecl.size() == 1);
264 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
265 auto Imported = importNode(From, To, *ImporterRef, ToImport);
266 EXPECT_TRUE(Imported);
267 }
268
269 // Find the declaration and import it.
270 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
271 AllASTs[FileForFinalCheck]->getASTContext());
272 EXPECT_TRUE(FoundDecl.size() == 1);
273 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
274 MatchVerifier<Decl> Verifier;
275 EXPECT_TRUE(
276 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
277 }
278};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000279
Gabor Martonf086fa82018-07-17 12:06:36 +0000280template <typename T> RecordDecl *getRecordDecl(T *D) {
281 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
282 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000283}
Gabor Martonf086fa82018-07-17 12:06:36 +0000284
Peter Szecsidedda6f2018-03-30 22:03:29 +0000285// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000286// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000287// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000288class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000289
290 const char *const InputFileName = "input.cc";
291 const char *const OutputFileName = "output.cc";
292
293 // Buffer for the To context, must live in the test scope.
294 std::string ToCode;
295
Gabor Marton26f72a92018-07-12 09:42:05 +0000296 // Represents a "From" translation unit and holds an importer object which we
297 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000298 struct TU {
299 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000300 std::string Code;
301 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000302 std::unique_ptr<ASTUnit> Unit;
303 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000304 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000305 TU(StringRef Code, StringRef FileName, ArgVector Args)
306 : Code(Code), FileName(FileName),
307 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
308 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000309 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
310 Unit->enableSourceFileDiagnostics();
311 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000312
Gabor Marton54058b52018-12-17 13:53:12 +0000313 void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000314 assert(ToAST);
315 if (!Importer) {
Gabor Marton54058b52018-12-17 13:53:12 +0000316 Importer.reset(
317 new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
318 Unit->getASTContext(), Unit->getFileManager(),
319 false, &LookupTable));
Gabor Marton26f72a92018-07-12 09:42:05 +0000320 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000321 assert(&ToAST->getASTContext() == &Importer->getToContext());
322 createVirtualFileIfNeeded(ToAST, FileName, Code);
323 }
324
Gabor Marton54058b52018-12-17 13:53:12 +0000325 Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
326 Decl *FromDecl) {
327 lazyInitImporter(LookupTable, ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000328 return Importer->Import(FromDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000329 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000330
Gabor Marton54058b52018-12-17 13:53:12 +0000331 QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
332 QualType FromType) {
333 lazyInitImporter(LookupTable, ToAST);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000334 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000335 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000336 };
337
338 // We may have several From contexts and related translation units. In each
339 // AST, the buffers for the source are handled via references and are set
340 // during the creation of the AST. These references must point to a valid
341 // buffer until the AST is alive. Thus, we must use a list in order to avoid
342 // moving of the stored objects because that would mean breaking the
343 // references in the AST. By using a vector a move could happen when the
344 // vector is expanding, with the list we won't have these issues.
345 std::list<TU> FromTUs;
346
Gabor Marton54058b52018-12-17 13:53:12 +0000347 // Initialize the lookup table if not initialized already.
348 void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
349 assert(ToTU);
350 if (!LookupTablePtr)
351 LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
352 }
353
354 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000355 if (ToAST)
356 return;
357 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton54058b52018-12-17 13:53:12 +0000358 // Source code must be a valid live buffer through the tests lifetime.
359 ToCode = ToSrcCode;
Gabor Marton6e1510c2018-07-12 11:50:21 +0000360 // Build the AST from an empty file.
Gabor Marton54058b52018-12-17 13:53:12 +0000361 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000362 ToAST->enableSourceFileDiagnostics();
Gabor Marton54058b52018-12-17 13:53:12 +0000363 lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
Gabor Marton6e1510c2018-07-12 11:50:21 +0000364 }
365
366 TU *findFromTU(Decl *From) {
367 // Create a virtual file in the To Ctx which corresponds to the file from
368 // which we want to import the `From` Decl. Without this source locations
369 // will be invalid in the ToCtx.
370 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
371 return E.TUDecl == From->getTranslationUnitDecl();
372 });
373 assert(It != FromTUs.end());
374 return &*It;
375 }
376
Gabor Marton54058b52018-12-17 13:53:12 +0000377protected:
378
379 std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
380
Peter Szecsidedda6f2018-03-30 22:03:29 +0000381public:
382 // We may have several From context but only one To context.
383 std::unique_ptr<ASTUnit> ToAST;
384
Peter Szecsidedda6f2018-03-30 22:03:29 +0000385 // Creates an AST both for the From and To source code and imports the Decl
386 // of the identifier into the To context.
387 // Must not be called more than once within the same test.
388 std::tuple<Decl *, Decl *>
389 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
390 Language ToLang, StringRef Identifier = DeclToImportID) {
391 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
392 ToArgs = getArgVectorForLanguage(ToLang);
393
394 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
395 TU &FromTU = FromTUs.back();
396
Peter Szecsidedda6f2018-03-30 22:03:29 +0000397 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000398 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000399
Gabor Marton26f72a92018-07-12 09:42:05 +0000400 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000401
Peter Szecsidedda6f2018-03-30 22:03:29 +0000402 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
403 assert(ImportedII && "Declaration with the given identifier "
404 "should be specified in test!");
405 DeclarationName ImportDeclName(ImportedII);
Gabor Marton54058b52018-12-17 13:53:12 +0000406 SmallVector<NamedDecl *, 1> FoundDecls;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000407 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
408 FoundDecls);
409
410 assert(FoundDecls.size() == 1);
411
Gabor Marton54058b52018-12-17 13:53:12 +0000412 Decl *Imported =
413 FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
Gabor Marton26f72a92018-07-12 09:42:05 +0000414
Peter Szecsidedda6f2018-03-30 22:03:29 +0000415 assert(Imported);
416 return std::make_tuple(*FoundDecls.begin(), Imported);
417 }
418
Gabor Marton9581c332018-05-23 13:53:36 +0000419 // Creates a TU decl for the given source code which can be used as a From
420 // context. May be called several times in a given test (with different file
421 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000422 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
423 StringRef FileName = "input.cc") {
424 assert(
425 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
426 return E.FileName == FileName;
427 }) == FromTUs.end());
428
429 ArgVector Args = getArgVectorForLanguage(Lang);
430 FromTUs.emplace_back(SrcCode, FileName, Args);
431 TU &Tu = FromTUs.back();
432
433 return Tu.TUDecl;
434 }
435
Gabor Marton9581c332018-05-23 13:53:36 +0000436 // Creates the To context with the given source code and returns the TU decl.
437 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
438 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000439 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000440 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000441 return ToAST->getASTContext().getTranslationUnitDecl();
442 }
443
Peter Szecsidedda6f2018-03-30 22:03:29 +0000444 // Import the given Decl into the ToCtx.
445 // May be called several times in a given test.
446 // The different instances of the param From may have different ASTContext.
447 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000448 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000449 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000450 assert(LookupTablePtr);
451 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000452 }
453
Gabor Marton6e1510c2018-07-12 11:50:21 +0000454 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000455 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000456 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000457 assert(LookupTablePtr);
458 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000459 }
460
Peter Szecsidedda6f2018-03-30 22:03:29 +0000461 ~ASTImporterTestBase() {
462 if (!::testing::Test::HasFailure()) return;
463
464 for (auto &Tu : FromTUs) {
465 assert(Tu.Unit);
466 llvm::errs() << "FromAST:\n";
467 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
468 llvm::errs() << "\n";
469 }
470 if (ToAST) {
471 llvm::errs() << "ToAST:\n";
472 ToAST->getASTContext().getTranslationUnitDecl()->dump();
473 }
474 }
475};
476
Gabor Marton19f4f392018-06-25 13:04:37 +0000477struct ImportExpr : TestImportBase {};
478struct ImportType : TestImportBase {};
479struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000480
Gabor Marton5254e642018-06-27 13:32:50 +0000481struct CanonicalRedeclChain : ASTImporterTestBase {};
482
483TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
484 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
485 auto Pattern = functionDecl(hasName("f"));
486 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
487
488 auto Redecls = getCanonicalForwardRedeclChain(D0);
489 ASSERT_EQ(Redecls.size(), 1u);
490 EXPECT_EQ(D0, Redecls[0]);
491}
492
493TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
494 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
495 auto Pattern = functionDecl(hasName("f"));
496 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
497 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
498 FunctionDecl *D1 = D2->getPreviousDecl();
499
500 auto Redecls = getCanonicalForwardRedeclChain(D0);
501 ASSERT_EQ(Redecls.size(), 3u);
502 EXPECT_EQ(D0, Redecls[0]);
503 EXPECT_EQ(D1, Redecls[1]);
504 EXPECT_EQ(D2, Redecls[2]);
505}
506
507TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
508 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
509 auto Pattern = functionDecl(hasName("f"));
510 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
511 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
512 FunctionDecl *D1 = D2->getPreviousDecl();
513
514 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
515 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
516 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
517
518 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
519 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
520}
521
Gabor Marton19f4f392018-06-25 13:04:37 +0000522TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000523 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000524 testImport(
525 "void declToImport() { (void)\"foo\"; }",
526 Lang_CXX, "", Lang_CXX, Verifier,
527 functionDecl(hasDescendant(
528 stringLiteral(hasType(asString("const char [4]"))))));
529 testImport(
530 "void declToImport() { (void)L\"foo\"; }",
531 Lang_CXX, "", Lang_CXX, Verifier,
532 functionDecl(hasDescendant(
533 stringLiteral(hasType(asString("const wchar_t [4]"))))));
534 testImport(
535 "void declToImport() { (void) \"foo\" \"bar\"; }",
536 Lang_CXX, "", Lang_CXX, Verifier,
537 functionDecl(hasDescendant(
538 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000539}
540
Gabor Marton19f4f392018-06-25 13:04:37 +0000541TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000542 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000543 testImport(
544 "void declToImport() { (void)__null; }",
545 Lang_CXX, "", Lang_CXX, Verifier,
546 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000547}
548
Gabor Marton19f4f392018-06-25 13:04:37 +0000549TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000550 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000551 testImport(
552 "void declToImport() { (void)nullptr; }",
553 Lang_CXX11, "", Lang_CXX11, Verifier,
554 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000555}
556
557
Gabor Marton19f4f392018-06-25 13:04:37 +0000558TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000559 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000560 testImport(
561 "void declToImport() { (void)1.0; }",
562 Lang_C, "", Lang_C, Verifier,
563 functionDecl(hasDescendant(
564 floatLiteral(equals(1.0), hasType(asString("double"))))));
565 testImport(
566 "void declToImport() { (void)1.0e-5f; }",
567 Lang_C, "", Lang_C, Verifier,
568 functionDecl(hasDescendant(
569 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000570}
571
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000572TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
573 MatchVerifier<Decl> Verifier;
574 testImport(
575 "void declToImport() { (void)1.0i; }",
576 Lang_CXX14, "", Lang_CXX14, Verifier,
577 functionDecl(hasDescendant(imaginaryLiteral())));
578}
579
Gabor Marton19f4f392018-06-25 13:04:37 +0000580TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000581 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000582 testImport(
583 "void declToImport() {"
584 " struct s { int x; long y; unsigned z; }; "
585 " (void)(struct s){ 42, 0L, 1U }; }",
586 Lang_CXX, "", Lang_CXX, Verifier,
587 functionDecl(hasDescendant(
588 compoundLiteralExpr(
589 hasType(asString("struct s")),
590 has(initListExpr(
591 hasType(asString("struct s")),
592 has(integerLiteral(
593 equals(42), hasType(asString("int")))),
594 has(integerLiteral(
595 equals(0), hasType(asString("long")))),
596 has(integerLiteral(
597 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000598}
599
Gabor Marton19f4f392018-06-25 13:04:37 +0000600TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000601 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000602 testImport(
603 "class declToImport { void f() { (void)this; } };",
604 Lang_CXX, "", Lang_CXX, Verifier,
605 cxxRecordDecl(
606 hasMethod(
607 hasDescendant(
608 cxxThisExpr(
609 hasType(
610 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000611}
612
Gabor Marton19f4f392018-06-25 13:04:37 +0000613TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000614 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000615 testImport(
616 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
617 Lang_C, "", Lang_C, Verifier,
618 functionDecl(hasDescendant(
619 atomicExpr(
620 has(ignoringParenImpCasts(
621 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
622 hasType(asString("int *"))))),
623 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000624}
625
Gabor Marton19f4f392018-06-25 13:04:37 +0000626TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000627 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000628 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000629 "void declToImport() { loop: goto loop; (void)&&loop; }",
630 Lang_C, "", Lang_C, Verifier,
631 functionDecl(
632 hasDescendant(
633 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
634 hasDescendant(
635 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000636}
637
638AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
639 internal::Matcher<NamedDecl>, InnerMatcher) {
640 const NamedDecl *Template = Node.getTemplatedDecl();
641 return Template && InnerMatcher.matches(*Template, Finder, Builder);
642}
643
Gabor Marton19f4f392018-06-25 13:04:37 +0000644TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000645 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000646 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000647 "template<typename T> class dummy { void f() { dummy X(*this); } };"
648 "typedef dummy<int> declToImport;"
649 "template class dummy<int>;",
650 Lang_CXX, "", Lang_CXX, Verifier,
651 typedefDecl(hasType(templateSpecializationType(
652 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
653 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
654 hasName("f"),
655 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
656 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
657 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000658 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000659}
660
Gabor Marton19f4f392018-06-25 13:04:37 +0000661TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000662 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000663 testImport(
664 "void declToImport() { int b; switch (b) { case 1: break; } }",
665 Lang_C, "", Lang_C, Verifier,
666 functionDecl(hasDescendant(
667 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000668}
669
Gabor Marton19f4f392018-06-25 13:04:37 +0000670TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000672 testImport(
673 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
674 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000675 functionDecl(hasDescendant(
676 varDecl(
677 hasName("C"),
678 hasType(asString("int")),
679 hasInitializer(
680 stmtExpr(
681 hasAnySubstatement(declStmt(hasSingleDecl(
682 varDecl(
683 hasName("X"),
684 hasType(asString("int")),
685 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000686 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000687 hasDescendant(
688 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000689}
690
Gabor Marton19f4f392018-06-25 13:04:37 +0000691TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000692 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000693 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000694 "void declToImport() { (void)(true ? 1 : -5); }",
695 Lang_CXX, "", Lang_CXX, Verifier,
696 functionDecl(hasDescendant(
697 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000698 hasCondition(cxxBoolLiteral(equals(true))),
699 hasTrueExpression(integerLiteral(equals(1))),
700 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000701 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
702 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000703}
704
Gabor Marton19f4f392018-06-25 13:04:37 +0000705TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000706 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000707 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000708 "void declToImport() { (void)(1 ?: -5); }",
709 Lang_CXX, "", Lang_CXX, Verifier,
710 functionDecl(hasDescendant(
711 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000712 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000713 implicitCastExpr(
714 hasSourceExpression(opaqueValueExpr(
715 hasSourceExpression(integerLiteral(equals(1))))),
716 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000717 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000718 opaqueValueExpr(
719 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000720 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000721 unaryOperator(
722 hasOperatorName("-"),
723 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000724}
725
Gabor Marton19f4f392018-06-25 13:04:37 +0000726TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000727 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000728 testImport(
729 "void declToImport() {"
730 " struct point { double x; double y; };"
731 " struct point ptarray[10] = "
732 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
733 Lang_C, "", Lang_C, Verifier,
734 functionDecl(hasDescendant(
735 initListExpr(
736 has(designatedInitExpr(
737 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000738 hasDescendant(floatLiteral(equals(1.0))),
739 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000740 has(designatedInitExpr(
741 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000742 hasDescendant(floatLiteral(equals(2.0))),
743 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000744 has(designatedInitExpr(
745 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000746 hasDescendant(floatLiteral(equals(1.0))),
747 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000748}
749
Gabor Marton19f4f392018-06-25 13:04:37 +0000750TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000751 MatchVerifier<Decl> Verifier;
752 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000753 testImport(
754 "void declToImport() { (void)__func__; }",
755 Lang_CXX, "", Lang_CXX, Verifier,
756 functionDecl(hasDescendant(
757 predefinedExpr(
758 hasType(
759 asString("const char [13]")),
760 has(stringLiteral(hasType(
761 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000762}
763
Gabor Marton19f4f392018-06-25 13:04:37 +0000764TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000765 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000766 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000767 "void declToImport() {"
768 " struct point { double x; double y; };"
769 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
770 " [0].x = 1.0 }; }",
771 Lang_CXX, "", Lang_CXX, Verifier,
772 functionDecl(hasDescendant(
773 initListExpr(
774 has(
775 cxxConstructExpr(
776 requiresZeroInitialization())),
777 has(
778 initListExpr(
779 hasType(asString("struct point")),
780 has(floatLiteral(equals(1.0))),
781 has(implicitValueInitExpr(
782 hasType(asString("double")))))),
783 has(
784 initListExpr(
785 hasType(asString("struct point")),
786 has(floatLiteral(equals(2.0))),
787 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000788}
789
790
Aleksei Sidorina693b372016-09-28 10:16:56 +0000791const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
792
Gabor Marton19f4f392018-06-25 13:04:37 +0000793TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000794 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000795 testImport(
796 "void declToImport(__builtin_va_list list, ...) {"
797 " (void)__builtin_va_arg(list, int); }",
798 Lang_CXX, "", Lang_CXX, Verifier,
799 functionDecl(hasDescendant(
800 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000801}
802
Gabor Marton19f4f392018-06-25 13:04:37 +0000803TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000804 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000805 testImport(
806 "struct C {};"
807 "void declToImport() { C c = C(); }",
808 Lang_CXX, "", Lang_CXX, Verifier,
809 functionDecl(hasDescendant(
810 exprWithCleanups(has(cxxConstructExpr(
811 has(materializeTemporaryExpr(has(implicitCastExpr(
812 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000813}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000814
Gabor Marton19f4f392018-06-25 13:04:37 +0000815TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000816 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000817 testImport(
818 "void declToImport() { typedef _Atomic(int) a_int; }",
819 Lang_CXX11, "", Lang_CXX11, Verifier,
820 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000821}
822
Gabor Marton19f4f392018-06-25 13:04:37 +0000823TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000824 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000825 testImport(
826 "template <typename T> void declToImport() { };",
827 Lang_CXX, "", Lang_CXX, Verifier,
828 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000829}
830
Gabor Marton19f4f392018-06-25 13:04:37 +0000831TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000832 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000833 testImport(
834 "template <typename T> struct C { T t; };"
835 "template <typename T> void declToImport() {"
836 " C<T> d;"
837 " (void)d.t;"
838 "}"
839 "void instantiate() { declToImport<int>(); }",
840 Lang_CXX, "", Lang_CXX, Verifier,
841 functionTemplateDecl(hasDescendant(
842 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
843 testImport(
844 "template <typename T> struct C { T t; };"
845 "template <typename T> void declToImport() {"
846 " C<T> d;"
847 " (void)(&d)->t;"
848 "}"
849 "void instantiate() { declToImport<int>(); }",
850 Lang_CXX, "", Lang_CXX, Verifier,
851 functionTemplateDecl(hasDescendant(
852 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000853}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000854
Gabor Marton19f4f392018-06-25 13:04:37 +0000855TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000856 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000857 testImport(
858 "template <int K>"
859 "struct dummy { static const int i = K; };"
860 "template <int K> using dummy2 = dummy<K>;"
861 "int declToImport() { return dummy2<3>::i; }",
862 Lang_CXX11, "", Lang_CXX11, Verifier,
863 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000864 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000865 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
866}
867
868const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
869 varTemplateSpecializationDecl;
870
Gabor Marton19f4f392018-06-25 13:04:37 +0000871TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000872 MatchVerifier<Decl> Verifier;
873 testImport(
874 "template <typename T>"
875 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000876 "void declToImport() { (void)pi<int>; }",
877 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000878 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000879 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000880 unless(hasAncestor(translationUnitDecl(has(varDecl(
881 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000882}
883
Gabor Marton19f4f392018-06-25 13:04:37 +0000884TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000885 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000886 testImport(
887 "template <typename... Args>"
888 "struct dummy {"
889 " dummy(Args... args) {}"
890 " static const int i = 4;"
891 "};"
892 "int declToImport() { return dummy<int>::i; }",
893 Lang_CXX11, "", Lang_CXX11, Verifier,
894 functionDecl(hasDescendant(
895 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000896}
897
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000898const internal::VariadicDynCastAllOfMatcher<Type,
899 DependentTemplateSpecializationType>
900 dependentTemplateSpecializationType;
901
Gabor Marton19f4f392018-06-25 13:04:37 +0000902TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000903 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000904 testImport(
905 "template<typename T>"
906 "struct A;"
907 "template<typename T>"
908 "struct declToImport {"
909 " typename A<T>::template B<T> a;"
910 "};",
911 Lang_CXX, "", Lang_CXX, Verifier,
912 classTemplateDecl(has(cxxRecordDecl(has(
913 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000914}
915
916const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
917 sizeOfPackExpr;
918
Gabor Marton19f4f392018-06-25 13:04:37 +0000919TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000920 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000921 testImport(
922 "template <typename... Ts>"
923 "void declToImport() {"
924 " const int i = sizeof...(Ts);"
925 "};"
926 "void g() { declToImport<int>(); }",
927 Lang_CXX11, "", Lang_CXX11, Verifier,
928 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000929 testImport(
930 "template <typename... Ts>"
931 "using X = int[sizeof...(Ts)];"
932 "template <typename... Us>"
933 "struct Y {"
934 " X<Us..., int, double, int, Us...> f;"
935 "};"
936 "Y<float, int> declToImport;",
937 Lang_CXX11, "", Lang_CXX11, Verifier,
938 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
939 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
940}
941
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000942/// \brief Matches __builtin_types_compatible_p:
943/// GNU extension to check equivalent types
944/// Given
945/// \code
946/// __builtin_types_compatible_p(int, int)
947/// \endcode
948// will generate TypeTraitExpr <...> 'int'
949const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
950
Gabor Marton19f4f392018-06-25 13:04:37 +0000951TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000952 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000953 testImport(
954 "void declToImport() { "
955 " (void)__builtin_types_compatible_p(int, int);"
956 "}",
957 Lang_C, "", Lang_C, Verifier,
958 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000959}
960
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000961const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
962
Gabor Marton19f4f392018-06-25 13:04:37 +0000963TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000964 MatchVerifier<Decl> Verifier;
965 testImport(
966 "namespace std { class type_info {}; }"
967 "void declToImport() {"
968 " int x;"
969 " auto a = typeid(int); auto b = typeid(x);"
970 "}",
971 Lang_CXX11, "", Lang_CXX11, Verifier,
972 functionDecl(
973 hasDescendant(varDecl(
974 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
975 hasDescendant(varDecl(
976 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
977}
978
Gabor Marton19f4f392018-06-25 13:04:37 +0000979TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000980 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000981 testImport(
982 "template<typename T> struct declToImport {"
983 " void m() { (void)__is_pod(T); }"
984 "};"
985 "void f() { declToImport<int>().m(); }",
986 Lang_CXX11, "", Lang_CXX11, Verifier,
987 classTemplateDecl(has(cxxRecordDecl(has(
988 functionDecl(hasDescendant(
989 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000990}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000991
Gabor Marton6e1510c2018-07-12 11:50:21 +0000992TEST_P(ImportDecl, ImportRecordDeclInFunc) {
993 MatchVerifier<Decl> Verifier;
994 testImport("int declToImport() { "
995 " struct data_t {int a;int b;};"
996 " struct data_t d;"
997 " return 0;"
998 "}",
999 Lang_C, "", Lang_C, Verifier,
1000 functionDecl(hasBody(compoundStmt(
1001 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1002}
1003
1004TEST_P(ASTImporterTestBase, ImportRecordTypeInFunc) {
1005 Decl *FromTU = getTuDecl("int declToImport() { "
1006 " struct data_t {int a;int b;};"
1007 " struct data_t d;"
1008 " return 0;"
1009 "}",
1010 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001011 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001012 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1013 ASSERT_TRUE(FromVar);
1014 auto ToType =
1015 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1016 EXPECT_FALSE(ToType.isNull());
1017}
1018
1019TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParams) {
1020 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001021 Decl *FromTU = getTuDecl(
1022 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1023 Lang_C, "input.c");
1024 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1025 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001026 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001027 auto *To = Import(From, Lang_C);
1028 EXPECT_EQ(To, nullptr);
1029}
1030
1031TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncFromMacro) {
1032 Decl *FromTU = getTuDecl(
1033 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1034 "int declToImport(){ return NONAME_SIZEOF(int); }",
1035 Lang_C, "input.c");
1036 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1037 FromTU, functionDecl(hasName("declToImport")));
1038 ASSERT_TRUE(From);
1039 auto *To = Import(From, Lang_C);
1040 ASSERT_TRUE(To);
1041 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1042 To, functionDecl(hasName("declToImport"),
1043 hasDescendant(unaryExprOrTypeTraitExpr()))));
1044}
1045
1046TEST_P(ASTImporterTestBase, ImportRecordDeclInFuncParamsFromMacro) {
1047 // This construct is not supported by ASTImporter.
1048 Decl *FromTU = getTuDecl(
1049 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1050 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1051 Lang_C, "input.c");
1052 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1053 FromTU, functionDecl(hasName("declToImport")));
1054 ASSERT_TRUE(From);
1055 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001056 EXPECT_EQ(To, nullptr);
1057}
1058
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001059const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1060 cxxPseudoDestructorExpr;
1061
Gabor Marton19f4f392018-06-25 13:04:37 +00001062TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001063 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001064 testImport(
1065 "typedef int T;"
1066 "void declToImport(int *p) {"
1067 " T t;"
1068 " p->T::~T();"
1069 "}",
1070 Lang_CXX, "", Lang_CXX, Verifier,
1071 functionDecl(hasDescendant(
1072 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001073}
1074
Gabor Marton19f4f392018-06-25 13:04:37 +00001075TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001076 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001077 testImport(
1078 "namespace foo { int bar; }"
1079 "void declToImport() { using foo::bar; }",
1080 Lang_CXX, "", Lang_CXX, Verifier,
1081 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001082}
1083
1084/// \brief Matches shadow declarations introduced into a scope by a
1085/// (resolved) using declaration.
1086///
1087/// Given
1088/// \code
1089/// namespace n { int f; }
1090/// namespace declToImport { using n::f; }
1091/// \endcode
1092/// usingShadowDecl()
1093/// matches \code f \endcode
1094const internal::VariadicDynCastAllOfMatcher<Decl,
1095 UsingShadowDecl> usingShadowDecl;
1096
Gabor Marton19f4f392018-06-25 13:04:37 +00001097TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001098 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001099 testImport(
1100 "namespace foo { int bar; }"
1101 "namespace declToImport { using foo::bar; }",
1102 Lang_CXX, "", Lang_CXX, Verifier,
1103 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001104}
1105
Gabor Marton19f4f392018-06-25 13:04:37 +00001106TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001107 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001108 testImport(
1109 "template<typename T> int foo();"
1110 "template <typename T> void declToImport() {"
1111 " (void)::foo<T>;"
1112 " (void)::template foo<T>;"
1113 "}"
1114 "void instantiate() { declToImport<int>(); }",
1115 Lang_CXX, "", Lang_CXX, Verifier,
1116 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001117}
1118
Gabor Marton19f4f392018-06-25 13:04:37 +00001119TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001120 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001121 testImport(
1122 "template <typename T> struct C { T t; };"
1123 "template <typename T> void declToImport() {"
1124 " C<T> d;"
1125 " d.t = T();"
1126 "}"
1127 "void instantiate() { declToImport<int>(); }",
1128 Lang_CXX, "", Lang_CXX, Verifier,
1129 functionTemplateDecl(hasDescendant(
1130 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1131 testImport(
1132 "template <typename T> struct C { T t; };"
1133 "template <typename T> void declToImport() {"
1134 " C<T> d;"
1135 " (&d)->t = T();"
1136 "}"
1137 "void instantiate() { declToImport<int>(); }",
1138 Lang_CXX, "", Lang_CXX, Verifier,
1139 functionTemplateDecl(hasDescendant(
1140 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001141}
1142
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001143/// Check that function "declToImport()" (which is the templated function
1144/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1145/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001146TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001147 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001148 testImport(
1149 "template <typename T> void declToImport() { T a = 1; }"
1150 "void instantiate() { declToImport<int>(); }",
1151 Lang_CXX, "", Lang_CXX, Verifier,
1152 functionTemplateDecl(hasAncestor(translationUnitDecl(
1153 unless(has(functionDecl(hasName("declToImport"))))))));
1154 testImport(
1155 "template <typename T> struct declToImport { T t; };"
1156 "void instantiate() { declToImport<int>(); }",
1157 Lang_CXX, "", Lang_CXX, Verifier,
1158 classTemplateDecl(hasAncestor(translationUnitDecl(
1159 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001160}
1161
Gabor Marton19f4f392018-06-25 13:04:37 +00001162TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001163 MatchVerifier<Decl> Verifier;
1164 auto Code =
1165 R"s(
1166 struct declToImport {
1167 template <typename T0> struct X;
1168 template <typename T0> struct X<T0 *> {};
1169 };
1170 )s";
1171 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1172 recordDecl(has(classTemplateDecl()),
1173 has(classTemplateSpecializationDecl())));
1174}
1175
Gabor Marton19f4f392018-06-25 13:04:37 +00001176TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001177 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001178 testImport(
1179 "class declToImport {"
1180 " void f() { *this = declToImport(); }"
1181 "};",
1182 Lang_CXX, "", Lang_CXX, Verifier,
1183 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1184 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001185}
1186
Gabor Marton19f4f392018-06-25 13:04:37 +00001187TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001188 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001189 testImport(
1190 "template<typename T, int Size> class declToImport {"
1191 " T data[Size];"
1192 "};",
1193 Lang_CXX, "", Lang_CXX, Verifier,
1194 classTemplateDecl(has(cxxRecordDecl(
1195 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001196}
1197
Gabor Martona0df7a92018-05-30 09:19:26 +00001198TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1199 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1200 auto From =
1201 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1202 ASSERT_TRUE(From);
1203 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1204 ASSERT_TRUE(To);
1205 Decl *ToTemplated = To->getTemplatedDecl();
1206 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1207 EXPECT_TRUE(ToTemplated1);
1208 EXPECT_EQ(ToTemplated1, ToTemplated);
1209}
1210
Gabor Marton26f72a92018-07-12 09:42:05 +00001211TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001212 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1213 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1214 FromTU, functionTemplateDecl());
1215 ASSERT_TRUE(From);
1216 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1217 ASSERT_TRUE(To);
1218 Decl *ToTemplated = To->getTemplatedDecl();
1219 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1220 EXPECT_TRUE(ToTemplated1);
1221 EXPECT_EQ(ToTemplated1, ToTemplated);
1222}
1223
1224TEST_P(ASTImporterTestBase,
1225 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1226 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1227 auto FromFT =
1228 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1229 ASSERT_TRUE(FromFT);
1230
1231 auto ToTemplated =
1232 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1233 EXPECT_TRUE(ToTemplated);
1234 auto ToTU = ToTemplated->getTranslationUnitDecl();
1235 auto ToFT =
1236 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1237 EXPECT_TRUE(ToFT);
1238}
1239
1240TEST_P(ASTImporterTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001241 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001242 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1243 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1244 FromTU, functionTemplateDecl());
1245 ASSERT_TRUE(FromFT);
1246
1247 auto ToTemplated =
1248 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1249 EXPECT_TRUE(ToTemplated);
1250 auto ToTU = ToTemplated->getTranslationUnitDecl();
1251 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1252 ToTU, functionTemplateDecl());
1253 EXPECT_TRUE(ToFT);
1254}
1255
Gabor Martona0df7a92018-05-30 09:19:26 +00001256TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1257 auto Code =
1258 R"(
1259 namespace x {
1260 template<class X> struct S1{};
1261 template<class X> struct S2{};
1262 template<class X> struct S3{};
1263 }
1264 )";
1265 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1266 auto FromNs =
1267 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1268 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1269 ASSERT_TRUE(ToNs);
1270 auto From =
1271 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1272 classTemplateDecl(
1273 hasName("S2")));
1274 auto To =
1275 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1276 classTemplateDecl(
1277 hasName("S2")));
1278 ASSERT_TRUE(From);
1279 ASSERT_TRUE(To);
1280 auto ToTemplated = To->getTemplatedDecl();
1281 auto ToTemplated1 =
1282 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1283 EXPECT_TRUE(ToTemplated1);
1284 ASSERT_EQ(ToTemplated1, ToTemplated);
1285}
1286
Gabor Marton26f72a92018-07-12 09:42:05 +00001287TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001288 Decl *From, *To;
1289 std::tie(From, To) = getImportedDecl(
1290 R"(
1291 template <typename T> struct X {};
1292
1293 void declToImport(int y, X<int> &x) {}
1294
1295 template <> struct X<int> {
1296 void g() {
1297 X<int> x;
1298 declToImport(0, x);
1299 }
1300 };
1301 )",
1302 Lang_CXX, "", Lang_CXX);
1303
1304 MatchVerifier<Decl> Verifier;
1305 auto Matcher = functionDecl(hasName("declToImport"),
1306 parameterCountIs(2),
1307 hasParameter(0, hasName("y")),
1308 hasParameter(1, hasName("x")),
1309 hasParameter(1, hasType(asString("X<int> &"))));
1310 ASSERT_TRUE(Verifier.match(From, Matcher));
1311 EXPECT_TRUE(Verifier.match(To, Matcher));
1312}
1313
1314TEST_P(ASTImporterTestBase,
1315 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1316 Decl *From, *To;
1317 std::tie(From, To) =
1318 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1319 "void instantiate() { declToImport<int>(); }",
1320 Lang_CXX, "", Lang_CXX);
1321
1322 auto Check = [](Decl *D) -> bool {
1323 auto TU = D->getTranslationUnitDecl();
1324 for (auto Child : TU->decls()) {
1325 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1326 if (FD->getNameAsString() == "declToImport") {
1327 GTEST_NONFATAL_FAILURE_(
1328 "TU should not contain any FunctionDecl with name declToImport");
1329 return false;
1330 }
1331 }
1332 }
1333 return true;
1334 };
1335
1336 ASSERT_TRUE(Check(From));
1337 EXPECT_TRUE(Check(To));
1338}
1339
1340TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1341 Decl *From, *To;
1342 std::tie(From, To) =
1343 getImportedDecl("template <typename T> struct declToImport { T t; };"
1344 "void instantiate() { declToImport<int>(); }",
1345 Lang_CXX, "", Lang_CXX);
1346
1347 auto Check = [](Decl *D) -> bool {
1348 auto TU = D->getTranslationUnitDecl();
1349 for (auto Child : TU->decls()) {
1350 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1351 if (RD->getNameAsString() == "declToImport") {
1352 GTEST_NONFATAL_FAILURE_(
1353 "TU should not contain any CXXRecordDecl with name declToImport");
1354 return false;
1355 }
1356 }
1357 }
1358 return true;
1359 };
1360
1361 ASSERT_TRUE(Check(From));
1362 EXPECT_TRUE(Check(To));
1363}
1364
1365TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1366 Decl *From, *To;
1367 std::tie(From, To) =
1368 getImportedDecl(
1369 "template <typename T> struct X {};"
1370 "template <typename T> using declToImport = X<T>;"
1371 "void instantiate() { declToImport<int> a; }",
1372 Lang_CXX11, "", Lang_CXX11);
1373
1374 auto Check = [](Decl *D) -> bool {
1375 auto TU = D->getTranslationUnitDecl();
1376 for (auto Child : TU->decls()) {
1377 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1378 if (AD->getNameAsString() == "declToImport") {
1379 GTEST_NONFATAL_FAILURE_(
1380 "TU should not contain any TypeAliasDecl with name declToImport");
1381 return false;
1382 }
1383 }
1384 }
1385 return true;
1386 };
1387
1388 ASSERT_TRUE(Check(From));
1389 EXPECT_TRUE(Check(To));
1390}
1391
1392TEST_P(
1393 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001394 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001395
1396 Decl *From, *To;
1397 std::tie(From, To) = getImportedDecl(
1398 R"(
1399 template<class T>
1400 class Base {};
1401 class declToImport : public Base<declToImport> {};
1402 )",
1403 Lang_CXX, "", Lang_CXX);
1404
1405 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1406 auto Pattern =
1407 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1408 ASSERT_TRUE(
1409 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1410 EXPECT_TRUE(
1411 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1412
1413 // Check that the ClassTemplateSpecializationDecl is the child of the
1414 // ClassTemplateDecl.
1415 Pattern = translationUnitDecl(has(classTemplateDecl(
1416 hasName("Base"), has(classTemplateSpecializationDecl()))));
1417 ASSERT_TRUE(
1418 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1419 EXPECT_TRUE(
1420 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1421}
1422
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001423AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1424 size_t Index = 0;
1425 for (FieldDecl *Field : Node.fields()) {
1426 if (Index == Order.size())
1427 return false;
1428 if (Field->getName() != Order[Index])
1429 return false;
1430 ++Index;
1431 }
1432 return Index == Order.size();
1433}
1434
Peter Szecsidedda6f2018-03-30 22:03:29 +00001435TEST_P(ASTImporterTestBase,
1436 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1437 Decl *From, *To;
1438 std::tie(From, To) = getImportedDecl(
1439 R"(
1440 namespace NS {
1441 template<class T>
1442 class X {};
1443 template class X<int>;
1444 }
1445 )",
1446 Lang_CXX, "", Lang_CXX, "NS");
1447
1448 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1449 // ClassTemplateDecl.
1450 auto Pattern = namespaceDecl(has(classTemplateDecl(
1451 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1452 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1453 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1454
1455 // Check that the ClassTemplateSpecializationDecl is the child of the
1456 // NamespaceDecl.
1457 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1458 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1459 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1460}
1461
1462TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1463 Decl *From, *To;
1464 std::tie(From, To) =
1465 getImportedDecl(
1466 "struct declToImport { int a; int b; };",
1467 Lang_CXX11, "", Lang_CXX11);
1468
1469 MatchVerifier<Decl> Verifier;
1470 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1471 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1472}
1473
1474TEST_P(ASTImporterTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001475 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001476 Decl *From, *To;
1477 std::tie(From, To) = getImportedDecl(
1478 // The original recursive algorithm of ASTImporter first imports 'c' then
1479 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1480 R"s(
1481 struct declToImport {
1482 int a = c + b;
1483 int b = 1;
1484 int c = 2;
1485 };
1486 )s",
1487 Lang_CXX11, "", Lang_CXX11);
1488
1489 MatchVerifier<Decl> Verifier;
1490 ASSERT_TRUE(
1491 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1492 EXPECT_TRUE(
1493 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1494}
1495
Gabor Martonde8bf262018-05-17 09:46:07 +00001496TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001497 Decl *From, *To;
1498 std::tie(From, To) = getImportedDecl(
1499 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001500 struct declToImport {
1501 };
1502 )",
1503 Lang_CXX, "", Lang_CXX);
1504
1505 MatchVerifier<Decl> Verifier;
1506 // Match the implicit Decl.
1507 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1508 ASSERT_TRUE(Verifier.match(From, Matcher));
1509 EXPECT_TRUE(Verifier.match(To, Matcher));
1510}
1511
1512TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1513 Decl *From, *To;
1514 std::tie(From, To) = getImportedDecl(
1515 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001516 template <typename U>
1517 struct declToImport {
1518 };
1519 )",
1520 Lang_CXX, "", Lang_CXX);
1521
1522 MatchVerifier<Decl> Verifier;
1523 // Match the implicit Decl.
1524 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1525 ASSERT_TRUE(Verifier.match(From, Matcher));
1526 EXPECT_TRUE(Verifier.match(To, Matcher));
1527}
1528
1529TEST_P(
1530 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001531 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001532 Decl *From, *To;
1533 std::tie(From, To) = getImportedDecl(
1534 R"(
1535 template<class T>
1536 class Base {};
1537 class declToImport : public Base<declToImport> {};
1538 )",
1539 Lang_CXX, "", Lang_CXX);
1540
1541 auto hasImplicitClass = has(cxxRecordDecl());
1542 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1543 hasName("Base"),
1544 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1545 ASSERT_TRUE(
1546 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1547 EXPECT_TRUE(
1548 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1549}
1550
1551TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1552 Decl *From, *To;
1553 std::tie(From, To) =
1554 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1555
1556 MatchVerifier<Decl> Verifier;
1557 auto Matcher = functionDecl();
1558 ASSERT_TRUE(Verifier.match(From, Matcher));
1559 EXPECT_TRUE(Verifier.match(To, Matcher));
1560 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1561}
1562
Gabor Marton2ae9da32018-05-18 15:46:18 +00001563TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001564 Decl *FromTU = getTuDecl(
1565 R"(
1566 struct X {};
1567 void operator<<(int, X);
1568 )",
1569 Lang_CXX);
1570 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1571 const Decl *To = Import(From, Lang_CXX);
1572 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1573}
1574
1575TEST_P(ASTImporterTestBase,
1576 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1577 Decl *From, *To;
1578 std::tie(From, To) = getImportedDecl(
1579 R"(
1580 template<class T>
1581 class Base { int a; };
1582 class declToImport : Base<declToImport> {};
1583 )",
1584 Lang_CXX, "", Lang_CXX);
1585
1586 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1587 hasName("Base"),
1588 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1589 ASSERT_TRUE(
1590 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1591 EXPECT_TRUE(
1592 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1593}
1594
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001595TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1596 {
1597 Decl *FromTU = getTuDecl(
1598 R"(
1599 template <typename T>
1600 struct B;
1601 )",
1602 Lang_CXX, "input0.cc");
1603 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1604 FromTU, classTemplateDecl(hasName("B")));
1605
1606 Import(FromD, Lang_CXX);
1607 }
1608
1609 {
1610 Decl *FromTU = getTuDecl(
1611 R"(
1612 template <typename T>
1613 struct B {
1614 void f();
1615 };
1616 )",
1617 Lang_CXX, "input1.cc");
1618 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1619 FromTU, functionDecl(hasName("f")));
1620 Import(FromD, Lang_CXX);
1621 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1622 FromTU, classTemplateDecl(hasName("B")));
1623 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1624 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1625 }
1626}
1627
Gabor Marton9581c332018-05-23 13:53:36 +00001628TEST_P(ASTImporterTestBase,
1629 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1630 Decl *ToTU = getToTuDecl(
1631 R"(
1632 template <typename T>
1633 struct B {
1634 void f();
1635 };
1636
1637 template <typename T>
1638 struct B;
1639 )",
1640 Lang_CXX);
1641 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1642 [](const ClassTemplateDecl *T) {
1643 return T->isThisDeclarationADefinition();
1644 })
1645 .match(ToTU, classTemplateDecl()));
1646
1647 Decl *FromTU = getTuDecl(
1648 R"(
1649 template <typename T>
1650 struct B {
1651 void f();
1652 };
1653 )",
1654 Lang_CXX, "input1.cc");
1655 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1656 FromTU, classTemplateDecl(hasName("B")));
1657
1658 Import(FromD, Lang_CXX);
1659
1660 // We should have only one definition.
1661 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1662 [](const ClassTemplateDecl *T) {
1663 return T->isThisDeclarationADefinition();
1664 })
1665 .match(ToTU, classTemplateDecl()));
1666}
1667
1668TEST_P(ASTImporterTestBase,
1669 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1670 Decl *ToTU = getToTuDecl(
1671 R"(
1672 struct B {
1673 void f();
1674 };
1675
1676 struct B;
1677 )",
1678 Lang_CXX);
1679 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001680 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001681
1682 Decl *FromTU = getTuDecl(
1683 R"(
1684 struct B {
1685 void f();
1686 };
1687 )",
1688 Lang_CXX, "input1.cc");
1689 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1690 FromTU, cxxRecordDecl(hasName("B")));
1691
1692 Import(FromD, Lang_CXX);
1693
1694 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001695 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001696}
1697
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001698static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1699 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1700 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1701 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1702 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1703}
1704static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1705 SourceManager &SM1, SourceManager &SM2) {
1706 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1707 FullSourceLoc{ Range2.getBegin(), SM2 });
1708 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1709 FullSourceLoc{ Range2.getEnd(), SM2 });
1710}
1711TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1712 Decl *FromTU = getTuDecl(
1713 R"(
1714 #define MFOO(arg) arg = arg + 1
1715
1716 void foo() {
1717 int a = 5;
1718 MFOO(a);
1719 }
1720 )",
1721 Lang_CXX);
1722 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1723 auto ToD = Import(FromD, Lang_CXX);
1724
1725 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1726 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1727 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1728 auto FromRHS =
1729 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1730
1731 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1732 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1733 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1734 FromSM);
1735 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1736 FromSM);
1737 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1738 FromSM);
1739}
1740
Rafael Stahla0010472018-07-09 08:40:17 +00001741TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001742 Decl *FromTU = getTuDecl(
1743 R"(
1744 #define FUNC_INT void declToImport
1745 #define FUNC FUNC_INT
1746 FUNC(int a);
1747 )",
1748 Lang_CXX);
1749 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1750 auto ToD = Import(FromD, Lang_CXX);
1751
1752 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1753 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1754 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1755 FromSM);
1756}
1757
Gabor Marton9581c332018-05-23 13:53:36 +00001758TEST_P(
1759 ASTImporterTestBase,
1760 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1761{
1762 Decl *ToTU = getToTuDecl(
1763 R"(
1764 template <typename T>
1765 struct B;
1766
1767 template <>
1768 struct B<int> {};
1769
1770 template <>
1771 struct B<int>;
1772 )",
1773 Lang_CXX);
1774 // We should have only one definition.
1775 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1776 [](const ClassTemplateSpecializationDecl *T) {
1777 return T->isThisDeclarationADefinition();
1778 })
1779 .match(ToTU, classTemplateSpecializationDecl()));
1780
1781 Decl *FromTU = getTuDecl(
1782 R"(
1783 template <typename T>
1784 struct B;
1785
1786 template <>
1787 struct B<int> {};
1788 )",
1789 Lang_CXX, "input1.cc");
1790 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1791 FromTU, classTemplateSpecializationDecl(hasName("B")));
1792
1793 Import(FromD, Lang_CXX);
1794
1795 // We should have only one definition.
1796 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1797 [](const ClassTemplateSpecializationDecl *T) {
1798 return T->isThisDeclarationADefinition();
1799 })
1800 .match(ToTU, classTemplateSpecializationDecl()));
1801}
1802
Gabor Marton0bebf952018-07-05 09:51:13 +00001803TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1804 Decl *FromTU = getTuDecl(
1805 R"(
1806 struct { int a; int b; } object0 = { 2, 3 };
1807 struct { int x; int y; int z; } object1;
1808 )",
1809 Lang_CXX, "input0.cc");
1810
Gabor Marton0bebf952018-07-05 09:51:13 +00001811 auto *Obj0 =
1812 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1813 auto *From0 = getRecordDecl(Obj0);
1814 auto *Obj1 =
1815 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1816 auto *From1 = getRecordDecl(Obj1);
1817
1818 auto *To0 = Import(From0, Lang_CXX);
1819 auto *To1 = Import(From1, Lang_CXX);
1820
1821 EXPECT_TRUE(To0);
1822 EXPECT_TRUE(To1);
1823 EXPECT_NE(To0, To1);
1824 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1825}
1826
Gabor Marton7df342a2018-12-17 12:42:12 +00001827TEST_P(ASTImporterTestBase, AnonymousRecords) {
1828 auto *Code =
1829 R"(
1830 struct X {
1831 struct { int a; };
1832 struct { int b; };
1833 };
1834 )";
1835 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1836
1837 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1838
1839 auto *X0 =
1840 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1841 auto *X1 =
1842 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1843 Import(X0, Lang_C);
1844 Import(X1, Lang_C);
1845
1846 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1847 // We expect no (ODR) warning during the import.
1848 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1849 EXPECT_EQ(1u,
1850 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1851}
1852
1853TEST_P(ASTImporterTestBase, AnonymousRecordsReversed) {
1854 Decl *FromTU0 = getTuDecl(
1855 R"(
1856 struct X {
1857 struct { int a; };
1858 struct { int b; };
1859 };
1860 )",
1861 Lang_C, "input0.c");
1862
1863 Decl *FromTU1 = getTuDecl(
1864 R"(
1865 struct X { // reversed order
1866 struct { int b; };
1867 struct { int a; };
1868 };
1869 )",
1870 Lang_C, "input1.c");
1871
1872 auto *X0 =
1873 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1874 auto *X1 =
1875 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1876 Import(X0, Lang_C);
1877 Import(X1, Lang_C);
1878
1879 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1880 // We expect one (ODR) warning during the import.
1881 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1882 EXPECT_EQ(2u,
1883 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1884}
1885
Gabor Marton26f72a92018-07-12 09:42:05 +00001886TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
1887 auto Pattern = varDecl(hasName("x"));
1888 VarDecl *Imported1;
1889 {
1890 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1891 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1892 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1893 }
1894 VarDecl *Imported2;
1895 {
1896 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1897 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1898 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1899 }
1900 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1901 EXPECT_FALSE(Imported2->isUsed(false));
1902 {
1903 Decl *FromTU =
1904 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001905 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1906 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001907 Import(FromD, Lang_CXX);
1908 }
1909 EXPECT_TRUE(Imported2->isUsed(false));
1910}
1911
Gabor Martonac3a5d62018-09-17 12:04:52 +00001912TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag2) {
1913 auto Pattern = varDecl(hasName("x"));
1914 VarDecl *ExistingD;
1915 {
1916 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1917 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1918 }
1919 EXPECT_FALSE(ExistingD->isUsed(false));
1920 {
1921 Decl *FromTU = getTuDecl(
1922 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1923 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1924 FromTU, functionDecl(hasName("f")));
1925 Import(FromD, Lang_CXX);
1926 }
1927 EXPECT_TRUE(ExistingD->isUsed(false));
1928}
1929
1930TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag3) {
1931 auto Pattern = varDecl(hasName("a"));
1932 VarDecl *ExistingD;
1933 {
1934 Decl *ToTU = getToTuDecl(
1935 R"(
1936 struct A {
1937 static const int a = 1;
1938 };
1939 )", Lang_CXX);
1940 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1941 }
1942 EXPECT_FALSE(ExistingD->isUsed(false));
1943 {
1944 Decl *FromTU = getTuDecl(
1945 R"(
1946 struct A {
1947 static const int a = 1;
1948 };
1949 const int *f() { return &A::a; } // requires storage,
1950 // thus used flag will be set
1951 )", Lang_CXX, "input1.cc");
1952 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1953 FromTU, functionDecl(hasName("f")));
1954 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1955 ASSERT_TRUE(FromD->isUsed(false));
1956 Import(FromFunD, Lang_CXX);
1957 }
1958 EXPECT_TRUE(ExistingD->isUsed(false));
1959}
1960
Gabor Marton26f72a92018-07-12 09:42:05 +00001961TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
1962 auto Pattern = varDecl(hasName("x"));
1963
1964 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1965 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1966
1967 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1968
1969 ASSERT_FALSE(Imported1->isUsed(false));
1970
1971 FromD->setIsUsed();
1972 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1973
1974 EXPECT_EQ(Imported1, Imported2);
1975 EXPECT_TRUE(Imported2->isUsed(false));
1976}
1977
Peter Szecsidedda6f2018-03-30 22:03:29 +00001978struct ImportFunctions : ASTImporterTestBase {};
1979
1980TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001981 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1982 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1983 auto Pattern = functionDecl(hasName("f"));
1984 FunctionDecl *FromD = // Definition
1985 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1986
1987 Decl *ImportedD = Import(FromD, Lang_CXX);
1988 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1989
Gabor Marton5254e642018-06-27 13:32:50 +00001990 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001991 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1992}
1993
1994TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1995 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1996 auto Pattern = functionDecl(hasName("f"));
1997 FunctionDecl *FromD =
1998 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1999
2000 Decl *ImportedD = Import(FromD, Lang_CXX);
2001 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2002
2003 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2004 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
2005}
2006
Gabor Marton5254e642018-06-27 13:32:50 +00002007TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002008 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2009 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002010 auto *From =
2011 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002012
Gabor Marton5254e642018-06-27 13:32:50 +00002013 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002014 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2015
Gabor Marton5254e642018-06-27 13:32:50 +00002016 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2017 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2018 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2019 EXPECT_TRUE(ImportedD == To0);
2020 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2021 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2022 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002023}
2024
2025TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2026 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2027 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002028 auto *From =
2029 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002030
Gabor Marton5254e642018-06-27 13:32:50 +00002031 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002032 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2033
Gabor Marton5254e642018-06-27 13:32:50 +00002034 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2035 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2036 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2037 EXPECT_TRUE(ImportedD == To1);
2038 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2039 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2040 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002041}
2042
2043TEST_P(ImportFunctions, ImportPrototypes) {
2044 auto Pattern = functionDecl(hasName("f"));
2045
2046 Decl *ImportedD;
2047 {
2048 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002049 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002050
2051 ImportedD = Import(FromD, Lang_CXX);
2052 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002053 {
2054 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002055 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2056 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002057 }
2058
Gabor Marton5254e642018-06-27 13:32:50 +00002059 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2060
2061 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2062 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2063 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2064 EXPECT_TRUE(ImportedD == To0);
2065 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2066 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2067 EXPECT_EQ(To1->getPreviousDecl(), To0);
2068}
2069
2070TEST_P(ImportFunctions, ImportDefinitions) {
2071 auto Pattern = functionDecl(hasName("f"));
2072
2073 Decl *ImportedD;
2074 {
2075 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
2076 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2077 ImportedD = Import(FromD, Lang_CXX);
2078 }
2079 {
2080 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
2081 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2082 Import(FromD, Lang_CXX);
2083 }
2084
2085 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2086
Peter Szecsidedda6f2018-03-30 22:03:29 +00002087 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00002088 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2089 EXPECT_TRUE(ImportedD == To0);
2090 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002091}
2092
2093TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
2094 auto Pattern = functionDecl(hasName("f"));
2095
2096 Decl *ImportedD;
2097 {
2098 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002099 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002100 ImportedD = Import(FromD, Lang_CXX);
2101 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00002102 {
2103 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002104 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2105 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002106 }
2107
2108 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002109
2110 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2111 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2112 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2113 EXPECT_TRUE(ImportedD == To0);
2114 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2115 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2116 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002117}
2118
2119TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
2120 auto Pattern = functionDecl(hasName("f"));
2121
2122 {
2123 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
2124 FunctionDecl *FromD =
2125 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2126
2127 Import(FromD, Lang_CXX);
2128 }
2129 {
2130 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
2131 FunctionDecl *FromD =
2132 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2133 Import(FromD, Lang_CXX);
2134 }
2135
2136 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2137 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2138 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002139 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00002140 FunctionDecl *DefinitionD =
2141 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2142 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
2143 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
2144}
2145
Gabor Marton5254e642018-06-27 13:32:50 +00002146TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002147 auto Pattern = functionDecl(hasName("f"));
2148
2149 {
2150 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002151 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002152 Import(FromD, Lang_CXX);
2153 }
2154 {
2155 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00002156 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002157 Import(FromD, Lang_CXX);
2158 }
2159
2160 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00002161
2162 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002163 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00002164 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
2165
Peter Szecsidedda6f2018-03-30 22:03:29 +00002166 FunctionDecl *DefinitionD =
2167 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2168 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00002169
2170 EXPECT_TRUE(DefinitionD->getPreviousDecl());
2171 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
2172 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002173}
2174
2175TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2176 auto Code =
2177 R"(
2178 struct B { virtual void f(); };
2179 void B::f() {}
2180 struct D : B { void f(); };
2181 )";
2182 auto Pattern =
2183 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2184 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2185 CXXMethodDecl *Proto =
2186 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2187
2188 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2189 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2190 EXPECT_EQ(To->size_overridden_methods(), 1u);
2191}
2192
2193TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2194 auto Code =
2195 R"(
2196 struct B { virtual void f(); };
2197 void B::f() {}
2198 )";
2199 auto Pattern =
2200 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2201 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2202 CXXMethodDecl *Proto =
2203 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2204 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2205
2206 ASSERT_TRUE(Proto->isVirtual());
2207 ASSERT_TRUE(Def->isVirtual());
2208 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2209 EXPECT_TRUE(To->isVirtual());
2210}
2211
Gabor Marton5254e642018-06-27 13:32:50 +00002212TEST_P(ImportFunctions,
2213 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2214 Decl *ToTU = getToTuDecl(
2215 R"(
2216 void f() {}
2217 void f();
2218 )",
2219 Lang_CXX);
2220 ASSERT_EQ(1u,
2221 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2222 return FD->doesThisDeclarationHaveABody();
2223 }).match(ToTU, functionDecl()));
2224
2225 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2226 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2227
2228 Import(FromD, Lang_CXX);
2229
2230 EXPECT_EQ(1u,
2231 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2232 return FD->doesThisDeclarationHaveABody();
2233 }).match(ToTU, functionDecl()));
2234}
2235
2236struct ImportFriendFunctions : ImportFunctions {};
2237
2238TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2239 auto Pattern = functionDecl(hasName("f"));
2240
2241 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2242 "void f();",
2243 Lang_CXX,
2244 "input0.cc");
2245 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2246
2247 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2248 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2249 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2250 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2251 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2252 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2253 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2254}
2255
2256TEST_P(ImportFriendFunctions,
2257 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2258 auto Pattern = functionDecl(hasName("f"));
2259
2260 Decl *FromTU = getTuDecl("void f();"
2261 "struct X { friend void f(); };",
2262 Lang_CXX, "input0.cc");
2263 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2264
2265 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2266 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2267 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2268 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2269 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2270 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2271 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2272}
2273
2274TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2275 auto Pattern = functionDecl(hasName("f"));
2276
2277 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2278 "void f();",
2279 Lang_CXX,
2280 "input0.cc");
2281 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2282
2283 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2284 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2285 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2286 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2287 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2288 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2289 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2290}
2291
2292TEST_P(ImportFriendFunctions,
2293 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2294 auto Pattern = functionDecl(hasName("f"));
2295
2296 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2297 "void f(){}",
2298 Lang_CXX, "input0.cc");
2299 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2300
2301 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2302 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2303 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2304 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2305 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2306 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2307 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2308}
2309
Gabor Marton26f72a92018-07-12 09:42:05 +00002310// Disabled temporarily, because the new structural equivalence check
2311// (https://reviews.llvm.org/D48628) breaks it.
2312// PreviousDecl is not set because there is no structural match.
2313// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002314TEST_P(ImportFriendFunctions,
2315 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2316 auto Pattern = functionDecl(hasName("f"));
2317
2318 Decl *FromTU = getTuDecl(
2319 R"(
2320 class X;
2321 void f(X *x){}
2322 class X{
2323 friend void f(X *x);
2324 };
2325 )",
2326 Lang_CXX, "input0.cc");
2327 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2328
2329 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2330 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2331 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2332 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2333 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2334 .match(ToTU, friendDecl())
2335 ->getFriendDecl());
2336 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2337 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2338 // The parameters must refer the same type
2339 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2340 (*ImportedD->param_begin())->getOriginalType());
2341}
2342
Gabor Marton26f72a92018-07-12 09:42:05 +00002343// Disabled temporarily, because the new structural equivalence check
2344// (https://reviews.llvm.org/D48628) breaks it.
2345// PreviousDecl is not set because there is no structural match.
2346// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002347TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002348 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002349 auto Pattern = functionDecl(hasName("f"));
2350
2351 Decl *FromTU = getTuDecl(
2352 R"(
2353 class X;
2354 void f(X *x){}
2355 class X{
2356 friend void f(X *x);
2357 };
2358 )",
2359 Lang_CXX, "input0.cc");
2360 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2361
2362 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2363 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2364 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2365 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2366 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2367 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2368
2369 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2370 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2371 // The parameters must refer the same type
2372 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2373 (*ImportedD->param_begin())->getOriginalType());
2374}
2375
2376TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2377 auto Pattern = functionDecl(hasName("f"));
2378
2379 FunctionDecl *ImportedD;
2380 {
2381 Decl *FromTU =
2382 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2383 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2384 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2385 }
2386 FunctionDecl *ImportedD1;
2387 {
2388 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2389 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2390 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2391 }
2392
2393 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2394 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2395 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2396 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2397 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2398}
2399
Balazs Keri89632b82018-08-21 14:32:21 +00002400TEST_P(ImportFriendFunctions, Lookup) {
2401 auto FunctionPattern = functionDecl(hasName("f"));
2402 auto ClassPattern = cxxRecordDecl(hasName("X"));
2403
2404 TranslationUnitDecl *FromTU =
2405 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2406 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2407 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2408 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2409 {
2410 auto FromName = FromD->getDeclName();
2411 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2412 auto LookupRes = Class->noload_lookup(FromName);
2413 ASSERT_EQ(LookupRes.size(), 0u);
2414 LookupRes = FromTU->noload_lookup(FromName);
2415 ASSERT_EQ(LookupRes.size(), 1u);
2416 }
2417
2418 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2419 auto ToName = ToD->getDeclName();
2420
2421 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2422 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2423 auto LookupRes = Class->noload_lookup(ToName);
2424 EXPECT_EQ(LookupRes.size(), 0u);
2425 LookupRes = ToTU->noload_lookup(ToName);
2426 EXPECT_EQ(LookupRes.size(), 1u);
2427
2428 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2429 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2430 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2431 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2432}
2433
2434TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2435 auto FunctionPattern = functionDecl(hasName("f"));
2436 auto ClassPattern = cxxRecordDecl(hasName("X"));
2437
2438 TranslationUnitDecl *FromTU = getTuDecl(
2439 "struct X { friend void f(); };"
2440 // This proto decl makes f available to normal
2441 // lookup, otherwise it is hidden.
2442 // Normal C++ lookup (implemented in
2443 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2444 // returns the found `NamedDecl` only if the set IDNS is matched
2445 "void f();",
2446 Lang_CXX, "input0.cc");
2447 auto *FromFriend =
2448 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2449 auto *FromNormal =
2450 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2451 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2452 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2453 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2454 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2455
2456 auto FromName = FromFriend->getDeclName();
2457 auto *FromClass =
2458 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2459 auto LookupRes = FromClass->noload_lookup(FromName);
2460 ASSERT_EQ(LookupRes.size(), 0u);
2461 LookupRes = FromTU->noload_lookup(FromName);
2462 ASSERT_EQ(LookupRes.size(), 1u);
2463
2464 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2465 auto ToName = ToFriend->getDeclName();
2466
2467 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2468 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2469 LookupRes = ToClass->noload_lookup(ToName);
2470 EXPECT_EQ(LookupRes.size(), 0u);
2471 LookupRes = ToTU->noload_lookup(ToName);
2472 // Test is disabled because this result is 2.
2473 EXPECT_EQ(LookupRes.size(), 1u);
2474
2475 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2476 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2477 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2478 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2479 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2480 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2481 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2482}
2483
2484TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2485 auto FunctionPattern = functionDecl(hasName("f"));
2486 auto ClassPattern = cxxRecordDecl(hasName("X"));
2487
2488 TranslationUnitDecl *FromTU = getTuDecl(
2489 "void f();"
2490 "struct X { friend void f(); };",
2491 Lang_CXX, "input0.cc");
2492 auto *FromNormal =
2493 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2494 auto *FromFriend =
2495 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2496 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2497 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2498 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2499 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2500
2501 auto FromName = FromNormal->getDeclName();
2502 auto *FromClass =
2503 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2504 auto LookupRes = FromClass->noload_lookup(FromName);
2505 ASSERT_EQ(LookupRes.size(), 0u);
2506 LookupRes = FromTU->noload_lookup(FromName);
2507 ASSERT_EQ(LookupRes.size(), 1u);
2508
2509 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2510 auto ToName = ToNormal->getDeclName();
2511 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2512
2513 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2514 LookupRes = ToClass->noload_lookup(ToName);
2515 EXPECT_EQ(LookupRes.size(), 0u);
2516 LookupRes = ToTU->noload_lookup(ToName);
2517 EXPECT_EQ(LookupRes.size(), 1u);
2518
2519 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2520 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2521 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2522 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2523 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2524 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2525 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2526}
2527
2528TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2529 auto Pattern = functionDecl(hasName("f"));
2530
2531 TranslationUnitDecl *FromNormalTU =
2532 getTuDecl("void f();", Lang_CXX, "input0.cc");
2533 auto *FromNormalF =
2534 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2535 TranslationUnitDecl *FromFriendTU =
2536 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2537 auto *FromFriendF =
2538 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2539 auto FromNormalName = FromNormalF->getDeclName();
2540 auto FromFriendName = FromFriendF->getDeclName();
2541
2542 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2543 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2544 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2545 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2546 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2547 ASSERT_EQ(LookupRes.size(), 1u);
2548 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2549 ASSERT_EQ(LookupRes.size(), 1u);
2550
2551 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2552 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2553 auto ToName = ToNormalF->getDeclName();
2554 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2555 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2556 LookupRes = ToTU->noload_lookup(ToName);
2557 EXPECT_EQ(LookupRes.size(), 1u);
2558 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002559
Balazs Keri89632b82018-08-21 14:32:21 +00002560 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2561 LookupRes = ToTU->noload_lookup(ToName);
2562 EXPECT_EQ(LookupRes.size(), 1u);
2563 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2564
2565 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2566 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2567
2568 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2569 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2570}
2571
2572TEST_P(ImportFriendFunctions, ImportFriendList) {
2573 TranslationUnitDecl *FromTU = getTuDecl(
2574 "struct X { friend void f(); };"
2575 "void f();",
2576 Lang_CXX, "input0.cc");
2577 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2578 FromTU, functionDecl(hasName("f")));
2579
2580 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2581 FromTU, cxxRecordDecl(hasName("X")));
2582 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2583 auto FromFriends = FromClass->friends();
2584 unsigned int FrN = 0;
2585 for (auto Fr : FromFriends) {
2586 ASSERT_EQ(Fr, FromFriend);
2587 ++FrN;
2588 }
2589 ASSERT_EQ(FrN, 1u);
2590
2591 Import(FromFriendF, Lang_CXX);
2592 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2593 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2594 ToTU, cxxRecordDecl(hasName("X")));
2595 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2596 auto ToFriends = ToClass->friends();
2597 FrN = 0;
2598 for (auto Fr : ToFriends) {
2599 EXPECT_EQ(Fr, ToFriend);
2600 ++FrN;
2601 }
2602 EXPECT_EQ(FrN, 1u);
2603}
2604
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002605AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2606 InnerMatcher) {
2607 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2608 return InnerMatcher.matches(*Typedef, Finder, Builder);
2609 return false;
2610}
2611
Gabor Marton19f4f392018-06-25 13:04:37 +00002612TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002613 CodeFiles Samples{{"main.c",
2614 {"void foo();"
2615 "void moo();"
2616 "int main() { foo(); moo(); }",
2617 Lang_C}},
2618
2619 {"foo.c",
2620 {"typedef enum { THING_VALUE } thing_t;"
2621 "void conflict(thing_t type);"
2622 "void foo() { (void)THING_VALUE; }"
2623 "void conflict(thing_t type) {}",
2624 Lang_C}},
2625
2626 {"moo.c",
2627 {"typedef enum { THING_VALUE } thing_t;"
2628 "void conflict(thing_t type);"
2629 "void moo() { conflict(THING_VALUE); }",
2630 Lang_C}}};
2631
2632 auto VerificationMatcher =
2633 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2634 hasTypedefForAnonDecl(hasName("thing_t")));
2635
2636 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2637 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2638
2639 testImportSequence(
2640 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2641 // Just check that there is only one enum decl in the result AST.
2642 "main.c", enumDecl(), VerificationMatcher);
2643
2644 // For different import order, result should be the same.
2645 testImportSequence(
2646 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2647 // Check that there is only one enum decl in the result AST.
2648 "main.c", enumDecl(), VerificationMatcher);
2649}
2650
Peter Szecsice7f3182018-05-07 12:08:27 +00002651const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2652 dependentScopeDeclRefExpr;
2653
Gabor Marton19f4f392018-06-25 13:04:37 +00002654TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002655 MatchVerifier<Decl> Verifier;
2656 testImport("template <typename T> struct S { static T foo; };"
2657 "template <typename T> void declToImport() {"
2658 " (void) S<T>::foo;"
2659 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002660 "void instantiate() { declToImport<int>(); }"
2661 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002662 Lang_CXX11, "", Lang_CXX11, Verifier,
2663 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2664 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2665
2666 testImport("template <typename T> struct S {"
2667 "template<typename S> static void foo(){};"
2668 "};"
2669 "template <typename T> void declToImport() {"
2670 " S<T>::template foo<T>();"
2671 "}"
2672 "void instantiate() { declToImport<int>(); }",
2673 Lang_CXX11, "", Lang_CXX11, Verifier,
2674 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2675 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2676}
2677
2678const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2679 dependentNameType;
2680
Gabor Marton19f4f392018-06-25 13:04:37 +00002681TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002682 MatchVerifier<Decl> Verifier;
2683 testImport("template <typename T> struct declToImport {"
2684 " typedef typename T::type dependent_name;"
2685 "};",
2686 Lang_CXX11, "", Lang_CXX11, Verifier,
2687 classTemplateDecl(has(
2688 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2689}
2690
Gabor Marton19f4f392018-06-25 13:04:37 +00002691TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002692 MatchVerifier<Decl> Verifier;
2693 testImport("struct S { template <typename T> void mem(); };"
2694 "template <typename U> void declToImport() {"
2695 " S s;"
2696 " s.mem<U>();"
2697 "}"
2698 "void instantiate() { declToImport<int>(); }",
2699 Lang_CXX11, "", Lang_CXX11, Verifier,
2700 functionTemplateDecl(has(functionDecl(has(
2701 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2702}
2703
Balazs Keri1d20cc22018-07-16 12:16:39 +00002704class ImportImplicitMethods : public ASTImporterTestBase {
2705public:
2706 static constexpr auto DefaultCode = R"(
2707 struct A { int x; };
2708 void f() {
2709 A a;
2710 A a1(a);
2711 A a2(A{});
2712 a = a1;
2713 a = A{};
2714 a.~A();
2715 })";
2716
2717 template <typename MatcherType>
2718 void testImportOf(
2719 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2720 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2721 }
2722
2723 template <typename MatcherType>
2724 void testNoImportOf(
2725 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2726 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2727 }
2728
2729private:
2730 template <typename MatcherType>
2731 void test(const MatcherType &MethodMatcher,
2732 const char *Code, unsigned int ExpectedCount) {
2733 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2734
2735 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2736 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2737 ToTU, ClassMatcher);
2738
Balazs Keri2f752ba2018-07-16 14:05:18 +00002739 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002740
2741 {
2742 CXXMethodDecl *Method =
2743 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2744 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00002745 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002746 }
2747
Balazs Keri2f752ba2018-07-16 14:05:18 +00002748 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002749
2750 Decl *ImportedClass = nullptr;
2751 {
2752 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2753 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2754 FromTU, ClassMatcher);
2755 ImportedClass = Import(FromClass, Lang_CXX11);
2756 }
2757
2758 EXPECT_EQ(ToClass, ImportedClass);
2759 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2760 ExpectedCount);
2761 }
2762};
2763
2764TEST_P(ImportImplicitMethods, DefaultConstructor) {
2765 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2766}
2767
2768TEST_P(ImportImplicitMethods, CopyConstructor) {
2769 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2770}
2771
2772TEST_P(ImportImplicitMethods, MoveConstructor) {
2773 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2774}
2775
2776TEST_P(ImportImplicitMethods, Destructor) {
2777 testImportOf(cxxDestructorDecl());
2778}
2779
2780TEST_P(ImportImplicitMethods, CopyAssignment) {
2781 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2782}
2783
2784TEST_P(ImportImplicitMethods, MoveAssignment) {
2785 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2786}
2787
2788TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2789 auto Code = R"(
2790 struct A { A() { int x; } };
2791 )";
2792 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2793}
2794
2795TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2796 auto Code = R"(
2797 struct A { A() = default; };
2798 )";
2799 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2800}
2801
2802TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2803 auto Code = R"(
2804 struct A { A() = delete; };
2805 )";
2806 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2807}
2808
2809TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2810 auto Code = R"(
2811 struct A { void f() { } };
2812 )";
2813 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2814}
2815
Balazs Keric7797c42018-07-11 09:37:24 +00002816TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2817 Decl *ToR1;
2818 {
2819 Decl *FromTU = getTuDecl(
2820 "struct A { };", Lang_CXX, "input0.cc");
2821 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2822 FromTU, cxxRecordDecl(hasName("A")));
2823
2824 ToR1 = Import(FromR, Lang_CXX);
2825 }
2826
2827 Decl *ToR2;
2828 {
2829 Decl *FromTU = getTuDecl(
2830 "struct A { };", Lang_CXX, "input1.cc");
2831 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2832 FromTU, cxxRecordDecl(hasName("A")));
2833
2834 ToR2 = Import(FromR, Lang_CXX);
2835 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002836
Balazs Keric7797c42018-07-11 09:37:24 +00002837 EXPECT_EQ(ToR1, ToR2);
2838}
2839
2840TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2841 Decl *ToR1;
2842 {
2843 Decl *FromTU = getTuDecl(
2844 "struct A { int x; };", Lang_CXX, "input0.cc");
2845 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2846 FromTU, cxxRecordDecl(hasName("A")));
2847 ToR1 = Import(FromR, Lang_CXX);
2848 }
2849 Decl *ToR2;
2850 {
2851 Decl *FromTU = getTuDecl(
2852 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2853 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2854 FromTU, cxxRecordDecl(hasName("A")));
2855 ToR2 = Import(FromR, Lang_CXX);
2856 }
2857 EXPECT_NE(ToR1, ToR2);
2858}
2859
2860TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2861 Decl *ToF1;
2862 {
2863 Decl *FromTU = getTuDecl(
2864 "struct A { int x; };", Lang_CXX, "input0.cc");
2865 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2866 FromTU, fieldDecl(hasName("x")));
2867 ToF1 = Import(FromF, Lang_CXX);
2868 }
2869 Decl *ToF2;
2870 {
2871 Decl *FromTU = getTuDecl(
2872 "struct A { int x; };", Lang_CXX, "input1.cc");
2873 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2874 FromTU, fieldDecl(hasName("x")));
2875 ToF2 = Import(FromF, Lang_CXX);
2876 }
2877 EXPECT_EQ(ToF1, ToF2);
2878}
2879
2880TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2881 Decl *ToF1;
2882 {
2883 Decl *FromTU = getTuDecl(
2884 "struct A { int x; };", Lang_CXX, "input0.cc");
2885 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2886 FromTU, fieldDecl(hasName("x")));
2887 ToF1 = Import(FromF, Lang_CXX);
2888 }
2889 Decl *ToF2;
2890 {
2891 Decl *FromTU = getTuDecl(
2892 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2893 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2894 FromTU, fieldDecl(hasName("x")));
2895 ToF2 = Import(FromF, Lang_CXX);
2896 }
2897 EXPECT_NE(ToF1, ToF2);
2898}
2899
2900TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2901 Decl *ToM1;
2902 {
2903 Decl *FromTU = getTuDecl(
2904 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2905 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2906 FromTU, functionDecl(hasName("x"), isDefinition()));
2907 ToM1 = Import(FromM, Lang_CXX);
2908 }
2909 Decl *ToM2;
2910 {
2911 Decl *FromTU = getTuDecl(
2912 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2913 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2914 FromTU, functionDecl(hasName("x"), isDefinition()));
2915 ToM2 = Import(FromM, Lang_CXX);
2916 }
2917 EXPECT_EQ(ToM1, ToM2);
2918}
2919
2920TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2921 Decl *ToM1;
2922 {
2923 Decl *FromTU = getTuDecl(
2924 "struct A { void x(); }; void A::x() { }",
2925 Lang_CXX, "input0.cc");
2926 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2927 FromTU, functionDecl(hasName("x"), isDefinition()));
2928 ToM1 = Import(FromM, Lang_CXX);
2929 }
2930 Decl *ToM2;
2931 {
2932 Decl *FromTU = getTuDecl(
2933 "struct A { void x() const; }; void A::x() const { }",
2934 Lang_CXX, "input1.cc");
2935 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2936 FromTU, functionDecl(hasName("x"), isDefinition()));
2937 ToM2 = Import(FromM, Lang_CXX);
2938 }
2939 EXPECT_NE(ToM1, ToM2);
2940}
2941
Gabor Martonf086fa82018-07-17 12:06:36 +00002942TEST_P(ASTImporterTestBase, ImportUnnamedStructsWithRecursingField) {
2943 Decl *FromTU = getTuDecl(
2944 R"(
2945 struct A {
2946 struct {
2947 struct A *next;
2948 } entry0;
2949 struct {
2950 struct A *next;
2951 } entry1;
2952 };
2953 )",
2954 Lang_C, "input0.cc");
2955 auto *From =
2956 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
2957
2958 Import(From, Lang_C);
2959
2960 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2961 auto *Entry0 =
2962 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
2963 auto *Entry1 =
2964 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
2965 auto *R0 = getRecordDecl(Entry0);
2966 auto *R1 = getRecordDecl(Entry1);
2967 EXPECT_NE(R0, R1);
2968 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2969 R0, recordDecl(has(fieldDecl(hasName("next"))))));
2970 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
2971 R1, recordDecl(has(fieldDecl(hasName("next"))))));
2972}
2973
Balazs Keri2544b4b2018-08-08 09:40:57 +00002974TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
2975 Decl *FromTU = getTuDecl(
2976 R"(
2977 void f(int X, int Y, bool Z) {
2978 (void)[X, Y, Z] { (void)Z; };
2979 }
2980 )",
2981 Lang_CXX11, "input0.cc");
2982 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
2983 FromTU, functionDecl(hasName("f")));
2984 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
2985 EXPECT_TRUE(ToF);
2986
2987 CXXRecordDecl *FromLambda =
2988 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
2989 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
2990
2991 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
2992 EXPECT_TRUE(ToLambda);
2993
2994 // Check if the fields of the lambda class are imported in correct order.
2995 unsigned FromIndex = 0u;
2996 for (auto *FromField : FromLambda->fields()) {
2997 ASSERT_FALSE(FromField->getDeclName());
2998 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
2999 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003000 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3001 EXPECT_TRUE(ToIndex);
3002 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003003 ++FromIndex;
3004 }
3005
3006 EXPECT_EQ(FromIndex, 3u);
3007}
3008
Gabor Marton42e15de2018-08-22 11:52:14 +00003009TEST_P(ASTImporterTestBase, MergeFieldDeclsOfClassTemplateSpecialization) {
3010 std::string ClassTemplate =
3011 R"(
3012 template <typename T>
3013 struct X {
3014 int a{0}; // FieldDecl with InitListExpr
3015 X(char) : a(3) {} // (1)
3016 X(int) {} // (2)
3017 };
3018 )";
3019 Decl *ToTU = getToTuDecl(ClassTemplate +
3020 R"(
3021 void foo() {
3022 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3023 X<char> xc('c');
3024 }
3025 )", Lang_CXX11);
3026 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3027 ToTU, classTemplateSpecializationDecl(hasName("X")));
3028 // FieldDecl without InitlistExpr:
3029 auto *ToField = *ToSpec->field_begin();
3030 ASSERT_TRUE(ToField);
3031 ASSERT_FALSE(ToField->getInClassInitializer());
3032 Decl *FromTU = getTuDecl(ClassTemplate +
3033 R"(
3034 void bar() {
3035 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3036 X<char> xc(1);
3037 }
3038 )", Lang_CXX11);
3039 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3040 FromTU, classTemplateSpecializationDecl(hasName("X")));
3041 // FieldDecl with InitlistExpr:
3042 auto *FromField = *FromSpec->field_begin();
3043 ASSERT_TRUE(FromField);
3044 ASSERT_TRUE(FromField->getInClassInitializer());
3045
3046 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3047 ASSERT_TRUE(ImportedSpec);
3048 EXPECT_EQ(ImportedSpec, ToSpec);
3049 // After the import, the FieldDecl has to be merged, thus it should have the
3050 // InitListExpr.
3051 EXPECT_TRUE(ToField->getInClassInitializer());
3052}
3053
3054TEST_P(ASTImporterTestBase, MergeFunctionOfClassTemplateSpecialization) {
3055 std::string ClassTemplate =
3056 R"(
3057 template <typename T>
3058 struct X {
3059 void f() {}
3060 void g() {}
3061 };
3062 )";
3063 Decl *ToTU = getToTuDecl(ClassTemplate +
3064 R"(
3065 void foo() {
3066 X<char> x;
3067 x.f();
3068 }
3069 )", Lang_CXX11);
3070 Decl *FromTU = getTuDecl(ClassTemplate +
3071 R"(
3072 void bar() {
3073 X<char> x;
3074 x.g();
3075 }
3076 )", Lang_CXX11);
3077 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3078 FromTU, classTemplateSpecializationDecl(hasName("X")));
3079 auto FunPattern = functionDecl(hasName("g"),
3080 hasParent(classTemplateSpecializationDecl()));
3081 auto *FromFun =
3082 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3083 auto *ToFun =
3084 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3085 ASSERT_TRUE(FromFun->hasBody());
3086 ASSERT_FALSE(ToFun->hasBody());
3087 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3088 ASSERT_TRUE(ImportedSpec);
3089 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3090 ToTU, classTemplateSpecializationDecl(hasName("X")));
3091 EXPECT_EQ(ImportedSpec, ToSpec);
3092 EXPECT_TRUE(ToFun->hasBody());
3093}
3094
3095TEST_P(ASTImporterTestBase,
3096 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3097 std::string ClassTemplate =
3098 R"(
3099 template <typename T>
3100 struct X {};
3101 )";
3102 Decl *ToTU = getToTuDecl(ClassTemplate +
3103 R"(
3104 template <>
3105 struct X<char> {
3106 int a;
3107 };
3108 void foo() {
3109 X<char> x;
3110 }
3111 )",
3112 Lang_CXX11);
3113 Decl *FromTU = getTuDecl(ClassTemplate +
3114 R"(
3115 template <>
3116 struct X<char> {
3117 int b;
3118 };
3119 void foo() {
3120 X<char> x;
3121 }
3122 )",
3123 Lang_CXX11);
3124 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3125 FromTU, classTemplateSpecializationDecl(hasName("X")));
3126 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3127
3128 // We expect one (ODR) warning during the import.
3129 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3130
3131 // The second specialization is different from the first, thus it violates
3132 // ODR, consequently we expect to keep the first specialization only, which is
3133 // already in the "To" context.
3134 EXPECT_TRUE(ImportedSpec);
3135 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3136 ToTU, classTemplateSpecializationDecl(hasName("X")));
3137 EXPECT_EQ(ImportedSpec, ToSpec);
3138 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3139 ToTU, classTemplateSpecializationDecl()));
3140}
3141
3142TEST_P(ASTImporterTestBase, MergeCtorOfClassTemplateSpecialization) {
3143 std::string ClassTemplate =
3144 R"(
3145 template <typename T>
3146 struct X {
3147 X(char) {}
3148 X(int) {}
3149 };
3150 )";
3151 Decl *ToTU = getToTuDecl(ClassTemplate +
3152 R"(
3153 void foo() {
3154 X<char> x('c');
3155 }
3156 )", Lang_CXX11);
3157 Decl *FromTU = getTuDecl(ClassTemplate +
3158 R"(
3159 void bar() {
3160 X<char> x(1);
3161 }
3162 )", Lang_CXX11);
3163 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3164 FromTU, classTemplateSpecializationDecl(hasName("X")));
3165 // Match the void(int) ctor.
3166 auto CtorPattern =
3167 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3168 hasParent(classTemplateSpecializationDecl()));
3169 auto *FromCtor =
3170 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3171 auto *ToCtor =
3172 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3173 ASSERT_TRUE(FromCtor->hasBody());
3174 ASSERT_FALSE(ToCtor->hasBody());
3175 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3176 ASSERT_TRUE(ImportedSpec);
3177 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3178 ToTU, classTemplateSpecializationDecl(hasName("X")));
3179 EXPECT_EQ(ImportedSpec, ToSpec);
3180 EXPECT_TRUE(ToCtor->hasBody());
3181}
3182
3183TEST_P(ASTImporterTestBase,
3184 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3185 auto Code =
3186 R"(
3187 // primary template
3188 template<class T1, class T2, int I>
3189 class A {};
3190
3191 // partial specialization
3192 template<class T, int I>
3193 class A<T, T*, I> {};
3194 )";
3195 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3196 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3197 auto *FromSpec =
3198 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3199 FromTU, classTemplatePartialSpecializationDecl());
3200 auto *ToSpec =
3201 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3202 ToTU, classTemplatePartialSpecializationDecl());
3203
3204 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3205 EXPECT_EQ(ImportedSpec, ToSpec);
3206 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3207 ToTU, classTemplatePartialSpecializationDecl()));
3208}
3209
3210TEST_P(ASTImporterTestBase, ClassTemplateSpecializationsShouldNotBeDuplicated) {
3211 auto Code =
3212 R"(
3213 // primary template
3214 template<class T1, class T2, int I>
3215 class A {};
3216
3217 // full specialization
3218 template<>
3219 class A<int, int, 1> {};
3220 )";
3221 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3222 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3223 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3224 FromTU, classTemplateSpecializationDecl());
3225 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3226 ToTU, classTemplateSpecializationDecl());
3227
3228 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3229 EXPECT_EQ(ImportedSpec, ToSpec);
3230 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3231 ToTU, classTemplateSpecializationDecl()));
3232}
3233
3234TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3235 std::string PrimaryTemplate =
3236 R"(
3237 template<class T1, class T2, int I>
3238 class A {};
3239 )";
3240 auto PartialSpec =
3241 R"(
3242 template<class T, int I>
3243 class A<T, T*, I> {};
3244 )";
3245 auto FullSpec =
3246 R"(
3247 template<>
3248 class A<int, int, 1> {};
3249 )";
3250 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3251 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3252 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3253 FromTU, classTemplateSpecializationDecl());
3254
3255 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3256 EXPECT_TRUE(ImportedSpec);
3257 // Check the number of partial specializations.
3258 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3259 ToTU, classTemplatePartialSpecializationDecl()));
3260 // Check the number of full specializations.
3261 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3262 ToTU, classTemplateSpecializationDecl(
3263 unless(classTemplatePartialSpecializationDecl()))));
3264}
3265
Gabor Martona20ce602018-09-03 13:10:53 +00003266TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) {
3267 Decl *TU = getTuDecl(
3268 R"(
3269 const int &init();
3270 void foo() { const int &a{init()}; }
3271 )", Lang_CXX11, "input0.cc");
3272 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3273 ASSERT_TRUE(FromD->getAnyInitializer());
3274 auto *InitExpr = FromD->getAnyInitializer();
3275 ASSERT_TRUE(InitExpr);
3276 ASSERT_TRUE(InitExpr->isGLValue());
3277
3278 auto *ToD = Import(FromD, Lang_CXX11);
3279 EXPECT_TRUE(ToD);
3280 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3281 EXPECT_TRUE(ToInitExpr);
3282 EXPECT_TRUE(ToInitExpr->isGLValue());
3283}
3284
Gabor Martonac3a5d62018-09-17 12:04:52 +00003285struct ImportVariables : ASTImporterTestBase {};
3286
3287TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3288 Decl *FromTU = getTuDecl(
3289 R"(
3290 struct A {
3291 static const int a = 1 + 2;
3292 };
3293 const int A::a;
3294 )", Lang_CXX, "input1.cc");
3295
3296 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3297 FromTU, varDecl(hasName("a"))); // Decl with init
3298 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3299 FromTU, varDecl(hasName("a"))); // Decl with definition
3300 ASSERT_NE(FromDWithInit, FromDWithDef);
3301 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3302
3303 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3304 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3305 ASSERT_TRUE(ToD0);
3306 ASSERT_TRUE(ToD1);
3307 EXPECT_NE(ToD0, ToD1);
3308 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3309}
3310
3311TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3312 auto StructA =
3313 R"(
3314 struct A {
3315 static const int a = 1 + 2;
3316 };
3317 )";
3318 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3319 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3320 "input1.cc");
3321
3322 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3323 FromTU, varDecl(hasName("a"))); // Decl with init
3324 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3325 FromTU, varDecl(hasName("a"))); // Decl with definition
3326 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3327 ASSERT_TRUE(FromDWithInit->getInit());
3328 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3329 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3330 ASSERT_FALSE(FromDWithDef->getInit());
3331
3332 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3333 ToTU, varDecl(hasName("a"))); // Decl with init
3334 ASSERT_TRUE(ToD->getInit());
3335 ASSERT_FALSE(ToD->getDefinition());
3336
3337 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3338 EXPECT_TRUE(ImportedD->getAnyInitializer());
3339 EXPECT_TRUE(ImportedD->getDefinition());
3340}
3341
3342TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3343 auto StructA =
3344 R"(
3345 struct A {
3346 static const int a;
3347 };
3348 )";
3349 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3350 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3351 Lang_CXX, "input1.cc");
3352
3353 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3354 FromTU, varDecl(hasName("a")));
3355 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3356 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3357 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3358 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3359 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3360 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3361 ASSERT_TRUE(FromDWithDef->getInit());
3362
3363 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3364 ToTU, varDecl(hasName("a")));
3365 ASSERT_FALSE(ToD->getInit());
3366 ASSERT_FALSE(ToD->getDefinition());
3367
3368 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3369 EXPECT_TRUE(ImportedD->getAnyInitializer());
3370 EXPECT_TRUE(ImportedD->getDefinition());
3371}
3372
Gabor Marton7df342a2018-12-17 12:42:12 +00003373struct ImportClasses : ASTImporterTestBase {};
3374
3375TEST_P(ImportClasses,
3376 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3377 Decl *FromTU = getTuDecl("class X;", Lang_CXX);
3378 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3379 auto FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3380
3381 Decl *ImportedD = Import(FromD, Lang_CXX);
3382 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3383
3384 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3385 auto ToD = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3386 EXPECT_TRUE(ImportedD == ToD);
3387 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3388}
3389
3390TEST_P(ImportClasses, ImportPrototypeAfterImportedPrototype) {
3391 Decl *FromTU = getTuDecl("class X; class X;", Lang_CXX);
3392 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3393 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3394 auto From1 = LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3395
3396 Decl *Imported0 = Import(From0, Lang_CXX);
3397 Decl *Imported1 = Import(From1, Lang_CXX);
3398 Decl *ToTU = Imported0->getTranslationUnitDecl();
3399
3400 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3401 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3402 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3403 EXPECT_TRUE(Imported0 == To0);
3404 EXPECT_TRUE(Imported1 == To1);
3405 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3406 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3407 EXPECT_EQ(To1->getPreviousDecl(), To0);
3408}
3409
3410TEST_P(ImportClasses, DefinitionShouldBeImportedAsADefinition) {
3411 Decl *FromTU = getTuDecl("class X {};", Lang_CXX);
3412 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3413 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
3414
3415 Decl *ImportedD = Import(FromD, Lang_CXX);
3416 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3417
3418 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3419 EXPECT_TRUE(cast<CXXRecordDecl>(ImportedD)->isThisDeclarationADefinition());
3420}
3421
3422TEST_P(ImportClasses, ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3423 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3424 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3425 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3426 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3427 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3428
3429 Decl *Imported0 = Import(From0, Lang_CXX);
3430 Decl *Imported1 = Import(From1, Lang_CXX);
3431 Decl *ToTU = Imported0->getTranslationUnitDecl();
3432
3433 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3434 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3435 auto To1 = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3436 EXPECT_TRUE(Imported0 == To0);
3437 EXPECT_TRUE(Imported1 == To1);
3438 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3439 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3440 EXPECT_EQ(To1->getPreviousDecl(), To0);
3441}
3442
3443TEST_P(ImportClasses, ImportDefinitions) {
3444 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3445 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3446 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3447 auto From0 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3448 auto From1 = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3449
3450 Decl *Imported0 = Import(From0, Lang_CXX);
3451 Decl *Imported1 = Import(From1, Lang_CXX);
3452 Decl *ToTU = Imported0->getTranslationUnitDecl();
3453
3454 EXPECT_EQ(Imported0, Imported1);
3455 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 1u);
3456 auto To0 = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3457 EXPECT_TRUE(Imported0 == To0);
3458 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3459}
3460
3461TEST_P(ImportClasses, ImportDefinitionThenPrototype) {
3462 Decl *FromTU0 = getTuDecl("class X {};", Lang_CXX, "input0.cc");
3463 Decl *FromTU1 = getTuDecl("class X;", Lang_CXX, "input1.cc");
3464 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3465 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3466 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3467
3468 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3469 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3470 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3471
3472 EXPECT_NE(ImportedDef, ImportedProto);
3473 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3474 auto ToDef = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3475 auto ToProto = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3476 EXPECT_TRUE(ImportedDef == ToDef);
3477 EXPECT_TRUE(ImportedProto == ToProto);
3478 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3479 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3480 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3481}
3482
3483TEST_P(ImportClasses, ImportPrototypeThenDefinition) {
3484 Decl *FromTU0 = getTuDecl("class X;", Lang_CXX, "input0.cc");
3485 Decl *FromTU1 = getTuDecl("class X {};", Lang_CXX, "input1.cc");
3486 auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
3487 auto FromProto = FirstDeclMatcher<CXXRecordDecl>().match(FromTU0, Pattern);
3488 auto FromDef = FirstDeclMatcher<CXXRecordDecl>().match(FromTU1, Pattern);
3489
3490 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3491 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3492 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3493
3494 EXPECT_NE(ImportedDef, ImportedProto);
3495 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, Pattern), 2u);
3496 auto ToProto = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3497 auto ToDef = LastDeclMatcher<CXXRecordDecl>().match(ToTU, Pattern);
3498 EXPECT_TRUE(ImportedDef == ToDef);
3499 EXPECT_TRUE(ImportedProto == ToProto);
3500 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3501 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3502 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3503}
3504
Gabor Marton54058b52018-12-17 13:53:12 +00003505TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInToContext) {
3506 Decl *ToTU = getToTuDecl("struct X;", Lang_C);
3507 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3508 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3509 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3510 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3511
3512 Decl *ImportedDef = Import(FromDef, Lang_C);
3513
3514 EXPECT_NE(ImportedDef, ToProto);
3515 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3516 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3517 EXPECT_TRUE(ImportedDef == ToDef);
3518 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3519 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3520 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3521}
3522
3523TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3524 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3525 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3526 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3527 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3528 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3529
3530 Decl *ImportedDef = Import(FromDef, Lang_C);
3531
3532 EXPECT_NE(ImportedDef, ToProto);
3533 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3534 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3535 EXPECT_TRUE(ImportedDef == ToDef);
3536 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3537 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3538 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3539}
3540
3541TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3542 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3543 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3544 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3545 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3546 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3547
3548 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3549
3550 EXPECT_NE(ImportedDef, ToProto);
3551 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3552 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3553 EXPECT_TRUE(ImportedDef == ToDef);
3554 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3555 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3556 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3557}
3558
3559TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3560 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3561 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3562 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3563 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3564 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3565
3566 Decl *ImportedProto = Import(FromProto, Lang_C);
3567 Decl *ImportedDef = Import(FromDef, Lang_C);
3568 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3569
3570 EXPECT_NE(ImportedDef, ImportedProto);
3571 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3572 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3573 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3574 EXPECT_TRUE(ImportedDef == ToDef);
3575 EXPECT_TRUE(ImportedProto == ToProto);
3576 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3577 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3578 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3579}
3580
Gabor Marton7df342a2018-12-17 12:42:12 +00003581struct ImportClassTemplates : ASTImporterTestBase {};
3582
3583TEST_P(ImportClassTemplates,
3584 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
3585 Decl *FromTU = getTuDecl("template <class T> class X;", Lang_CXX);
3586 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3587 auto FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3588
3589 Decl *ImportedD = Import(FromD, Lang_CXX);
3590 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3591
3592 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3593 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3594 EXPECT_TRUE(ImportedD == ToD);
3595 ASSERT_TRUE(ToD->getTemplatedDecl());
3596 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3597}
3598
3599TEST_P(ImportClassTemplates, ImportPrototypeAfterImportedPrototype) {
3600 Decl *FromTU = getTuDecl(
3601 "template <class T> class X; template <class T> class X;", Lang_CXX);
3602 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3603 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3604 auto From1 = LastDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3605
3606 Decl *Imported0 = Import(From0, Lang_CXX);
3607 Decl *Imported1 = Import(From1, Lang_CXX);
3608 Decl *ToTU = Imported0->getTranslationUnitDecl();
3609
3610 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3611 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3612 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3613 EXPECT_TRUE(Imported0 == To0);
3614 EXPECT_TRUE(Imported1 == To1);
3615 ASSERT_TRUE(To0->getTemplatedDecl());
3616 ASSERT_TRUE(To1->getTemplatedDecl());
3617 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3618 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3619 EXPECT_EQ(To1->getPreviousDecl(), To0);
3620 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3621 To0->getTemplatedDecl());
3622}
3623
3624TEST_P(ImportClassTemplates, DefinitionShouldBeImportedAsADefinition) {
3625 Decl *FromTU = getTuDecl("template <class T> class X {};", Lang_CXX);
3626 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3627 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
3628
3629 Decl *ImportedD = Import(FromD, Lang_CXX);
3630 Decl *ToTU = ImportedD->getTranslationUnitDecl();
3631
3632 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3633 auto ToD = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3634 ASSERT_TRUE(ToD->getTemplatedDecl());
3635 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3636}
3637
3638TEST_P(ImportClassTemplates,
3639 ImportPrototypeFromDifferentTUAfterImportedPrototype) {
3640 Decl *FromTU0 =
3641 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3642 Decl *FromTU1 =
3643 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3644 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3645 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3646 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3647
3648 Decl *Imported0 = Import(From0, Lang_CXX);
3649 Decl *Imported1 = Import(From1, Lang_CXX);
3650 Decl *ToTU = Imported0->getTranslationUnitDecl();
3651
3652 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3653 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3654 auto To1 = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3655 EXPECT_TRUE(Imported0 == To0);
3656 EXPECT_TRUE(Imported1 == To1);
3657 ASSERT_TRUE(To0->getTemplatedDecl());
3658 ASSERT_TRUE(To1->getTemplatedDecl());
3659 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3660 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3661 EXPECT_EQ(To1->getPreviousDecl(), To0);
3662 EXPECT_EQ(To1->getTemplatedDecl()->getPreviousDecl(),
3663 To0->getTemplatedDecl());
3664}
3665
3666TEST_P(ImportClassTemplates, ImportDefinitions) {
3667 Decl *FromTU0 =
3668 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3669 Decl *FromTU1 =
3670 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3671 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3672 auto From0 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3673 auto From1 = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3674
3675 Decl *Imported0 = Import(From0, Lang_CXX);
3676 Decl *Imported1 = Import(From1, Lang_CXX);
3677 Decl *ToTU = Imported0->getTranslationUnitDecl();
3678
3679 EXPECT_EQ(Imported0, Imported1);
3680 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 1u);
3681 auto To0 = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3682 EXPECT_TRUE(Imported0 == To0);
3683 ASSERT_TRUE(To0->getTemplatedDecl());
3684 EXPECT_TRUE(To0->isThisDeclarationADefinition());
3685}
3686
3687TEST_P(ImportClassTemplates, ImportDefinitionThenPrototype) {
3688 Decl *FromTU0 =
3689 getTuDecl("template <class T> class X {};", Lang_CXX, "input0.cc");
3690 Decl *FromTU1 =
3691 getTuDecl("template <class T> class X;", Lang_CXX, "input1.cc");
3692 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3693 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3694 auto FromProto =
3695 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3696
3697 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3698 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3699 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3700
3701 EXPECT_NE(ImportedDef, ImportedProto);
3702 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3703 auto ToDef = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3704 auto ToProto = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3705 EXPECT_TRUE(ImportedDef == ToDef);
3706 EXPECT_TRUE(ImportedProto == ToProto);
3707 ASSERT_TRUE(ToDef->getTemplatedDecl());
3708 ASSERT_TRUE(ToProto->getTemplatedDecl());
3709 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3710 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3711 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
3712 EXPECT_EQ(ToProto->getTemplatedDecl()->getPreviousDecl(),
3713 ToDef->getTemplatedDecl());
3714}
3715
3716TEST_P(ImportClassTemplates, ImportPrototypeThenDefinition) {
3717 Decl *FromTU0 =
3718 getTuDecl("template <class T> class X;", Lang_CXX, "input0.cc");
3719 Decl *FromTU1 =
3720 getTuDecl("template <class T> class X {};", Lang_CXX, "input1.cc");
3721 auto Pattern = classTemplateDecl(hasName("X"), unless(isImplicit()));
3722 auto FromProto =
3723 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU0, Pattern);
3724 auto FromDef = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU1, Pattern);
3725
3726 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3727 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3728 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3729
3730 EXPECT_NE(ImportedDef, ImportedProto);
3731 EXPECT_EQ(DeclCounter<ClassTemplateDecl>().match(ToTU, Pattern), 2u);
3732 auto ToProto = FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3733 auto ToDef = LastDeclMatcher<ClassTemplateDecl>().match(ToTU, Pattern);
3734 EXPECT_TRUE(ImportedDef == ToDef);
3735 EXPECT_TRUE(ImportedProto == ToProto);
3736 ASSERT_TRUE(ToProto->getTemplatedDecl());
3737 ASSERT_TRUE(ToDef->getTemplatedDecl());
3738 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3739 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3740 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3741 EXPECT_EQ(ToDef->getTemplatedDecl()->getPreviousDecl(),
3742 ToProto->getTemplatedDecl());
3743}
3744
3745struct ImportFriendClasses : ASTImporterTestBase {};
3746
3747TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3748 Decl *FromTU = getTuDecl(
3749 R"(
3750 class A {
3751 template <int I> class F {};
3752 class X {
3753 template <int I> friend class F;
3754 };
3755 };
3756 )",
3757 Lang_CXX, "input0.cc");
3758
3759 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3760 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3761 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3762 FromTU, cxxRecordDecl(hasName("F")));
3763
3764 ASSERT_TRUE(FromClass);
3765 ASSERT_TRUE(FromFriendClass);
3766 ASSERT_NE(FromClass, FromFriendClass);
3767 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3768 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3769 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3770 FromClass->getDescribedClassTemplate());
3771
3772 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3773 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3774
3775 EXPECT_TRUE(ToClass);
3776 EXPECT_TRUE(ToFriendClass);
3777 EXPECT_NE(ToClass, ToFriendClass);
3778 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3779 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3780 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3781 ToClass->getDescribedClassTemplate());
3782}
3783
3784TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3785 Decl *FromTu = getTuDecl(
3786 R"(
3787 class declToImport {
3788 friend class declToImport;
3789 };
3790 )",
3791 Lang_CXX, "input.cc");
3792
3793 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3794 FromTu, cxxRecordDecl(hasName("declToImport")));
3795 auto *ToD = Import(FromD, Lang_CXX);
3796 auto Pattern = cxxRecordDecl(has(friendDecl()));
3797 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3798 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3799}
3800
3801TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3802 Decl *FromTu = getTuDecl(
3803 R"(
3804 template<class A> class declToImport {
3805 template<class A1> friend class declToImport;
3806 };
3807 )",
3808 Lang_CXX, "input.cc");
3809
3810 auto *FromD =
3811 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3812 auto *ToD = Import(FromD, Lang_CXX);
3813
3814 auto Pattern = classTemplateDecl(
3815 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3816 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3817 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3818
3819 auto *Class =
3820 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3821 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3822 EXPECT_NE(Friend->getFriendDecl(), Class);
3823 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3824}
3825
3826TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3827 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3828
3829 ClassTemplateSpecializationDecl *Imported1;
3830 {
3831 Decl *FromTU = getTuDecl("template<class T> class X;"
3832 "struct Y { friend class X<int>; };",
3833 Lang_CXX, "input0.cc");
3834 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3835 FromTU, Pattern);
3836
3837 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3838 }
3839 ClassTemplateSpecializationDecl *Imported2;
3840 {
3841 Decl *FromTU = getTuDecl("template<class T> class X;"
3842 "template<> class X<int>{};"
3843 "struct Z { friend class X<int>; };",
3844 Lang_CXX, "input1.cc");
3845 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3846 FromTU, Pattern);
3847
3848 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3849 }
3850
3851 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3852 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3853 2u);
3854 ASSERT_TRUE(Imported2->getPreviousDecl());
3855 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3856}
3857
3858TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3859 Decl *FromTU0 = getTuDecl(
3860 R"(
3861 class X {
3862 class Y;
3863 };
3864 class X::Y {
3865 template <typename T>
3866 friend class F; // The decl context of F is the global namespace.
3867 };
3868 )",
3869 Lang_CXX, "input0.cc");
3870 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3871 FromTU0, classTemplateDecl(hasName("F")));
3872 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3873 Decl *FromTU1 = getTuDecl(
3874 R"(
3875 template <typename T>
3876 class F {};
3877 )",
3878 Lang_CXX, "input1.cc");
3879 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3880 FromTU1, classTemplateDecl(hasName("F")));
3881 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3882 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3883 Imported1->getTemplatedDecl()->getTypeForDecl());
3884}
3885
3886TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3887 Decl *From, *To;
3888 std::tie(From, To) =
3889 getImportedDecl("class declToImport {};", Lang_CXX,
3890 "class Y { friend class declToImport; };", Lang_CXX);
3891 auto *Imported = cast<CXXRecordDecl>(To);
3892
3893 EXPECT_TRUE(Imported->getPreviousDecl());
3894}
3895
3896TEST_P(ImportFriendClasses,
3897 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3898 Decl *ToTU = getToTuDecl(
3899 R"(
3900 class X {
3901 class Y;
3902 };
3903 class X::Y {
3904 template <typename T>
3905 friend class F; // The decl context of F is the global namespace.
3906 };
3907 )",
3908 Lang_CXX);
3909 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3910 ToTU, classTemplateDecl(hasName("F")));
3911 Decl *FromTU = getTuDecl(
3912 R"(
3913 template <typename T>
3914 class F {};
3915 )",
3916 Lang_CXX, "input0.cc");
3917 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3918 FromTU, classTemplateDecl(hasName("F")));
3919 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3920 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3921 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3922 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3923 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3924}
3925
3926TEST_P(ImportFriendClasses,
3927 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3928 Decl *FromTU0 = getTuDecl(
3929 R"(
3930 class X {
3931 class Y;
3932 };
3933 class X::Y {
3934 template <typename T>
3935 friend class F; // The decl context of F is the global namespace.
3936 };
3937 )",
3938 Lang_CXX, "input0.cc");
3939 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3940 FromTU0, classTemplateDecl(hasName("F")));
3941 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3942 Decl *FromTU1 = getTuDecl(
3943 R"(
3944 template <typename T>
3945 class F {};
3946 )",
3947 Lang_CXX, "input1.cc");
3948 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3949 FromTU1, classTemplateDecl(hasName("F")));
3950 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3951 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3952 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3953 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3954 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3955}
3956
3957TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3958 Decl *FromTU0 = getTuDecl(
3959 R"(
3960 class X {
3961 class Y;
3962 };
3963 class X::Y {
3964 friend class F; // The decl context of F is the global namespace.
3965 };
3966 )",
3967 Lang_CXX, "input0.cc");
3968 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3969 QualType FT = Friend->getFriendType()->getType();
3970 FT = FromTU0->getASTContext().getCanonicalType(FT);
3971 auto *Fwd = cast<TagType>(FT)->getDecl();
3972 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3973 Decl *FromTU1 = getTuDecl(
3974 R"(
3975 class F {};
3976 )",
3977 Lang_CXX, "input1.cc");
3978 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3979 FromTU1, cxxRecordDecl(hasName("F")));
3980 auto *ImportedDef = Import(Definition, Lang_CXX);
3981 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3982 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3983}
3984
Gabor Marton54058b52018-12-17 13:53:12 +00003985TEST_P(ASTImporterTestBase, FriendFunInClassTemplate) {
3986 auto *Code = R"(
3987 template <class T>
3988 struct X {
3989 friend void foo(){}
3990 };
3991 )";
3992 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3993 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3994 ToTU, functionDecl(hasName("foo")));
3995
3996 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3997 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3998 FromTU, functionDecl(hasName("foo")));
3999 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4000 EXPECT_EQ(ImportedFoo, ToFoo);
4001}
4002
Gabor Marton61d862a2018-05-18 09:08:47 +00004003struct DeclContextTest : ASTImporterTestBase {};
4004
4005TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4006 Decl *TU = getTuDecl(
4007 R"(
4008 namespace NS {
4009
4010 template <typename T>
4011 struct S {};
4012 template struct S<int>;
4013
4014 inline namespace INS {
4015 template <typename T>
4016 struct S {};
4017 template struct S<int>;
4018 }
4019
4020 }
4021 )", Lang_CXX11, "input0.cc");
4022 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4023 TU, namespaceDecl());
4024 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4025 TU, classTemplateSpecializationDecl());
4026 ASSERT_TRUE(NS->containsDecl(Spec));
4027
4028 NS->removeDecl(Spec);
4029 EXPECT_FALSE(NS->containsDecl(Spec));
4030}
4031
Gabor Marton7df342a2018-12-17 12:42:12 +00004032TEST_P(DeclContextTest,
4033 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4034 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4035 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4036 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4037
4038 // Investigate the list.
4039 auto *DC = A0->getDeclContext();
4040 ASSERT_TRUE(DC->containsDecl(A0));
4041 ASSERT_TRUE(DC->containsDecl(A1));
4042
4043 // Investigate the lookup table.
4044 auto *Map = DC->getLookupPtr();
4045 ASSERT_TRUE(Map);
4046 auto I = Map->find(A0->getDeclName());
4047 ASSERT_NE(I, Map->end());
4048 StoredDeclsList &L = I->second;
4049 // The lookup table contains the most recent decl of A.
4050 ASSERT_NE(L.getAsDecl(), A0);
4051 ASSERT_EQ(L.getAsDecl(), A1);
4052
4053 ASSERT_TRUE(L.getAsDecl());
4054 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4055 // The point here is to have a Vec with only one element, which is not the
4056 // one we are going to delete from the DC later.
4057 L.setHasExternalDecls();
4058 ASSERT_TRUE(L.getAsVector());
4059 ASSERT_EQ(1u, L.getAsVector()->size());
4060
4061 // This asserts in the old implementation.
4062 DC->removeDecl(A0);
4063 EXPECT_FALSE(DC->containsDecl(A0));
4064}
4065
Gabor Marton5254e642018-06-27 13:32:50 +00004066struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
4067
4068TEST_P(ImportFunctionTemplateSpecializations,
4069 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4070
4071 Decl *FromTU = getTuDecl(
4072 R"(
4073 template<class T>
4074 int f() { return 0; }
4075 void foo() { f<int>(); }
4076 )",
4077 Lang_CXX, "input0.cc");
4078
4079 // Check that the function template instantiation is NOT the child of the TU.
4080 auto Pattern = translationUnitDecl(
4081 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4082 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4083
4084 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4085 FromTU, functionDecl(hasName("foo")));
4086 ASSERT_TRUE(Import(Foo, Lang_CXX));
4087
4088 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4089 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4090}
4091
4092TEST_P(ImportFunctionTemplateSpecializations,
4093 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4094
4095 Decl *FromTU = getTuDecl(
4096 R"(
4097 template<class T>
4098 int f() { return 0; }
4099 template int f<int>();
4100 )",
4101 Lang_CXX, "input0.cc");
4102
4103 // Check that the function template instantiation is NOT the child of the TU.
4104 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4105 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4106 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4107
4108 ASSERT_TRUE(
4109 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4110
4111 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4112 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4113}
4114
4115TEST_P(ImportFunctionTemplateSpecializations,
4116 TUshouldContainFunctionTemplateSpecialization) {
4117
4118 Decl *FromTU = getTuDecl(
4119 R"(
4120 template<class T>
4121 int f() { return 0; }
4122 template <> int f<int>() { return 4; }
4123 )",
4124 Lang_CXX, "input0.cc");
4125
4126 // Check that the function template specialization is the child of the TU.
4127 auto Specialization =
4128 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4129 auto Pattern = translationUnitDecl(has(Specialization));
4130 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4131
4132 ASSERT_TRUE(
4133 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4134
4135 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4136 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4137}
4138
4139TEST_P(ImportFunctionTemplateSpecializations,
4140 FunctionTemplateSpecializationRedeclChain) {
4141
4142 Decl *FromTU = getTuDecl(
4143 R"(
4144 template<class T>
4145 int f() { return 0; }
4146 template <> int f<int>() { return 4; }
4147 )",
4148 Lang_CXX, "input0.cc");
4149
4150 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4151 hasParent(translationUnitDecl()));
4152 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4153 {
4154 auto *TU = FromTU;
4155 auto *SpecD = FromSpecD;
4156 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4157 TU, functionTemplateDecl());
4158 auto *FirstSpecD = *(TemplateD->spec_begin());
4159 ASSERT_EQ(SpecD, FirstSpecD);
4160 ASSERT_TRUE(SpecD->getPreviousDecl());
4161 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4162 ->doesThisDeclarationHaveABody());
4163 }
4164
4165 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4166
4167 {
4168 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4169 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4170 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4171 TU, functionTemplateDecl());
4172 auto *FirstSpecD = *(TemplateD->spec_begin());
4173 EXPECT_EQ(SpecD, FirstSpecD);
4174 ASSERT_TRUE(SpecD->getPreviousDecl());
4175 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4176 ->doesThisDeclarationHaveABody());
4177 }
4178}
4179
4180TEST_P(ImportFunctionTemplateSpecializations,
4181 MatchNumberOfFunctionTemplateSpecializations) {
4182
4183 Decl *FromTU = getTuDecl(
4184 R"(
4185 template <typename T> constexpr int f() { return 0; }
4186 template <> constexpr int f<int>() { return 4; }
4187 void foo() {
4188 static_assert(f<char>() == 0, "");
4189 static_assert(f<int>() == 4, "");
4190 }
4191 )",
4192 Lang_CXX11, "input0.cc");
4193 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4194 FromTU, functionDecl(hasName("foo")));
4195
4196 Import(FromD, Lang_CXX11);
4197 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4198 EXPECT_EQ(
4199 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4200 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4201}
4202
4203TEST_P(ImportFunctionTemplateSpecializations,
4204 ImportPrototypes) {
4205 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4206 auto Code =
4207 R"(
4208 // Proto of the primary template.
4209 template <class T>
4210 void f();
4211 // Proto of the specialization.
4212 template <>
4213 void f<int>();
4214 )";
4215
4216 Decl *ImportedD;
4217 {
4218 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4219 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4220
4221 ImportedD = Import(FromD, Lang_CXX);
4222 }
4223 {
4224 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4225 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4226 Import(FromD, Lang_CXX);
4227 }
4228
4229 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4230
4231 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4232 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4233 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4234 EXPECT_TRUE(ImportedD == To0);
4235 EXPECT_TRUE(ImportedD != To1);
4236 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4237 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4238 // Check that they are part of the same redecl chain.
4239 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
4240}
4241
4242TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
4243 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4244 auto Code =
4245 R"(
4246 // Proto of the primary template.
4247 template <class T>
4248 void f();
4249 // Specialization and definition.
4250 template <>
4251 void f<int>() {}
4252 )";
4253
4254 Decl *ImportedD;
4255 {
4256 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4257 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4258 ImportedD = Import(FromD, Lang_CXX);
4259 }
4260 {
4261 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
4262 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4263 Import(FromD, Lang_CXX);
4264 }
4265
4266 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4267
4268 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
4269 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4270 EXPECT_TRUE(ImportedD == To0);
4271 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4272
4273 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4274 ToTU, functionTemplateDecl());
4275 auto *FirstSpecD = *(TemplateD->spec_begin());
4276 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
4277}
4278
4279TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
4280 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4281 auto Code =
4282 R"(
4283 // Proto of the primary template.
4284 template <class T>
4285 void f();
4286 // Specialization proto.
4287 template <>
4288 void f<int>();
4289 // Specialization proto.
4290 template <>
4291 void f<int>();
4292 )";
4293
4294 Decl *ImportedD;
4295 {
4296 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4297 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4298 ImportedD = Import(FromD, Lang_CXX);
4299 }
4300
4301 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4302
4303 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4304 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4305 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4306 EXPECT_TRUE(ImportedD == To0);
4307 EXPECT_TRUE(ImportedD != To1);
4308 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4309 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4310 EXPECT_EQ(To1->getPreviousDecl(), To0);
4311}
4312
4313TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
4314 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4315 auto Code =
4316 R"(
4317 // Proto of the primary template.
4318 template <class T>
4319 void f();
4320 // Specialization proto.
4321 template <>
4322 void f<int>();
4323 // Specialization definition.
4324 template <>
4325 void f<int>() {}
4326 )";
4327
4328 Decl *ImportedD;
4329 {
4330 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4331 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4332 ImportedD = Import(FromD, Lang_CXX);
4333 }
4334
4335 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4336
4337 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4338 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4339 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4340 EXPECT_TRUE(ImportedD == To0);
4341 EXPECT_TRUE(ImportedD != To1);
4342 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
4343 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
4344 EXPECT_EQ(To1->getPreviousDecl(), To0);
4345}
4346
4347TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
4348 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4349 auto Code =
4350 R"(
4351 // Proto of the primary template.
4352 template <class T>
4353 void f();
4354 // Specialization definition.
4355 template <>
4356 void f<int>() {}
4357 // Specialization proto.
4358 template <>
4359 void f<int>();
4360 )";
4361
4362 Decl *ImportedD;
4363 {
4364 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
4365 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
4366 ImportedD = Import(FromD, Lang_CXX);
4367 }
4368
4369 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4370
4371 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
4372 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4373 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
4374 EXPECT_TRUE(ImportedD == To0);
4375 EXPECT_TRUE(ImportedD != To1);
4376 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
4377 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
4378 EXPECT_EQ(To1->getPreviousDecl(), To0);
4379}
4380
Gabor Marton17d39672018-11-26 15:54:08 +00004381TEST_P(ASTImporterTestBase,
4382 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4383 {
4384 Decl *FromTU = getTuDecl(
4385 R"(
4386 template <typename T>
4387 struct B;
4388 )",
4389 Lang_CXX, "input0.cc");
4390 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4391 FromTU, classTemplateDecl(hasName("B")));
4392
4393 Import(FromD, Lang_CXX);
4394 }
4395
4396 {
4397 Decl *FromTU = getTuDecl(
4398 R"(
4399 template <typename T>
4400 struct B {
4401 void f();
4402 B* b;
4403 };
4404 )",
4405 Lang_CXX, "input1.cc");
4406 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4407 FromTU, functionDecl(hasName("f")));
4408 Import(FromD, Lang_CXX);
4409 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4410 FromTU, classTemplateDecl(hasName("B")));
4411 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4412 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4413
4414 // We expect no (ODR) warning during the import.
4415 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4416 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4417 }
4418}
4419
Gabor Martonb93baf62018-11-27 09:51:36 +00004420TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
4421 // We already have an incomplete underlying type in the "To" context.
4422 auto Code =
4423 R"(
4424 template <typename T>
4425 struct S {
4426 void foo();
4427 };
4428 using U = S<int>;
4429 )";
4430 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4431 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4432 typedefNameDecl(hasName("U")));
4433 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4434
4435 // The "From" context has the same typedef, but the underlying type is
4436 // complete this time.
4437 Decl *FromTU = getTuDecl(std::string(Code) +
4438 R"(
4439 void foo(U* u) {
4440 u->foo();
4441 }
4442 )", Lang_CXX11);
4443 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4444 typedefNameDecl(hasName("U")));
4445 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4446
4447 // The imported type should be complete.
4448 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4449 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4450}
4451
Gabor Marton54058b52018-12-17 13:53:12 +00004452struct ASTImporterLookupTableTest : ASTImporterTestBase {};
4453
4454TEST_P(ASTImporterLookupTableTest, OneDecl) {
4455 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4456 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4457 ASTImporterLookupTable LT(*ToTU);
4458 auto Res = LT.lookup(ToTU, D->getDeclName());
4459 ASSERT_EQ(Res.size(), 1u);
4460 EXPECT_EQ(*Res.begin(), D);
4461}
4462
4463static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4464 for (Decl *D : DC->decls()) {
4465 if (auto *ND = dyn_cast<NamedDecl>(D))
4466 if (ND->getDeclName() == Name)
4467 return ND;
4468 }
4469 return nullptr;
4470};
4471
4472TEST_P(ASTImporterLookupTableTest,
4473 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4474 auto *Code = R"(
4475 template <class T>
4476 struct X {
4477 friend void foo(){}
4478 };
4479 )";
4480 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4481 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4482 ToTU, classTemplateDecl(hasName("X")));
4483 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4484 ToTU, functionDecl(hasName("foo")));
4485 DeclContext *FooDC = Foo->getDeclContext();
4486 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4487 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4488 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4489 DeclarationName FooName = Foo->getDeclName();
4490
4491 // Cannot find in the LookupTable of its DC (TUDecl)
4492 SmallVector<NamedDecl *, 2> FoundDecls;
4493 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4494 EXPECT_EQ(FoundDecls.size(), 0u);
4495
4496 // Cannot find in the LookupTable of its LexicalDC (X)
4497 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4498 EXPECT_EQ(FoundDecls.size(), 0u);
4499
4500 // Can't find in the list of Decls of the DC.
4501 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4502
4503 // Can't find in the list of Decls of the LexicalDC
4504 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4505
4506 // ASTImporter specific lookup finds it.
4507 ASTImporterLookupTable LT(*ToTU);
4508 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4509 ASSERT_EQ(Res.size(), 1u);
4510 EXPECT_EQ(*Res.begin(), Foo);
4511}
4512
4513TEST_P(ASTImporterLookupTableTest,
4514 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4515 TranslationUnitDecl *ToTU =
4516 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4517 auto *Foo =
4518 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4519 auto *A =
4520 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4521 DeclContext *FooDC = Foo->getDeclContext();
4522 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4523 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4524 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4525 DeclarationName FooName = Foo->getDeclName();
4526
4527 // Cannot find in the LookupTable of its DC (TUDecl).
4528 SmallVector<NamedDecl *, 2> FoundDecls;
4529 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4530 EXPECT_EQ(FoundDecls.size(), 0u);
4531
4532 // Cannot find in the LookupTable of its LexicalDC (A).
4533 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4534 EXPECT_EQ(FoundDecls.size(), 0u);
4535
4536 // Can't find in the list of Decls of the DC.
4537 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4538
4539 // Can find in the list of Decls of the LexicalDC.
4540 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4541
4542 // ASTImporter specific lookup finds it.
4543 ASTImporterLookupTable LT(*ToTU);
4544 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4545 ASSERT_EQ(Res.size(), 1u);
4546 EXPECT_EQ(*Res.begin(), Foo);
4547}
4548
4549TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4550 TranslationUnitDecl *ToTU =
4551 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4552 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4553 .match(ToTU, varDecl(hasName("V")))
4554 ->getDeclName();
4555 auto *A =
4556 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4557 auto *B =
4558 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4559
4560 ASTImporterLookupTable LT(*ToTU);
4561
4562 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4563 ASSERT_EQ(Res.size(), 1u);
4564 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4565 ToTU, fieldDecl(hasName("V"),
4566 hasParent(recordDecl(hasName("A"))))));
4567 Res = LT.lookup(cast<DeclContext>(B), VName);
4568 ASSERT_EQ(Res.size(), 1u);
4569 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4570 ToTU, fieldDecl(hasName("V"),
4571 hasParent(recordDecl(hasName("B"))))));
4572 Res = LT.lookup(ToTU, VName);
4573 ASSERT_EQ(Res.size(), 1u);
4574 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4575 ToTU, varDecl(hasName("V"),
4576 hasParent(translationUnitDecl()))));
4577}
4578
4579TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4580 TranslationUnitDecl *ToTU = getToTuDecl(
4581 R"(
4582 void foo();
4583 void foo(int);
4584 void foo(int, int);
4585 )",
4586 Lang_CXX);
4587
4588 ASTImporterLookupTable LT(*ToTU);
4589 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4590 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4591 DeclarationName Name = F0->getDeclName();
4592 auto Res = LT.lookup(ToTU, Name);
4593 EXPECT_EQ(Res.size(), 3u);
4594 EXPECT_EQ(Res.count(F0), 1u);
4595 EXPECT_EQ(Res.count(F2), 1u);
4596}
4597
4598static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
4599 QualType Ty = FD->getFriendType()->getType();
4600 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
4601 return cast<RecordType>(NamedTy)->getDecl();
4602}
4603
4604TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
4605 TranslationUnitDecl *ToTU = getToTuDecl(
4606 R"(
4607 class Y { friend class F; };
4608 )",
4609 Lang_CXX);
4610
4611 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4612 // So we must dig up the underlying CXXRecordDecl.
4613 ASTImporterLookupTable LT(*ToTU);
4614 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4615 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4616 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4617 ToTU, cxxRecordDecl(hasName("Y")));
4618
4619 DeclarationName Name = RD->getDeclName();
4620 auto Res = LT.lookup(ToTU, Name);
4621 EXPECT_EQ(Res.size(), 1u);
4622 EXPECT_EQ(*Res.begin(), RD);
4623
4624 Res = LT.lookup(Y, Name);
4625 EXPECT_EQ(Res.size(), 0u);
4626}
4627
4628TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4629 TranslationUnitDecl *ToTU = getToTuDecl(
4630 R"(
4631 class Y { template <class T> friend class F; };
4632 )",
4633 Lang_CXX);
4634
4635 ASTImporterLookupTable LT(*ToTU);
4636 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4637 ToTU, classTemplateDecl(hasName("F")));
4638 DeclarationName Name = F->getDeclName();
4639 auto Res = LT.lookup(ToTU, Name);
4640 EXPECT_EQ(Res.size(), 2u);
4641 EXPECT_EQ(Res.count(F), 1u);
4642 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4643}
4644
4645TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4646 TranslationUnitDecl *ToTU = getToTuDecl(
4647 R"(
4648 template <typename T>
4649 class F;
4650
4651 template <typename T>
4652 class Y {
4653 friend class F<T>;
4654 };
4655 )",
4656 Lang_CXX);
4657
4658 ASTImporterLookupTable LT(*ToTU);
4659 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4660 ToTU, classTemplateDecl(hasName("F")));
4661 DeclarationName Name = F->getDeclName();
4662 auto Res = LT.lookup(ToTU, Name);
4663 EXPECT_EQ(Res.size(), 2u);
4664 EXPECT_EQ(Res.count(F), 1u);
4665 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4666}
4667
4668TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4669 TranslationUnitDecl *ToTU = getToTuDecl(
4670 R"(
4671 template <typename T>
4672 class F;
4673
4674 class Y {
4675 friend class F<int>;
4676 };
4677 )",
4678 Lang_CXX);
4679
4680 ASTImporterLookupTable LT(*ToTU);
4681 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4682 ToTU, classTemplateDecl(hasName("F")));
4683 DeclarationName Name = F->getDeclName();
4684 auto Res = LT.lookup(ToTU, Name);
4685 ASSERT_EQ(Res.size(), 3u);
4686 EXPECT_EQ(Res.count(F), 1u);
4687 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4688 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4689}
4690
4691TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4692 TranslationUnitDecl *ToTU = getToTuDecl(
4693 R"(
4694 class Y { friend void F(); };
4695 )",
4696 Lang_CXX);
4697
4698 ASTImporterLookupTable LT(*ToTU);
4699 auto *F =
4700 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4701 DeclarationName Name = F->getDeclName();
4702 auto Res = LT.lookup(ToTU, Name);
4703 EXPECT_EQ(Res.size(), 1u);
4704 EXPECT_EQ(*Res.begin(), F);
4705}
4706
4707TEST_P(ASTImporterLookupTableTest,
4708 LookupFindsDeclsInClassTemplateSpecialization) {
4709 TranslationUnitDecl *ToTU = getToTuDecl(
4710 R"(
4711 template <typename T>
4712 struct X {
4713 int F;
4714 };
4715 void foo() {
4716 X<char> xc;
4717 }
4718 )",
4719 Lang_CXX);
4720
4721 ASTImporterLookupTable LT(*ToTU);
4722
4723 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4724 ToTU, classTemplateDecl(hasName("X")));
4725 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4726 ToTU,
4727 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4728
4729 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4730 ToTU, classTemplateSpecializationDecl(hasName("X")));
4731 FieldDecl *FieldInSpec = *Spec->field_begin();
4732 ASSERT_TRUE(FieldInSpec);
4733
4734 DeclarationName Name = FieldInSpec->getDeclName();
4735 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4736
4737 SmallVector<NamedDecl *, 2> FoundDecls;
4738 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4739 EXPECT_EQ(FoundDecls.size(), 1u);
4740 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4741
4742 auto Res = LT.lookup(TemplateDC, Name);
4743 ASSERT_EQ(Res.size(), 1u);
4744 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4745
4746 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4747 FoundDecls);
4748 EXPECT_EQ(FoundDecls.size(), 1u);
4749 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4750
4751 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4752 ASSERT_EQ(Res.size(), 1u);
4753 EXPECT_EQ(*Res.begin(), FieldInSpec);
4754}
4755
4756TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4757 TranslationUnitDecl *ToTU = getToTuDecl(
4758 R"(
4759 class Y { template <class T> friend void F(); };
4760 )",
4761 Lang_CXX);
4762
4763 ASTImporterLookupTable LT(*ToTU);
4764 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4765 ToTU, functionTemplateDecl(hasName("F")));
4766 DeclarationName Name = F->getDeclName();
4767 auto Res = LT.lookup(ToTU, Name);
4768 EXPECT_EQ(Res.size(), 2u);
4769 EXPECT_EQ(Res.count(F), 1u);
4770 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4771}
4772
4773TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4774 TranslationUnitDecl *ToTU = getToTuDecl(
4775 R"(
4776 struct X;
4777 struct A {
4778 friend struct X;
4779 };
4780 struct B {
4781 friend struct X;
4782 };
4783 )",
4784 Lang_CXX);
4785
4786 ASTImporterLookupTable LT(*ToTU);
4787 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4788 ToTU, cxxRecordDecl(hasName("X")));
4789 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4790 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4791 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4792 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4793 ASSERT_EQ(RD0, RD1);
4794 ASSERT_EQ(RD1, X);
4795
4796 DeclarationName Name = X->getDeclName();
4797 auto Res = LT.lookup(ToTU, Name);
4798 EXPECT_EQ(Res.size(), 1u);
4799 EXPECT_EQ(*Res.begin(), X);
4800}
4801
4802TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4803 TranslationUnitDecl *ToTU = getToTuDecl(
4804 R"(
4805 enum E {
4806 A,
4807 B
4808 };
4809 )",
4810 Lang_C);
4811
4812 ASTImporterLookupTable LT(*ToTU);
4813 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4814 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4815 ToTU, enumConstantDecl(hasName("A")));
4816
4817 DeclarationName Name = A->getDeclName();
4818 // Redecl context is the TU.
4819 ASSERT_EQ(E->getRedeclContext(), ToTU);
4820
4821 SmallVector<NamedDecl *, 2> FoundDecls;
4822 // Normal lookup finds in the DC.
4823 E->localUncachedLookup(Name, FoundDecls);
4824 EXPECT_EQ(FoundDecls.size(), 1u);
4825
4826 // Normal lookup finds in the Redecl context.
4827 ToTU->localUncachedLookup(Name, FoundDecls);
4828 EXPECT_EQ(FoundDecls.size(), 1u);
4829
4830 // Import specific lookup finds in the DC.
4831 auto Res = LT.lookup(E, Name);
4832 ASSERT_EQ(Res.size(), 1u);
4833 EXPECT_EQ(*Res.begin(), A);
4834
4835 // Import specific lookup finds in the Redecl context.
4836 Res = LT.lookup(ToTU, Name);
4837 ASSERT_EQ(Res.size(), 1u);
4838 EXPECT_EQ(*Res.begin(), A);
4839}
4840
4841TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4842 TranslationUnitDecl *ToTU = getToTuDecl(
4843 R"(
4844 namespace N {
4845 int A;
4846 }
4847 namespace N {
4848 }
4849 )",
4850 Lang_CXX);
4851 auto *N1 =
4852 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4853 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4854 DeclarationName Name = A->getDeclName();
4855
4856 ASTImporterLookupTable LT(*ToTU);
4857 auto Res = LT.lookup(N1, Name);
4858 ASSERT_EQ(Res.size(), 1u);
4859 EXPECT_EQ(*Res.begin(), A);
4860}
4861
Gabor Marton19f4f392018-06-25 13:04:37 +00004862INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
4863 ::testing::Values(ArgVector()), );
4864
Gabor Marton5254e642018-06-27 13:32:50 +00004865INSTANTIATE_TEST_CASE_P(
4866 ParameterizedTests, CanonicalRedeclChain,
4867 ::testing::Values(ArgVector()),);
4868
Gabor Marton19f4f392018-06-25 13:04:37 +00004869auto DefaultTestValuesForRunOptions = ::testing::Values(
4870 ArgVector(),
4871 ArgVector{"-fdelayed-template-parsing"},
4872 ArgVector{"-fms-compatibility"},
4873 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
4874
Gabor Marton54058b52018-12-17 13:53:12 +00004875INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
4876 DefaultTestValuesForRunOptions, );
4877
Gabor Marton19f4f392018-06-25 13:04:37 +00004878INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
4879 DefaultTestValuesForRunOptions, );
4880
4881INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
4882 DefaultTestValuesForRunOptions, );
4883
4884INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
4885 DefaultTestValuesForRunOptions, );
4886
4887INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
4888 DefaultTestValuesForRunOptions, );
4889
4890INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
4891 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00004892
Gabor Marton54058b52018-12-17 13:53:12 +00004893INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00004894 DefaultTestValuesForRunOptions, );
4895
Gabor Marton54058b52018-12-17 13:53:12 +00004896INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00004897 DefaultTestValuesForRunOptions, );
4898
4899INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClassTemplates,
4900 DefaultTestValuesForRunOptions, );
4901
4902INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
4903 DefaultTestValuesForRunOptions, );
4904
Gabor Marton5254e642018-06-27 13:32:50 +00004905INSTANTIATE_TEST_CASE_P(ParameterizedTests,
4906 ImportFunctionTemplateSpecializations,
4907 DefaultTestValuesForRunOptions, );
4908
Gabor Martonac3a5d62018-09-17 12:04:52 +00004909INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
4910 DefaultTestValuesForRunOptions, );
4911
4912INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
4913 DefaultTestValuesForRunOptions, );
4914
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00004915} // end namespace ast_matchers
4916} // end namespace clang