blob: 08d57e2e433eab99928ca6612b16b7b1295b2208 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Gabor Marton458d1452019-02-14 13:07:03 +000013// Define this to have ::testing::Combine available.
14// FIXME: Better solution for this?
15#define GTEST_HAS_COMBINE 1
16
Gabor Marton7df342a2018-12-17 12:42:12 +000017#include "clang/AST/ASTImporter.h"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000018#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000019#include "clang/AST/ASTContext.h"
Gabor Marton7df342a2018-12-17 12:42:12 +000020#include "clang/AST/DeclContextInternals.h"
Gabor Marton54058b52018-12-17 13:53:12 +000021#include "clang/AST/ASTImporter.h"
22#include "clang/AST/ASTImporterLookupTable.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023#include "clang/ASTMatchers/ASTMatchFinder.h"
24#include "clang/ASTMatchers/ASTMatchers.h"
25#include "clang/Tooling/Tooling.h"
Peter Szecsidedda6f2018-03-30 22:03:29 +000026
27#include "DeclMatcher.h"
Gabor Marton1f667532018-05-24 08:41:07 +000028#include "Language.h"
Gabor Marton5254e642018-06-27 13:32:50 +000029#include "gmock/gmock.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000030#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000031
32namespace clang {
33namespace ast_matchers {
34
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035using internal::Matcher;
36using internal::BindableMatcher;
37using llvm::StringMap;
38
Peter Szecsidedda6f2018-03-30 22:03:29 +000039// Creates a virtual file and assigns that to the context of given AST. If the
40// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000041static void
42createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
43 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000044 assert(ToAST);
45 ASTContext &ToCtx = ToAST->getASTContext();
Jonas Devliegherefc514902018-10-10 13:27:25 +000046 auto *OFS = static_cast<llvm::vfs::OverlayFileSystem *>(
Peter Szecsidedda6f2018-03-30 22:03:29 +000047 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
Jonas Devliegherefc514902018-10-10 13:27:25 +000048 auto *MFS = static_cast<llvm::vfs::InMemoryFileSystem *>(
49 OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000050 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000051}
52
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
54 StringRef Code) {
55 return createVirtualFileIfNeeded(ToAST, FileName,
56 llvm::MemoryBuffer::getMemBuffer(Code));
57}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000058
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059const StringRef DeclToImportID = "declToImport";
60const StringRef DeclToVerifyID = "declToVerify";
61
Gabor Marton19f4f392018-06-25 13:04:37 +000062// Common base for the different families of ASTImporter tests that are
63// parameterized on the compiler options which may result a different AST. E.g.
64// -fms-compatibility or -fdelayed-template-parsing.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000065class CompilerOptionSpecificTest : public ::testing::Test {
66protected:
67 // Return the extra arguments appended to runtime options at compilation.
68 virtual ArgVector getExtraArgs() const { return ArgVector(); }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000069
Gabor Marton19f4f392018-06-25 13:04:37 +000070 // Returns the argument vector used for a specific language option, this set
71 // can be tweaked by the test parameters.
72 ArgVector getArgVectorForLanguage(Language Lang) const {
73 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
Gabor Marton0b57ccb2019-02-07 16:52:48 +000074 ArgVector ExtraArgs = getExtraArgs();
Gabor Marton19f4f392018-06-25 13:04:37 +000075 for (const auto &Arg : ExtraArgs) {
76 Args.push_back(Arg);
77 }
78 return Args;
79 }
Gabor Marton19f4f392018-06-25 13:04:37 +000080};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton0b57ccb2019-02-07 16:52:48 +000082auto DefaultTestValuesForRunOptions = ::testing::Values(
83 ArgVector(), ArgVector{"-fdelayed-template-parsing"},
84 ArgVector{"-fms-compatibility"},
85 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
86
Gabor Marton19f4f392018-06-25 13:04:37 +000087// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000088class TestImportBase : public CompilerOptionSpecificTest,
89 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 template <typename NodeType>
92 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
93 NodeType Node) {
94 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000095
Gabor Marton19f4f392018-06-25 13:04:37 +000096 // Add 'From' file to virtual file system so importer can 'find' it
97 // while importing SourceLocations. It is safe to add same file multiple
98 // times - it just isn't replaced.
99 StringRef FromFileName = From->getMainFileName();
100 createVirtualFileIfNeeded(To, FromFileName,
101 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000102
Gabor Marton19f4f392018-06-25 13:04:37 +0000103 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000104
Gabor Marton19f4f392018-06-25 13:04:37 +0000105 // This should dump source locations and assert if some source locations
106 // were not imported.
107 SmallString<1024> ImportChecker;
108 llvm::raw_svector_ostream ToNothing(ImportChecker);
109 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000110
Gabor Marton19f4f392018-06-25 13:04:37 +0000111 // This traverses the AST to catch certain bugs like poorly or not
112 // implemented subtrees.
113 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000114
Gabor Marton19f4f392018-06-25 13:04:37 +0000115 return Imported;
116 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000117
Gabor Marton19f4f392018-06-25 13:04:37 +0000118 template <typename NodeType>
119 testing::AssertionResult
120 testImport(const std::string &FromCode, const ArgVector &FromArgs,
121 const std::string &ToCode, const ArgVector &ToArgs,
122 MatchVerifier<NodeType> &Verifier,
123 const BindableMatcher<NodeType> &SearchMatcher,
124 const BindableMatcher<NodeType> &VerificationMatcher) {
125 const char *const InputFileName = "input.cc";
126 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000127
Gabor Marton19f4f392018-06-25 13:04:37 +0000128 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
129 FromCode, FromArgs, InputFileName),
130 ToAST = tooling::buildASTFromCodeWithArgs(
131 ToCode, ToArgs, OutputFileName);
132
133 ASTContext &FromCtx = FromAST->getASTContext(),
134 &ToCtx = ToAST->getASTContext();
135
136 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
137 FromAST->getFileManager(), false);
138
139 auto FoundNodes = match(SearchMatcher, FromCtx);
140 if (FoundNodes.size() != 1)
141 return testing::AssertionFailure()
142 << "Multiple potential nodes were found!";
143
144 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
145 if (!ToImport)
146 return testing::AssertionFailure() << "Node type mismatch!";
147
148 // Sanity check: the node being imported should match in the same way as
149 // the result node.
150 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
151 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
152
153 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
154 if (!Imported)
155 return testing::AssertionFailure() << "Import failed, nullptr returned!";
156
Bill Wendling8003edc2018-11-09 00:41:36 +0000157
Gabor Marton19f4f392018-06-25 13:04:37 +0000158 return Verifier.match(Imported, WrapperMatcher);
159 }
160
161 template <typename NodeType>
162 testing::AssertionResult
163 testImport(const std::string &FromCode, const ArgVector &FromArgs,
164 const std::string &ToCode, const ArgVector &ToArgs,
165 MatchVerifier<NodeType> &Verifier,
166 const BindableMatcher<NodeType> &VerificationMatcher) {
167 return testImport(
168 FromCode, FromArgs, ToCode, ToArgs, Verifier,
169 translationUnitDecl(
170 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
171 VerificationMatcher);
172 }
173
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000174protected:
175 ArgVector getExtraArgs() const override { return GetParam(); }
176
Gabor Marton19f4f392018-06-25 13:04:37 +0000177public:
178
179 /// Test how AST node named "declToImport" located in the translation unit
180 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
181 /// The verification is done by running AMatcher over the imported node.
182 template <typename NodeType, typename MatcherType>
183 void testImport(const std::string &FromCode, Language FromLang,
184 const std::string &ToCode, Language ToLang,
185 MatchVerifier<NodeType> &Verifier,
186 const MatcherType &AMatcher) {
187 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
188 ToArgs = getArgVectorForLanguage(ToLang);
189 EXPECT_TRUE(
190 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
191 }
192
193 struct ImportAction {
194 StringRef FromFilename;
195 StringRef ToFilename;
196 // FIXME: Generalize this to support other node kinds.
197 BindableMatcher<Decl> ImportPredicate;
198
199 ImportAction(StringRef FromFilename, StringRef ToFilename,
200 DeclarationMatcher ImportPredicate)
201 : FromFilename(FromFilename), ToFilename(ToFilename),
202 ImportPredicate(ImportPredicate) {}
203
204 ImportAction(StringRef FromFilename, StringRef ToFilename,
205 const std::string &DeclName)
206 : FromFilename(FromFilename), ToFilename(ToFilename),
207 ImportPredicate(namedDecl(hasName(DeclName))) {}
208 };
209
210 using SingleASTUnit = std::unique_ptr<ASTUnit>;
211 using AllASTUnits = StringMap<SingleASTUnit>;
212
213 struct CodeEntry {
214 std::string CodeSample;
215 Language Lang;
216 };
217
218 using CodeFiles = StringMap<CodeEntry>;
219
220 /// Builds an ASTUnit for one potential compile options set.
221 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
222 ArgVector Args = getArgVectorForLanguage(CE.Lang);
223 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
224 EXPECT_TRUE(AST.get());
225 return AST;
226 }
227
228 /// Test an arbitrary sequence of imports for a set of given in-memory files.
229 /// The verification is done by running VerificationMatcher against a
230 /// specified AST node inside of one of given files.
231 /// \param CodeSamples Map whose key is the file name and the value is the
232 /// file content.
233 /// \param ImportActions Sequence of imports. Each import in sequence
234 /// specifies "from file" and "to file" and a matcher that is used for
235 /// searching a declaration for import in "from file".
236 /// \param FileForFinalCheck Name of virtual file for which the final check is
237 /// applied.
238 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
239 /// FileForFinalCheck for which the verification will be done.
240 /// \param VerificationMatcher Matcher that will be used for verification
241 /// after all imports in sequence are done.
242 void testImportSequence(const CodeFiles &CodeSamples,
243 const std::vector<ImportAction> &ImportActions,
244 StringRef FileForFinalCheck,
245 BindableMatcher<Decl> FinalSelectPredicate,
246 BindableMatcher<Decl> VerificationMatcher) {
247 AllASTUnits AllASTs;
248 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
249 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
250
251 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
252 if (!AllASTs.count(Filename)) {
253 auto Found = CodeSamples.find(Filename);
254 assert(Found != CodeSamples.end() && "Wrong file for import!");
255 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
256 }
257 };
258
259 for (const ImportAction &Action : ImportActions) {
260 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
261 GenASTsIfNeeded(FromFile);
262 GenASTsIfNeeded(ToFile);
263
264 ASTUnit *From = AllASTs[FromFile].get();
265 ASTUnit *To = AllASTs[ToFile].get();
266
267 // Create a new importer if needed.
268 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
269 if (!ImporterRef)
270 ImporterRef.reset(new ASTImporter(
271 To->getASTContext(), To->getFileManager(), From->getASTContext(),
272 From->getFileManager(), false));
273
274 // Find the declaration and import it.
275 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
276 From->getASTContext());
277 EXPECT_TRUE(FoundDecl.size() == 1);
278 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
279 auto Imported = importNode(From, To, *ImporterRef, ToImport);
280 EXPECT_TRUE(Imported);
281 }
282
283 // Find the declaration and import it.
284 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
285 AllASTs[FileForFinalCheck]->getASTContext());
286 EXPECT_TRUE(FoundDecl.size() == 1);
287 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
288 MatchVerifier<Decl> Verifier;
289 EXPECT_TRUE(
290 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
291 }
292};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000293
Gabor Martonf086fa82018-07-17 12:06:36 +0000294template <typename T> RecordDecl *getRecordDecl(T *D) {
295 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
296 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000297}
Gabor Martonf086fa82018-07-17 12:06:36 +0000298
Peter Szecsidedda6f2018-03-30 22:03:29 +0000299// This class provides generic methods to write tests which can check internal
Balazs Keri21f938c2018-07-02 14:14:07 +0000300// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000301// this fixture makes it possible to import from several "From" contexts.
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000302class ASTImporterTestBase : public CompilerOptionSpecificTest {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000303
304 const char *const InputFileName = "input.cc";
305 const char *const OutputFileName = "output.cc";
306
307 // Buffer for the To context, must live in the test scope.
308 std::string ToCode;
309
Gabor Marton26f72a92018-07-12 09:42:05 +0000310 // Represents a "From" translation unit and holds an importer object which we
311 // use to import from this translation unit.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000312 struct TU {
313 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000314 std::string Code;
315 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000316 std::unique_ptr<ASTUnit> Unit;
317 TranslationUnitDecl *TUDecl = nullptr;
Gabor Marton26f72a92018-07-12 09:42:05 +0000318 std::unique_ptr<ASTImporter> Importer;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000319 TU(StringRef Code, StringRef FileName, ArgVector Args)
320 : Code(Code), FileName(FileName),
321 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
322 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000323 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
324 Unit->enableSourceFileDiagnostics();
325 }
Gabor Marton26f72a92018-07-12 09:42:05 +0000326
Gabor Marton54058b52018-12-17 13:53:12 +0000327 void lazyInitImporter(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST) {
Gabor Marton26f72a92018-07-12 09:42:05 +0000328 assert(ToAST);
329 if (!Importer) {
Gabor Marton54058b52018-12-17 13:53:12 +0000330 Importer.reset(
331 new ASTImporter(ToAST->getASTContext(), ToAST->getFileManager(),
332 Unit->getASTContext(), Unit->getFileManager(),
333 false, &LookupTable));
Gabor Marton26f72a92018-07-12 09:42:05 +0000334 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000335 assert(&ToAST->getASTContext() == &Importer->getToContext());
336 createVirtualFileIfNeeded(ToAST, FileName, Code);
337 }
338
Gabor Marton54058b52018-12-17 13:53:12 +0000339 Decl *import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
340 Decl *FromDecl) {
341 lazyInitImporter(LookupTable, ToAST);
Gabor Marton26f72a92018-07-12 09:42:05 +0000342 return Importer->Import(FromDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000343 }
Gabor Marton6e1510c2018-07-12 11:50:21 +0000344
Gabor Marton54058b52018-12-17 13:53:12 +0000345 QualType import(ASTImporterLookupTable &LookupTable, ASTUnit *ToAST,
346 QualType FromType) {
347 lazyInitImporter(LookupTable, ToAST);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000348 return Importer->Import(FromType);
Gabor Marton26f72a92018-07-12 09:42:05 +0000349 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000350 };
351
352 // We may have several From contexts and related translation units. In each
353 // AST, the buffers for the source are handled via references and are set
354 // during the creation of the AST. These references must point to a valid
355 // buffer until the AST is alive. Thus, we must use a list in order to avoid
356 // moving of the stored objects because that would mean breaking the
357 // references in the AST. By using a vector a move could happen when the
358 // vector is expanding, with the list we won't have these issues.
359 std::list<TU> FromTUs;
360
Gabor Marton54058b52018-12-17 13:53:12 +0000361 // Initialize the lookup table if not initialized already.
362 void lazyInitLookupTable(TranslationUnitDecl *ToTU) {
363 assert(ToTU);
364 if (!LookupTablePtr)
365 LookupTablePtr = llvm::make_unique<ASTImporterLookupTable>(*ToTU);
366 }
367
368 void lazyInitToAST(Language ToLang, StringRef ToSrcCode, StringRef FileName) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000369 if (ToAST)
370 return;
371 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton54058b52018-12-17 13:53:12 +0000372 // Source code must be a valid live buffer through the tests lifetime.
373 ToCode = ToSrcCode;
Gabor Marton6e1510c2018-07-12 11:50:21 +0000374 // Build the AST from an empty file.
Gabor Marton54058b52018-12-17 13:53:12 +0000375 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, FileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000376 ToAST->enableSourceFileDiagnostics();
Gabor Marton54058b52018-12-17 13:53:12 +0000377 lazyInitLookupTable(ToAST->getASTContext().getTranslationUnitDecl());
Gabor Marton6e1510c2018-07-12 11:50:21 +0000378 }
379
380 TU *findFromTU(Decl *From) {
381 // Create a virtual file in the To Ctx which corresponds to the file from
382 // which we want to import the `From` Decl. Without this source locations
383 // will be invalid in the ToCtx.
384 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
385 return E.TUDecl == From->getTranslationUnitDecl();
386 });
387 assert(It != FromTUs.end());
388 return &*It;
389 }
390
Gabor Marton54058b52018-12-17 13:53:12 +0000391protected:
392
393 std::unique_ptr<ASTImporterLookupTable> LookupTablePtr;
394
Peter Szecsidedda6f2018-03-30 22:03:29 +0000395public:
396 // We may have several From context but only one To context.
397 std::unique_ptr<ASTUnit> ToAST;
398
Peter Szecsidedda6f2018-03-30 22:03:29 +0000399 // Creates an AST both for the From and To source code and imports the Decl
400 // of the identifier into the To context.
401 // Must not be called more than once within the same test.
402 std::tuple<Decl *, Decl *>
403 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
404 Language ToLang, StringRef Identifier = DeclToImportID) {
405 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
406 ToArgs = getArgVectorForLanguage(ToLang);
407
408 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
409 TU &FromTU = FromTUs.back();
410
Peter Szecsidedda6f2018-03-30 22:03:29 +0000411 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000412 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000413
Gabor Marton26f72a92018-07-12 09:42:05 +0000414 ASTContext &FromCtx = FromTU.Unit->getASTContext();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000415
Peter Szecsidedda6f2018-03-30 22:03:29 +0000416 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
417 assert(ImportedII && "Declaration with the given identifier "
418 "should be specified in test!");
419 DeclarationName ImportDeclName(ImportedII);
Gabor Marton54058b52018-12-17 13:53:12 +0000420 SmallVector<NamedDecl *, 1> FoundDecls;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000421 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
422 FoundDecls);
423
424 assert(FoundDecls.size() == 1);
425
Gabor Marton54058b52018-12-17 13:53:12 +0000426 Decl *Imported =
427 FromTU.import(*LookupTablePtr, ToAST.get(), FoundDecls.front());
Gabor Marton26f72a92018-07-12 09:42:05 +0000428
Peter Szecsidedda6f2018-03-30 22:03:29 +0000429 assert(Imported);
430 return std::make_tuple(*FoundDecls.begin(), Imported);
431 }
432
Gabor Marton9581c332018-05-23 13:53:36 +0000433 // Creates a TU decl for the given source code which can be used as a From
434 // context. May be called several times in a given test (with different file
435 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000436 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
437 StringRef FileName = "input.cc") {
438 assert(
439 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
440 return E.FileName == FileName;
441 }) == FromTUs.end());
442
443 ArgVector Args = getArgVectorForLanguage(Lang);
444 FromTUs.emplace_back(SrcCode, FileName, Args);
445 TU &Tu = FromTUs.back();
446
447 return Tu.TUDecl;
448 }
449
Gabor Marton9581c332018-05-23 13:53:36 +0000450 // Creates the To context with the given source code and returns the TU decl.
451 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
452 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
Gabor Marton9581c332018-05-23 13:53:36 +0000453 assert(!ToAST);
Gabor Marton54058b52018-12-17 13:53:12 +0000454 lazyInitToAST(ToLang, ToSrcCode, OutputFileName);
Gabor Marton9581c332018-05-23 13:53:36 +0000455 return ToAST->getASTContext().getTranslationUnitDecl();
456 }
457
Peter Szecsidedda6f2018-03-30 22:03:29 +0000458 // Import the given Decl into the ToCtx.
459 // May be called several times in a given test.
460 // The different instances of the param From may have different ASTContext.
461 Decl *Import(Decl *From, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000462 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000463 TU *FromTU = findFromTU(From);
Gabor Marton54058b52018-12-17 13:53:12 +0000464 assert(LookupTablePtr);
465 return FromTU->import(*LookupTablePtr, ToAST.get(), From);
Peter Szecsidedda6f2018-03-30 22:03:29 +0000466 }
467
Gabor Marton458d1452019-02-14 13:07:03 +0000468 template <class DeclT> DeclT *Import(DeclT *From, Language Lang) {
469 return cast_or_null<DeclT>(Import(cast<Decl>(From), Lang));
470 }
471
Gabor Marton6e1510c2018-07-12 11:50:21 +0000472 QualType ImportType(QualType FromType, Decl *TUDecl, Language ToLang) {
Gabor Marton54058b52018-12-17 13:53:12 +0000473 lazyInitToAST(ToLang, "", OutputFileName);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000474 TU *FromTU = findFromTU(TUDecl);
Gabor Marton54058b52018-12-17 13:53:12 +0000475 assert(LookupTablePtr);
476 return FromTU->import(*LookupTablePtr, ToAST.get(), FromType);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000477 }
478
Peter Szecsidedda6f2018-03-30 22:03:29 +0000479 ~ASTImporterTestBase() {
480 if (!::testing::Test::HasFailure()) return;
481
482 for (auto &Tu : FromTUs) {
483 assert(Tu.Unit);
484 llvm::errs() << "FromAST:\n";
485 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
486 llvm::errs() << "\n";
487 }
488 if (ToAST) {
489 llvm::errs() << "ToAST:\n";
490 ToAST->getASTContext().getTranslationUnitDecl()->dump();
491 }
492 }
493};
494
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000495class ASTImporterOptionSpecificTestBase
496 : public ASTImporterTestBase,
497 public ::testing::WithParamInterface<ArgVector> {
498protected:
499 ArgVector getExtraArgs() const override { return GetParam(); }
500};
501
Gabor Marton19f4f392018-06-25 13:04:37 +0000502struct ImportExpr : TestImportBase {};
503struct ImportType : TestImportBase {};
504struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000505
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000506struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000507
508TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
509 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
510 auto Pattern = functionDecl(hasName("f"));
511 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
512
513 auto Redecls = getCanonicalForwardRedeclChain(D0);
514 ASSERT_EQ(Redecls.size(), 1u);
515 EXPECT_EQ(D0, Redecls[0]);
516}
517
518TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
519 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
520 auto Pattern = functionDecl(hasName("f"));
521 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
522 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
523 FunctionDecl *D1 = D2->getPreviousDecl();
524
525 auto Redecls = getCanonicalForwardRedeclChain(D0);
526 ASSERT_EQ(Redecls.size(), 3u);
527 EXPECT_EQ(D0, Redecls[0]);
528 EXPECT_EQ(D1, Redecls[1]);
529 EXPECT_EQ(D2, Redecls[2]);
530}
531
532TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
533 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
534 auto Pattern = functionDecl(hasName("f"));
535 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
536 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
537 FunctionDecl *D1 = D2->getPreviousDecl();
538
539 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
540 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
541 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
542
543 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
544 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
545}
546
Gabor Marton19f4f392018-06-25 13:04:37 +0000547TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000548 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000549 testImport(
550 "void declToImport() { (void)\"foo\"; }",
551 Lang_CXX, "", Lang_CXX, Verifier,
552 functionDecl(hasDescendant(
553 stringLiteral(hasType(asString("const char [4]"))))));
554 testImport(
555 "void declToImport() { (void)L\"foo\"; }",
556 Lang_CXX, "", Lang_CXX, Verifier,
557 functionDecl(hasDescendant(
558 stringLiteral(hasType(asString("const wchar_t [4]"))))));
559 testImport(
560 "void declToImport() { (void) \"foo\" \"bar\"; }",
561 Lang_CXX, "", Lang_CXX, Verifier,
562 functionDecl(hasDescendant(
563 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000564}
565
Tom Roeder521f0042019-02-26 19:26:41 +0000566TEST_P(ImportExpr, ImportChooseExpr) {
567 MatchVerifier<Decl> Verifier;
568
569 // This case tests C code that is not condition-dependent and has a true
570 // condition.
571 testImport(
572 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
573 Lang_C, "", Lang_C, Verifier,
574 functionDecl(hasDescendant(chooseExpr())));
575}
576
Gabor Marton19f4f392018-06-25 13:04:37 +0000577TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000578 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000579 testImport(
580 "void declToImport() { (void)__null; }",
581 Lang_CXX, "", Lang_CXX, Verifier,
582 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000583}
584
Gabor Marton19f4f392018-06-25 13:04:37 +0000585TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000586 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000587 testImport(
588 "void declToImport() { (void)nullptr; }",
589 Lang_CXX11, "", Lang_CXX11, Verifier,
590 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000591}
592
593
Gabor Marton19f4f392018-06-25 13:04:37 +0000594TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000596 testImport(
597 "void declToImport() { (void)1.0; }",
598 Lang_C, "", Lang_C, Verifier,
599 functionDecl(hasDescendant(
600 floatLiteral(equals(1.0), hasType(asString("double"))))));
601 testImport(
602 "void declToImport() { (void)1.0e-5f; }",
603 Lang_C, "", Lang_C, Verifier,
604 functionDecl(hasDescendant(
605 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000606}
607
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000608TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
609 MatchVerifier<Decl> Verifier;
610 testImport(
611 "void declToImport() { (void)1.0i; }",
612 Lang_CXX14, "", Lang_CXX14, Verifier,
613 functionDecl(hasDescendant(imaginaryLiteral())));
614}
615
Gabor Marton19f4f392018-06-25 13:04:37 +0000616TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000617 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000618 testImport(
619 "void declToImport() {"
620 " struct s { int x; long y; unsigned z; }; "
621 " (void)(struct s){ 42, 0L, 1U }; }",
622 Lang_CXX, "", Lang_CXX, Verifier,
623 functionDecl(hasDescendant(
624 compoundLiteralExpr(
625 hasType(asString("struct s")),
626 has(initListExpr(
627 hasType(asString("struct s")),
628 has(integerLiteral(
629 equals(42), hasType(asString("int")))),
630 has(integerLiteral(
631 equals(0), hasType(asString("long")))),
632 has(integerLiteral(
633 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000634}
635
Gabor Marton19f4f392018-06-25 13:04:37 +0000636TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000637 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000638 testImport(
639 "class declToImport { void f() { (void)this; } };",
640 Lang_CXX, "", Lang_CXX, Verifier,
641 cxxRecordDecl(
642 hasMethod(
643 hasDescendant(
644 cxxThisExpr(
645 hasType(
646 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000647}
648
Gabor Marton19f4f392018-06-25 13:04:37 +0000649TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000650 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000651 testImport(
652 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
653 Lang_C, "", Lang_C, Verifier,
654 functionDecl(hasDescendant(
655 atomicExpr(
656 has(ignoringParenImpCasts(
657 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
658 hasType(asString("int *"))))),
659 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000660}
661
Gabor Marton19f4f392018-06-25 13:04:37 +0000662TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000663 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000664 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000665 "void declToImport() { loop: goto loop; (void)&&loop; }",
666 Lang_C, "", Lang_C, Verifier,
667 functionDecl(
668 hasDescendant(
669 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
670 hasDescendant(
671 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000672}
673
674AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
675 internal::Matcher<NamedDecl>, InnerMatcher) {
676 const NamedDecl *Template = Node.getTemplatedDecl();
677 return Template && InnerMatcher.matches(*Template, Finder, Builder);
678}
679
Gabor Marton19f4f392018-06-25 13:04:37 +0000680TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000681 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000682 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000683 "template<typename T> class dummy { void f() { dummy X(*this); } };"
684 "typedef dummy<int> declToImport;"
685 "template class dummy<int>;",
686 Lang_CXX, "", Lang_CXX, Verifier,
687 typedefDecl(hasType(templateSpecializationType(
688 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
689 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
690 hasName("f"),
691 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
692 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
693 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000694 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000695}
696
Gabor Marton19f4f392018-06-25 13:04:37 +0000697TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000698 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000699 testImport(
700 "void declToImport() { int b; switch (b) { case 1: break; } }",
701 Lang_C, "", Lang_C, Verifier,
702 functionDecl(hasDescendant(
703 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000704}
705
Gabor Marton19f4f392018-06-25 13:04:37 +0000706TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000707 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000708 testImport(
709 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
710 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000711 functionDecl(hasDescendant(
712 varDecl(
713 hasName("C"),
714 hasType(asString("int")),
715 hasInitializer(
716 stmtExpr(
717 hasAnySubstatement(declStmt(hasSingleDecl(
718 varDecl(
719 hasName("X"),
720 hasType(asString("int")),
721 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000722 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000723 hasDescendant(
724 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000725}
726
Gabor Marton19f4f392018-06-25 13:04:37 +0000727TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000728 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000729 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000730 "void declToImport() { (void)(true ? 1 : -5); }",
731 Lang_CXX, "", Lang_CXX, Verifier,
732 functionDecl(hasDescendant(
733 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000734 hasCondition(cxxBoolLiteral(equals(true))),
735 hasTrueExpression(integerLiteral(equals(1))),
736 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000737 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
738 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000739}
740
Gabor Marton19f4f392018-06-25 13:04:37 +0000741TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000742 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000743 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000744 "void declToImport() { (void)(1 ?: -5); }",
745 Lang_CXX, "", Lang_CXX, Verifier,
746 functionDecl(hasDescendant(
747 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000748 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000749 implicitCastExpr(
750 hasSourceExpression(opaqueValueExpr(
751 hasSourceExpression(integerLiteral(equals(1))))),
752 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000753 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000754 opaqueValueExpr(
755 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000756 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000757 unaryOperator(
758 hasOperatorName("-"),
759 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000760}
761
Gabor Marton19f4f392018-06-25 13:04:37 +0000762TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000763 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000764 testImport(
765 "void declToImport() {"
766 " struct point { double x; double y; };"
767 " struct point ptarray[10] = "
768 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
769 Lang_C, "", Lang_C, Verifier,
770 functionDecl(hasDescendant(
771 initListExpr(
772 has(designatedInitExpr(
773 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000774 hasDescendant(floatLiteral(equals(1.0))),
775 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000776 has(designatedInitExpr(
777 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000778 hasDescendant(floatLiteral(equals(2.0))),
779 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000780 has(designatedInitExpr(
781 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000782 hasDescendant(floatLiteral(equals(1.0))),
783 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000784}
785
Gabor Marton19f4f392018-06-25 13:04:37 +0000786TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000787 MatchVerifier<Decl> Verifier;
788 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000789 testImport(
790 "void declToImport() { (void)__func__; }",
791 Lang_CXX, "", Lang_CXX, Verifier,
792 functionDecl(hasDescendant(
793 predefinedExpr(
794 hasType(
795 asString("const char [13]")),
796 has(stringLiteral(hasType(
797 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000798}
799
Gabor Marton19f4f392018-06-25 13:04:37 +0000800TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000801 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000802 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000803 "void declToImport() {"
804 " struct point { double x; double y; };"
805 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
806 " [0].x = 1.0 }; }",
807 Lang_CXX, "", Lang_CXX, Verifier,
808 functionDecl(hasDescendant(
809 initListExpr(
810 has(
811 cxxConstructExpr(
812 requiresZeroInitialization())),
813 has(
814 initListExpr(
815 hasType(asString("struct point")),
816 has(floatLiteral(equals(1.0))),
817 has(implicitValueInitExpr(
818 hasType(asString("double")))))),
819 has(
820 initListExpr(
821 hasType(asString("struct point")),
822 has(floatLiteral(equals(2.0))),
823 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000824}
825
826
Aleksei Sidorina693b372016-09-28 10:16:56 +0000827const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
828
Gabor Marton19f4f392018-06-25 13:04:37 +0000829TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000830 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000831 testImport(
832 "void declToImport(__builtin_va_list list, ...) {"
833 " (void)__builtin_va_arg(list, int); }",
834 Lang_CXX, "", Lang_CXX, Verifier,
835 functionDecl(hasDescendant(
836 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000837}
838
Gabor Marton19f4f392018-06-25 13:04:37 +0000839TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000840 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000841 testImport(
842 "struct C {};"
843 "void declToImport() { C c = C(); }",
844 Lang_CXX, "", Lang_CXX, Verifier,
845 functionDecl(hasDescendant(
846 exprWithCleanups(has(cxxConstructExpr(
847 has(materializeTemporaryExpr(has(implicitCastExpr(
848 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000849}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000850
Gabor Marton19f4f392018-06-25 13:04:37 +0000851TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000852 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000853 testImport(
854 "void declToImport() { typedef _Atomic(int) a_int; }",
855 Lang_CXX11, "", Lang_CXX11, Verifier,
856 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000857}
858
Gabor Marton19f4f392018-06-25 13:04:37 +0000859TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000860 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000861 testImport(
862 "template <typename T> void declToImport() { };",
863 Lang_CXX, "", Lang_CXX, Verifier,
864 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000865}
866
Gabor Marton19f4f392018-06-25 13:04:37 +0000867TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000868 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000869 testImport(
870 "template <typename T> struct C { T t; };"
871 "template <typename T> void declToImport() {"
872 " C<T> d;"
873 " (void)d.t;"
874 "}"
875 "void instantiate() { declToImport<int>(); }",
876 Lang_CXX, "", Lang_CXX, Verifier,
877 functionTemplateDecl(hasDescendant(
878 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
879 testImport(
880 "template <typename T> struct C { T t; };"
881 "template <typename T> void declToImport() {"
882 " C<T> d;"
883 " (void)(&d)->t;"
884 "}"
885 "void instantiate() { declToImport<int>(); }",
886 Lang_CXX, "", Lang_CXX, Verifier,
887 functionTemplateDecl(hasDescendant(
888 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000889}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000890
Gabor Marton19f4f392018-06-25 13:04:37 +0000891TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000892 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000893 testImport(
894 "template <int K>"
895 "struct dummy { static const int i = K; };"
896 "template <int K> using dummy2 = dummy<K>;"
897 "int declToImport() { return dummy2<3>::i; }",
898 Lang_CXX11, "", Lang_CXX11, Verifier,
899 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000900 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000901 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
902}
903
904const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
905 varTemplateSpecializationDecl;
906
Gabor Marton19f4f392018-06-25 13:04:37 +0000907TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000908 MatchVerifier<Decl> Verifier;
909 testImport(
910 "template <typename T>"
911 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000912 "void declToImport() { (void)pi<int>; }",
913 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000914 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000915 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000916 unless(hasAncestor(translationUnitDecl(has(varDecl(
917 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000918}
919
Gabor Marton19f4f392018-06-25 13:04:37 +0000920TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000921 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000922 testImport(
923 "template <typename... Args>"
924 "struct dummy {"
925 " dummy(Args... args) {}"
926 " static const int i = 4;"
927 "};"
928 "int declToImport() { return dummy<int>::i; }",
929 Lang_CXX11, "", Lang_CXX11, Verifier,
930 functionDecl(hasDescendant(
931 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000932}
933
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000934const internal::VariadicDynCastAllOfMatcher<Type,
935 DependentTemplateSpecializationType>
936 dependentTemplateSpecializationType;
937
Gabor Marton19f4f392018-06-25 13:04:37 +0000938TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000939 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000940 testImport(
941 "template<typename T>"
942 "struct A;"
943 "template<typename T>"
944 "struct declToImport {"
945 " typename A<T>::template B<T> a;"
946 "};",
947 Lang_CXX, "", Lang_CXX, Verifier,
948 classTemplateDecl(has(cxxRecordDecl(has(
949 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000950}
951
952const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
953 sizeOfPackExpr;
954
Gabor Marton19f4f392018-06-25 13:04:37 +0000955TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000956 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000957 testImport(
958 "template <typename... Ts>"
959 "void declToImport() {"
960 " const int i = sizeof...(Ts);"
961 "};"
962 "void g() { declToImport<int>(); }",
963 Lang_CXX11, "", Lang_CXX11, Verifier,
964 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000965 testImport(
966 "template <typename... Ts>"
967 "using X = int[sizeof...(Ts)];"
968 "template <typename... Us>"
969 "struct Y {"
970 " X<Us..., int, double, int, Us...> f;"
971 "};"
972 "Y<float, int> declToImport;",
973 Lang_CXX11, "", Lang_CXX11, Verifier,
974 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
975 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
976}
977
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000978/// \brief Matches __builtin_types_compatible_p:
979/// GNU extension to check equivalent types
980/// Given
981/// \code
982/// __builtin_types_compatible_p(int, int)
983/// \endcode
984// will generate TypeTraitExpr <...> 'int'
985const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
986
Gabor Marton19f4f392018-06-25 13:04:37 +0000987TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000988 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000989 testImport(
990 "void declToImport() { "
991 " (void)__builtin_types_compatible_p(int, int);"
992 "}",
993 Lang_C, "", Lang_C, Verifier,
994 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000995}
996
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000997const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
998
Gabor Marton19f4f392018-06-25 13:04:37 +0000999TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001000 MatchVerifier<Decl> Verifier;
1001 testImport(
1002 "namespace std { class type_info {}; }"
1003 "void declToImport() {"
1004 " int x;"
1005 " auto a = typeid(int); auto b = typeid(x);"
1006 "}",
1007 Lang_CXX11, "", Lang_CXX11, Verifier,
1008 functionDecl(
1009 hasDescendant(varDecl(
1010 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1011 hasDescendant(varDecl(
1012 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1013}
1014
Gabor Marton19f4f392018-06-25 13:04:37 +00001015TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001016 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001017 testImport(
1018 "template<typename T> struct declToImport {"
1019 " void m() { (void)__is_pod(T); }"
1020 "};"
1021 "void f() { declToImport<int>().m(); }",
1022 Lang_CXX11, "", Lang_CXX11, Verifier,
1023 classTemplateDecl(has(cxxRecordDecl(has(
1024 functionDecl(hasDescendant(
1025 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001026}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001027
Gabor Marton6e1510c2018-07-12 11:50:21 +00001028TEST_P(ImportDecl, ImportRecordDeclInFunc) {
1029 MatchVerifier<Decl> Verifier;
1030 testImport("int declToImport() { "
1031 " struct data_t {int a;int b;};"
1032 " struct data_t d;"
1033 " return 0;"
1034 "}",
1035 Lang_C, "", Lang_C, Verifier,
1036 functionDecl(hasBody(compoundStmt(
1037 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
1038}
1039
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001040TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001041 Decl *FromTU = getTuDecl("int declToImport() { "
1042 " struct data_t {int a;int b;};"
1043 " struct data_t d;"
1044 " return 0;"
1045 "}",
1046 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +00001047 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +00001048 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
1049 ASSERT_TRUE(FromVar);
1050 auto ToType =
1051 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
1052 EXPECT_FALSE(ToType.isNull());
1053}
1054
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001055TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +00001056 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +00001057 Decl *FromTU = getTuDecl(
1058 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
1059 Lang_C, "input.c");
1060 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1061 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +00001062 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +00001063 auto *To = Import(From, Lang_C);
1064 EXPECT_EQ(To, nullptr);
1065}
1066
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001067TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001068 Decl *FromTU = getTuDecl(
1069 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1070 "int declToImport(){ return NONAME_SIZEOF(int); }",
1071 Lang_C, "input.c");
1072 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1073 FromTU, functionDecl(hasName("declToImport")));
1074 ASSERT_TRUE(From);
1075 auto *To = Import(From, Lang_C);
1076 ASSERT_TRUE(To);
1077 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1078 To, functionDecl(hasName("declToImport"),
1079 hasDescendant(unaryExprOrTypeTraitExpr()))));
1080}
1081
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001082TEST_P(ASTImporterOptionSpecificTestBase,
1083 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001084 // This construct is not supported by ASTImporter.
1085 Decl *FromTU = getTuDecl(
1086 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1087 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1088 Lang_C, "input.c");
1089 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1090 FromTU, functionDecl(hasName("declToImport")));
1091 ASSERT_TRUE(From);
1092 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001093 EXPECT_EQ(To, nullptr);
1094}
1095
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001096const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1097 cxxPseudoDestructorExpr;
1098
Gabor Marton19f4f392018-06-25 13:04:37 +00001099TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001100 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001101 testImport(
1102 "typedef int T;"
1103 "void declToImport(int *p) {"
1104 " T t;"
1105 " p->T::~T();"
1106 "}",
1107 Lang_CXX, "", Lang_CXX, Verifier,
1108 functionDecl(hasDescendant(
1109 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001110}
1111
Gabor Marton19f4f392018-06-25 13:04:37 +00001112TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001113 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001114 testImport(
1115 "namespace foo { int bar; }"
1116 "void declToImport() { using foo::bar; }",
1117 Lang_CXX, "", Lang_CXX, Verifier,
1118 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001119}
1120
1121/// \brief Matches shadow declarations introduced into a scope by a
1122/// (resolved) using declaration.
1123///
1124/// Given
1125/// \code
1126/// namespace n { int f; }
1127/// namespace declToImport { using n::f; }
1128/// \endcode
1129/// usingShadowDecl()
1130/// matches \code f \endcode
1131const internal::VariadicDynCastAllOfMatcher<Decl,
1132 UsingShadowDecl> usingShadowDecl;
1133
Gabor Marton19f4f392018-06-25 13:04:37 +00001134TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001135 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001136 testImport(
1137 "namespace foo { int bar; }"
1138 "namespace declToImport { using foo::bar; }",
1139 Lang_CXX, "", Lang_CXX, Verifier,
1140 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001141}
1142
Gabor Marton19f4f392018-06-25 13:04:37 +00001143TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001144 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001145 testImport(
1146 "template<typename T> int foo();"
1147 "template <typename T> void declToImport() {"
1148 " (void)::foo<T>;"
1149 " (void)::template foo<T>;"
1150 "}"
1151 "void instantiate() { declToImport<int>(); }",
1152 Lang_CXX, "", Lang_CXX, Verifier,
1153 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001154}
1155
Gabor Marton19f4f392018-06-25 13:04:37 +00001156TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001157 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001158 testImport(
1159 "template <typename T> struct C { T t; };"
1160 "template <typename T> void declToImport() {"
1161 " C<T> d;"
1162 " d.t = T();"
1163 "}"
1164 "void instantiate() { declToImport<int>(); }",
1165 Lang_CXX, "", Lang_CXX, Verifier,
1166 functionTemplateDecl(hasDescendant(
1167 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1168 testImport(
1169 "template <typename T> struct C { T t; };"
1170 "template <typename T> void declToImport() {"
1171 " C<T> d;"
1172 " (&d)->t = T();"
1173 "}"
1174 "void instantiate() { declToImport<int>(); }",
1175 Lang_CXX, "", Lang_CXX, Verifier,
1176 functionTemplateDecl(hasDescendant(
1177 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001178}
1179
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001180/// Check that function "declToImport()" (which is the templated function
1181/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1182/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001183TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001184 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001185 testImport(
1186 "template <typename T> void declToImport() { T a = 1; }"
1187 "void instantiate() { declToImport<int>(); }",
1188 Lang_CXX, "", Lang_CXX, Verifier,
1189 functionTemplateDecl(hasAncestor(translationUnitDecl(
1190 unless(has(functionDecl(hasName("declToImport"))))))));
1191 testImport(
1192 "template <typename T> struct declToImport { T t; };"
1193 "void instantiate() { declToImport<int>(); }",
1194 Lang_CXX, "", Lang_CXX, Verifier,
1195 classTemplateDecl(hasAncestor(translationUnitDecl(
1196 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001197}
1198
Gabor Marton19f4f392018-06-25 13:04:37 +00001199TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001200 MatchVerifier<Decl> Verifier;
1201 auto Code =
1202 R"s(
1203 struct declToImport {
1204 template <typename T0> struct X;
1205 template <typename T0> struct X<T0 *> {};
1206 };
1207 )s";
1208 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1209 recordDecl(has(classTemplateDecl()),
1210 has(classTemplateSpecializationDecl())));
1211}
1212
Gabor Marton19f4f392018-06-25 13:04:37 +00001213TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001214 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001215 testImport(
1216 "class declToImport {"
1217 " void f() { *this = declToImport(); }"
1218 "};",
1219 Lang_CXX, "", Lang_CXX, Verifier,
1220 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1221 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001222}
1223
Gabor Marton19f4f392018-06-25 13:04:37 +00001224TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001225 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001226 testImport(
1227 "template<typename T, int Size> class declToImport {"
1228 " T data[Size];"
1229 "};",
1230 Lang_CXX, "", Lang_CXX, Verifier,
1231 classTemplateDecl(has(cxxRecordDecl(
1232 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001233}
1234
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001235TEST_P(ASTImporterOptionSpecificTestBase,
1236 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001237 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1238 auto From =
1239 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1240 ASSERT_TRUE(From);
1241 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1242 ASSERT_TRUE(To);
1243 Decl *ToTemplated = To->getTemplatedDecl();
1244 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1245 EXPECT_TRUE(ToTemplated1);
1246 EXPECT_EQ(ToTemplated1, ToTemplated);
1247}
1248
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001249TEST_P(ASTImporterOptionSpecificTestBase,
1250 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001251 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1252 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1253 FromTU, functionTemplateDecl());
1254 ASSERT_TRUE(From);
1255 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1256 ASSERT_TRUE(To);
1257 Decl *ToTemplated = To->getTemplatedDecl();
1258 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1259 EXPECT_TRUE(ToTemplated1);
1260 EXPECT_EQ(ToTemplated1, ToTemplated);
1261}
1262
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001263TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001264 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1265 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1266 auto FromFT =
1267 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1268 ASSERT_TRUE(FromFT);
1269
1270 auto ToTemplated =
1271 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1272 EXPECT_TRUE(ToTemplated);
1273 auto ToTU = ToTemplated->getTranslationUnitDecl();
1274 auto ToFT =
1275 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1276 EXPECT_TRUE(ToFT);
1277}
1278
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001279TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001280 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001281 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1282 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1283 FromTU, functionTemplateDecl());
1284 ASSERT_TRUE(FromFT);
1285
1286 auto ToTemplated =
1287 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1288 EXPECT_TRUE(ToTemplated);
1289 auto ToTU = ToTemplated->getTranslationUnitDecl();
1290 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1291 ToTU, functionTemplateDecl());
1292 EXPECT_TRUE(ToFT);
1293}
1294
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001295TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001296 auto Code =
1297 R"(
1298 namespace x {
1299 template<class X> struct S1{};
1300 template<class X> struct S2{};
1301 template<class X> struct S3{};
1302 }
1303 )";
1304 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1305 auto FromNs =
1306 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1307 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1308 ASSERT_TRUE(ToNs);
1309 auto From =
1310 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1311 classTemplateDecl(
1312 hasName("S2")));
1313 auto To =
1314 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1315 classTemplateDecl(
1316 hasName("S2")));
1317 ASSERT_TRUE(From);
1318 ASSERT_TRUE(To);
1319 auto ToTemplated = To->getTemplatedDecl();
1320 auto ToTemplated1 =
1321 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1322 EXPECT_TRUE(ToTemplated1);
1323 ASSERT_EQ(ToTemplated1, ToTemplated);
1324}
1325
Tom Roeder521f0042019-02-26 19:26:41 +00001326TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1327 // This tests the import of isConditionTrue directly to make sure the importer
1328 // gets it right.
1329 Decl *From, *To;
1330 std::tie(From, To) = getImportedDecl(
1331 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1332 Lang_C, "", Lang_C);
1333
1334 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1335 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1336
1337 const ChooseExpr *FromChooseExpr =
1338 selectFirst<ChooseExpr>("choose", FromResults);
1339 ASSERT_TRUE(FromChooseExpr);
1340
1341 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1342 ASSERT_TRUE(ToChooseExpr);
1343
1344 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1345 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1346 ToChooseExpr->isConditionDependent());
1347}
1348
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001349TEST_P(ASTImporterOptionSpecificTestBase,
1350 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001351 Decl *From, *To;
1352 std::tie(From, To) = getImportedDecl(
1353 R"(
1354 template <typename T> struct X {};
1355
1356 void declToImport(int y, X<int> &x) {}
1357
1358 template <> struct X<int> {
1359 void g() {
1360 X<int> x;
1361 declToImport(0, x);
1362 }
1363 };
1364 )",
1365 Lang_CXX, "", Lang_CXX);
1366
1367 MatchVerifier<Decl> Verifier;
1368 auto Matcher = functionDecl(hasName("declToImport"),
1369 parameterCountIs(2),
1370 hasParameter(0, hasName("y")),
1371 hasParameter(1, hasName("x")),
1372 hasParameter(1, hasType(asString("X<int> &"))));
1373 ASSERT_TRUE(Verifier.match(From, Matcher));
1374 EXPECT_TRUE(Verifier.match(To, Matcher));
1375}
1376
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001377TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001378 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1379 Decl *From, *To;
1380 std::tie(From, To) =
1381 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1382 "void instantiate() { declToImport<int>(); }",
1383 Lang_CXX, "", Lang_CXX);
1384
1385 auto Check = [](Decl *D) -> bool {
1386 auto TU = D->getTranslationUnitDecl();
1387 for (auto Child : TU->decls()) {
1388 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1389 if (FD->getNameAsString() == "declToImport") {
1390 GTEST_NONFATAL_FAILURE_(
1391 "TU should not contain any FunctionDecl with name declToImport");
1392 return false;
1393 }
1394 }
1395 }
1396 return true;
1397 };
1398
1399 ASSERT_TRUE(Check(From));
1400 EXPECT_TRUE(Check(To));
1401}
1402
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001403TEST_P(ASTImporterOptionSpecificTestBase,
1404 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001405 Decl *From, *To;
1406 std::tie(From, To) =
1407 getImportedDecl("template <typename T> struct declToImport { T t; };"
1408 "void instantiate() { declToImport<int>(); }",
1409 Lang_CXX, "", Lang_CXX);
1410
1411 auto Check = [](Decl *D) -> bool {
1412 auto TU = D->getTranslationUnitDecl();
1413 for (auto Child : TU->decls()) {
1414 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1415 if (RD->getNameAsString() == "declToImport") {
1416 GTEST_NONFATAL_FAILURE_(
1417 "TU should not contain any CXXRecordDecl with name declToImport");
1418 return false;
1419 }
1420 }
1421 }
1422 return true;
1423 };
1424
1425 ASSERT_TRUE(Check(From));
1426 EXPECT_TRUE(Check(To));
1427}
1428
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001429TEST_P(ASTImporterOptionSpecificTestBase,
1430 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001431 Decl *From, *To;
1432 std::tie(From, To) =
1433 getImportedDecl(
1434 "template <typename T> struct X {};"
1435 "template <typename T> using declToImport = X<T>;"
1436 "void instantiate() { declToImport<int> a; }",
1437 Lang_CXX11, "", Lang_CXX11);
1438
1439 auto Check = [](Decl *D) -> bool {
1440 auto TU = D->getTranslationUnitDecl();
1441 for (auto Child : TU->decls()) {
1442 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1443 if (AD->getNameAsString() == "declToImport") {
1444 GTEST_NONFATAL_FAILURE_(
1445 "TU should not contain any TypeAliasDecl with name declToImport");
1446 return false;
1447 }
1448 }
1449 }
1450 return true;
1451 };
1452
1453 ASSERT_TRUE(Check(From));
1454 EXPECT_TRUE(Check(To));
1455}
1456
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001457TEST_P(ASTImporterOptionSpecificTestBase,
1458 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001459
1460 Decl *From, *To;
1461 std::tie(From, To) = getImportedDecl(
1462 R"(
1463 template<class T>
1464 class Base {};
1465 class declToImport : public Base<declToImport> {};
1466 )",
1467 Lang_CXX, "", Lang_CXX);
1468
1469 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1470 auto Pattern =
1471 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1472 ASSERT_TRUE(
1473 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1474 EXPECT_TRUE(
1475 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1476
1477 // Check that the ClassTemplateSpecializationDecl is the child of the
1478 // ClassTemplateDecl.
1479 Pattern = translationUnitDecl(has(classTemplateDecl(
1480 hasName("Base"), has(classTemplateSpecializationDecl()))));
1481 ASSERT_TRUE(
1482 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1483 EXPECT_TRUE(
1484 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1485}
1486
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001487AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1488 size_t Index = 0;
1489 for (FieldDecl *Field : Node.fields()) {
1490 if (Index == Order.size())
1491 return false;
1492 if (Field->getName() != Order[Index])
1493 return false;
1494 ++Index;
1495 }
1496 return Index == Order.size();
1497}
1498
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001499TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001500 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1501 Decl *From, *To;
1502 std::tie(From, To) = getImportedDecl(
1503 R"(
1504 namespace NS {
1505 template<class T>
1506 class X {};
1507 template class X<int>;
1508 }
1509 )",
1510 Lang_CXX, "", Lang_CXX, "NS");
1511
1512 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1513 // ClassTemplateDecl.
1514 auto Pattern = namespaceDecl(has(classTemplateDecl(
1515 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1516 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1517 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1518
1519 // Check that the ClassTemplateSpecializationDecl is the child of the
1520 // NamespaceDecl.
1521 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1522 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1523 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1524}
1525
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001526TEST_P(ASTImporterOptionSpecificTestBase,
1527 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001528 Decl *From, *To;
1529 std::tie(From, To) =
1530 getImportedDecl(
1531 "struct declToImport { int a; int b; };",
1532 Lang_CXX11, "", Lang_CXX11);
1533
1534 MatchVerifier<Decl> Verifier;
1535 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1536 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1537}
1538
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001539TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001540 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001541 Decl *From, *To;
1542 std::tie(From, To) = getImportedDecl(
1543 // The original recursive algorithm of ASTImporter first imports 'c' then
1544 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1545 R"s(
1546 struct declToImport {
1547 int a = c + b;
1548 int b = 1;
1549 int c = 2;
1550 };
1551 )s",
1552 Lang_CXX11, "", Lang_CXX11);
1553
1554 MatchVerifier<Decl> Verifier;
1555 ASSERT_TRUE(
1556 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1557 EXPECT_TRUE(
1558 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1559}
1560
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001561TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001562 Decl *From, *To;
1563 std::tie(From, To) = getImportedDecl(
1564 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001565 struct declToImport {
1566 };
1567 )",
1568 Lang_CXX, "", Lang_CXX);
1569
1570 MatchVerifier<Decl> Verifier;
1571 // Match the implicit Decl.
1572 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1573 ASSERT_TRUE(Verifier.match(From, Matcher));
1574 EXPECT_TRUE(Verifier.match(To, Matcher));
1575}
1576
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001577TEST_P(ASTImporterOptionSpecificTestBase,
1578 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001579 Decl *From, *To;
1580 std::tie(From, To) = getImportedDecl(
1581 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001582 template <typename U>
1583 struct declToImport {
1584 };
1585 )",
1586 Lang_CXX, "", Lang_CXX);
1587
1588 MatchVerifier<Decl> Verifier;
1589 // Match the implicit Decl.
1590 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1591 ASSERT_TRUE(Verifier.match(From, Matcher));
1592 EXPECT_TRUE(Verifier.match(To, Matcher));
1593}
1594
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001595TEST_P(ASTImporterOptionSpecificTestBase,
1596 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001597 Decl *From, *To;
1598 std::tie(From, To) = getImportedDecl(
1599 R"(
1600 template<class T>
1601 class Base {};
1602 class declToImport : public Base<declToImport> {};
1603 )",
1604 Lang_CXX, "", Lang_CXX);
1605
1606 auto hasImplicitClass = has(cxxRecordDecl());
1607 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1608 hasName("Base"),
1609 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1610 ASSERT_TRUE(
1611 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1612 EXPECT_TRUE(
1613 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1614}
1615
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001616TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001617 Decl *From, *To;
1618 std::tie(From, To) =
1619 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1620
1621 MatchVerifier<Decl> Verifier;
1622 auto Matcher = functionDecl();
1623 ASSERT_TRUE(Verifier.match(From, Matcher));
1624 EXPECT_TRUE(Verifier.match(To, Matcher));
1625 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1626}
1627
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001628TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001629 Decl *FromTU = getTuDecl(
1630 R"(
1631 struct X {};
1632 void operator<<(int, X);
1633 )",
1634 Lang_CXX);
1635 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1636 const Decl *To = Import(From, Lang_CXX);
1637 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1638}
1639
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001640TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001641 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1642 Decl *From, *To;
1643 std::tie(From, To) = getImportedDecl(
1644 R"(
1645 template<class T>
1646 class Base { int a; };
1647 class declToImport : Base<declToImport> {};
1648 )",
1649 Lang_CXX, "", Lang_CXX);
1650
1651 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1652 hasName("Base"),
1653 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1654 ASSERT_TRUE(
1655 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1656 EXPECT_TRUE(
1657 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1658}
1659
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001660TEST_P(ASTImporterOptionSpecificTestBase,
1661 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001662 {
1663 Decl *FromTU = getTuDecl(
1664 R"(
1665 template <typename T>
1666 struct B;
1667 )",
1668 Lang_CXX, "input0.cc");
1669 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1670 FromTU, classTemplateDecl(hasName("B")));
1671
1672 Import(FromD, Lang_CXX);
1673 }
1674
1675 {
1676 Decl *FromTU = getTuDecl(
1677 R"(
1678 template <typename T>
1679 struct B {
1680 void f();
1681 };
1682 )",
1683 Lang_CXX, "input1.cc");
1684 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1685 FromTU, functionDecl(hasName("f")));
1686 Import(FromD, Lang_CXX);
1687 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1688 FromTU, classTemplateDecl(hasName("B")));
1689 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1690 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1691 }
1692}
1693
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001694TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001695 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1696 Decl *ToTU = getToTuDecl(
1697 R"(
1698 template <typename T>
1699 struct B {
1700 void f();
1701 };
1702
1703 template <typename T>
1704 struct B;
1705 )",
1706 Lang_CXX);
1707 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1708 [](const ClassTemplateDecl *T) {
1709 return T->isThisDeclarationADefinition();
1710 })
1711 .match(ToTU, classTemplateDecl()));
1712
1713 Decl *FromTU = getTuDecl(
1714 R"(
1715 template <typename T>
1716 struct B {
1717 void f();
1718 };
1719 )",
1720 Lang_CXX, "input1.cc");
1721 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1722 FromTU, classTemplateDecl(hasName("B")));
1723
1724 Import(FromD, Lang_CXX);
1725
1726 // We should have only one definition.
1727 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1728 [](const ClassTemplateDecl *T) {
1729 return T->isThisDeclarationADefinition();
1730 })
1731 .match(ToTU, classTemplateDecl()));
1732}
1733
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001734TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001735 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1736 Decl *ToTU = getToTuDecl(
1737 R"(
1738 struct B {
1739 void f();
1740 };
1741
1742 struct B;
1743 )",
1744 Lang_CXX);
1745 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001746 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001747
1748 Decl *FromTU = getTuDecl(
1749 R"(
1750 struct B {
1751 void f();
1752 };
1753 )",
1754 Lang_CXX, "input1.cc");
1755 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1756 FromTU, cxxRecordDecl(hasName("B")));
1757
1758 Import(FromD, Lang_CXX);
1759
1760 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001761 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001762}
1763
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001764static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1765 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1766 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1767 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1768 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1769}
1770static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1771 SourceManager &SM1, SourceManager &SM2) {
1772 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1773 FullSourceLoc{ Range2.getBegin(), SM2 });
1774 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1775 FullSourceLoc{ Range2.getEnd(), SM2 });
1776}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001777TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001778 Decl *FromTU = getTuDecl(
1779 R"(
1780 #define MFOO(arg) arg = arg + 1
1781
1782 void foo() {
1783 int a = 5;
1784 MFOO(a);
1785 }
1786 )",
1787 Lang_CXX);
1788 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1789 auto ToD = Import(FromD, Lang_CXX);
1790
1791 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1792 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1793 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1794 auto FromRHS =
1795 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1796
1797 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1798 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1799 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1800 FromSM);
1801 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1802 FromSM);
1803 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1804 FromSM);
1805}
1806
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001807TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001808 Decl *FromTU = getTuDecl(
1809 R"(
1810 #define FUNC_INT void declToImport
1811 #define FUNC FUNC_INT
1812 FUNC(int a);
1813 )",
1814 Lang_CXX);
1815 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1816 auto ToD = Import(FromD, Lang_CXX);
1817
1818 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1819 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1820 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1821 FromSM);
1822}
1823
Gabor Marton9581c332018-05-23 13:53:36 +00001824TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001825 ASTImporterOptionSpecificTestBase,
1826 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001827 Decl *ToTU = getToTuDecl(
1828 R"(
1829 template <typename T>
1830 struct B;
1831
1832 template <>
1833 struct B<int> {};
1834
1835 template <>
1836 struct B<int>;
1837 )",
1838 Lang_CXX);
1839 // We should have only one definition.
1840 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1841 [](const ClassTemplateSpecializationDecl *T) {
1842 return T->isThisDeclarationADefinition();
1843 })
1844 .match(ToTU, classTemplateSpecializationDecl()));
1845
1846 Decl *FromTU = getTuDecl(
1847 R"(
1848 template <typename T>
1849 struct B;
1850
1851 template <>
1852 struct B<int> {};
1853 )",
1854 Lang_CXX, "input1.cc");
1855 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1856 FromTU, classTemplateSpecializationDecl(hasName("B")));
1857
1858 Import(FromD, Lang_CXX);
1859
1860 // We should have only one definition.
1861 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1862 [](const ClassTemplateSpecializationDecl *T) {
1863 return T->isThisDeclarationADefinition();
1864 })
1865 .match(ToTU, classTemplateSpecializationDecl()));
1866}
1867
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001868TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001869 Decl *FromTU = getTuDecl(
1870 R"(
1871 struct { int a; int b; } object0 = { 2, 3 };
1872 struct { int x; int y; int z; } object1;
1873 )",
1874 Lang_CXX, "input0.cc");
1875
Gabor Marton0bebf952018-07-05 09:51:13 +00001876 auto *Obj0 =
1877 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1878 auto *From0 = getRecordDecl(Obj0);
1879 auto *Obj1 =
1880 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1881 auto *From1 = getRecordDecl(Obj1);
1882
1883 auto *To0 = Import(From0, Lang_CXX);
1884 auto *To1 = Import(From1, Lang_CXX);
1885
1886 EXPECT_TRUE(To0);
1887 EXPECT_TRUE(To1);
1888 EXPECT_NE(To0, To1);
1889 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1890}
1891
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001892TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001893 auto *Code =
1894 R"(
1895 struct X {
1896 struct { int a; };
1897 struct { int b; };
1898 };
1899 )";
1900 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1901
1902 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1903
1904 auto *X0 =
1905 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1906 auto *X1 =
1907 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1908 Import(X0, Lang_C);
1909 Import(X1, Lang_C);
1910
1911 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1912 // We expect no (ODR) warning during the import.
1913 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1914 EXPECT_EQ(1u,
1915 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1916}
1917
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001918TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001919 Decl *FromTU0 = getTuDecl(
1920 R"(
1921 struct X {
1922 struct { int a; };
1923 struct { int b; };
1924 };
1925 )",
1926 Lang_C, "input0.c");
1927
1928 Decl *FromTU1 = getTuDecl(
1929 R"(
1930 struct X { // reversed order
1931 struct { int b; };
1932 struct { int a; };
1933 };
1934 )",
1935 Lang_C, "input1.c");
1936
1937 auto *X0 =
1938 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1939 auto *X1 =
1940 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1941 Import(X0, Lang_C);
1942 Import(X1, Lang_C);
1943
1944 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1945 // We expect one (ODR) warning during the import.
1946 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1947 EXPECT_EQ(2u,
1948 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1949}
1950
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001951TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001952 auto Pattern = varDecl(hasName("x"));
1953 VarDecl *Imported1;
1954 {
1955 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1956 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1957 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1958 }
1959 VarDecl *Imported2;
1960 {
1961 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1962 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1963 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1964 }
1965 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1966 EXPECT_FALSE(Imported2->isUsed(false));
1967 {
1968 Decl *FromTU =
1969 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001970 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1971 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001972 Import(FromD, Lang_CXX);
1973 }
1974 EXPECT_TRUE(Imported2->isUsed(false));
1975}
1976
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001977TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001978 auto Pattern = varDecl(hasName("x"));
1979 VarDecl *ExistingD;
1980 {
1981 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1982 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1983 }
1984 EXPECT_FALSE(ExistingD->isUsed(false));
1985 {
1986 Decl *FromTU = getTuDecl(
1987 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1988 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1989 FromTU, functionDecl(hasName("f")));
1990 Import(FromD, Lang_CXX);
1991 }
1992 EXPECT_TRUE(ExistingD->isUsed(false));
1993}
1994
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001995TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001996 auto Pattern = varDecl(hasName("a"));
1997 VarDecl *ExistingD;
1998 {
1999 Decl *ToTU = getToTuDecl(
2000 R"(
2001 struct A {
2002 static const int a = 1;
2003 };
2004 )", Lang_CXX);
2005 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
2006 }
2007 EXPECT_FALSE(ExistingD->isUsed(false));
2008 {
2009 Decl *FromTU = getTuDecl(
2010 R"(
2011 struct A {
2012 static const int a = 1;
2013 };
2014 const int *f() { return &A::a; } // requires storage,
2015 // thus used flag will be set
2016 )", Lang_CXX, "input1.cc");
2017 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2018 FromTU, functionDecl(hasName("f")));
2019 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2020 ASSERT_TRUE(FromD->isUsed(false));
2021 Import(FromFunD, Lang_CXX);
2022 }
2023 EXPECT_TRUE(ExistingD->isUsed(false));
2024}
2025
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002026TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002027 auto Pattern = varDecl(hasName("x"));
2028
2029 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2030 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2031
2032 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2033
2034 ASSERT_FALSE(Imported1->isUsed(false));
2035
2036 FromD->setIsUsed();
2037 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2038
2039 EXPECT_EQ(Imported1, Imported2);
2040 EXPECT_TRUE(Imported2->isUsed(false));
2041}
2042
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002043struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002044
Gabor Marton5254e642018-06-27 13:32:50 +00002045TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002046 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2047 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002048 auto *From =
2049 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002050
Gabor Marton5254e642018-06-27 13:32:50 +00002051 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002052 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2053
Gabor Marton5254e642018-06-27 13:32:50 +00002054 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2055 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2056 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2057 EXPECT_TRUE(ImportedD == To0);
2058 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2059 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2060 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002061}
2062
2063TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2064 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2065 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002066 auto *From =
2067 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002068
Gabor Marton5254e642018-06-27 13:32:50 +00002069 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002070 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2071
Gabor Marton5254e642018-06-27 13:32:50 +00002072 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2073 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2074 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2075 EXPECT_TRUE(ImportedD == To1);
2076 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2077 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2078 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002079}
2080
Peter Szecsidedda6f2018-03-30 22:03:29 +00002081TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2082 auto Code =
2083 R"(
2084 struct B { virtual void f(); };
2085 void B::f() {}
2086 struct D : B { void f(); };
2087 )";
2088 auto Pattern =
2089 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2090 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2091 CXXMethodDecl *Proto =
2092 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2093
2094 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2095 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2096 EXPECT_EQ(To->size_overridden_methods(), 1u);
2097}
2098
2099TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2100 auto Code =
2101 R"(
2102 struct B { virtual void f(); };
2103 void B::f() {}
2104 )";
2105 auto Pattern =
2106 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2107 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2108 CXXMethodDecl *Proto =
2109 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2110 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2111
2112 ASSERT_TRUE(Proto->isVirtual());
2113 ASSERT_TRUE(Def->isVirtual());
2114 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2115 EXPECT_TRUE(To->isVirtual());
2116}
2117
Gabor Marton5254e642018-06-27 13:32:50 +00002118TEST_P(ImportFunctions,
2119 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2120 Decl *ToTU = getToTuDecl(
2121 R"(
2122 void f() {}
2123 void f();
2124 )",
2125 Lang_CXX);
2126 ASSERT_EQ(1u,
2127 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2128 return FD->doesThisDeclarationHaveABody();
2129 }).match(ToTU, functionDecl()));
2130
2131 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2132 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2133
2134 Import(FromD, Lang_CXX);
2135
2136 EXPECT_EQ(1u,
2137 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2138 return FD->doesThisDeclarationHaveABody();
2139 }).match(ToTU, functionDecl()));
2140}
2141
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002142TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2143 auto Code =
2144 R"(
2145 struct B { virtual void f(); };
2146 struct D:B { void f(); };
2147 )";
2148 auto BFP =
2149 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2150 auto DFP =
2151 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2152
2153 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2154 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2155 Import(DF, Lang_CXX);
2156
2157 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2158 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2159 Import(BF, Lang_CXX);
2160
2161 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2162
2163 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2164 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2165}
2166
2167TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2168 auto CodeWithoutDef =
2169 R"(
2170 struct B { virtual void f(); };
2171 struct D:B { void f(); };
2172 )";
2173 auto CodeWithDef =
2174 R"(
2175 struct B { virtual void f(){}; };
2176 struct D:B { void f(){}; };
2177 )";
2178 auto BFP =
2179 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2180 auto DFP =
2181 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2182 auto BFDefP = cxxMethodDecl(
2183 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2184 auto DFDefP = cxxMethodDecl(
2185 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2186 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2187
2188 {
2189 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2190 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2191 Import(FromD, Lang_CXX);
2192 }
2193 {
2194 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2195 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2196 Import(FromB, Lang_CXX);
2197 }
2198
2199 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2200
2201 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2202 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2203 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2204 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2205 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2206}
2207
2208TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2209 auto Code =
2210 R"(
2211 struct B { virtual void f(); };
2212 struct D:B { void f(); };
2213 void B::f(){};
2214 )";
2215
2216 auto BFP =
2217 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2218 auto BFDefP = cxxMethodDecl(
2219 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2220 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2221 unless(isDefinition()));
2222
2223 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2224 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2225 Import(D, Lang_CXX);
2226
2227 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2228 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2229 Import(B, Lang_CXX);
2230
2231 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2232
2233 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2234 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2235
2236 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2237 ToTU, cxxRecordDecl(hasName("B")));
2238 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2239 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2240 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2241
2242 // The definition should be out-of-class.
2243 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2244 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2245 ToBFOutOfClass->getLexicalDeclContext());
2246 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2247 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2248
2249 // Check that the redecl chain is intact.
2250 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2251}
2252
2253TEST_P(ImportFunctions,
2254 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2255 auto CodeTU0 =
2256 R"(
2257 struct B { virtual void f(); };
2258 struct D:B { void f(); };
2259 )";
2260 auto CodeTU1 =
2261 R"(
2262 struct B { virtual void f(); };
2263 struct D:B { void f(); };
2264 void B::f(){}
2265 void D::f(){}
2266 void foo(B &b, D &d) { b.f(); d.f(); }
2267 )";
2268
2269 auto BFP =
2270 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2271 auto BFDefP = cxxMethodDecl(
2272 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2273 auto DFP =
2274 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2275 auto DFDefP = cxxMethodDecl(
2276 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2277 auto FooDef = functionDecl(hasName("foo"));
2278
2279 {
2280 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2281 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2282 Import(D, Lang_CXX);
2283 }
2284
2285 {
2286 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2287 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2288 Import(Foo, Lang_CXX);
2289 }
2290
2291 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2292
2293 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2294 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2295 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2296 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2297
2298 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2299 ToTU, cxxRecordDecl(hasName("B")));
2300 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2301 ToTU, cxxRecordDecl(hasName("D")));
2302 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2303 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2304 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2305 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2306 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2307 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2308
2309 // The definition should be out-of-class.
2310 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2311 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2312 ToBFOutOfClass->getLexicalDeclContext());
2313 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2314 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2315
2316 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2317 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2318 ToDFOutOfClass->getLexicalDeclContext());
2319 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2320 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2321
2322 // Check that the redecl chain is intact.
2323 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2324 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2325}
2326
Gabor Marton458d1452019-02-14 13:07:03 +00002327//FIXME Move these tests to a separate test file.
2328namespace TypeAndValueParameterizedTests {
2329
2330// Type parameters for type-parameterized test fixtures.
2331struct GetFunPattern {
2332 using DeclTy = FunctionDecl;
2333 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
2334};
2335struct GetVarPattern {
2336 using DeclTy = VarDecl;
2337 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
2338};
2339
2340// Values for the value-parameterized test fixtures.
2341// FunctionDecl:
2342auto *ExternF = "void f();";
2343auto *StaticF = "static void f();";
2344auto *AnonF = "namespace { void f(); }";
2345// VarDecl:
2346auto *ExternV = "extern int v;";
2347auto *StaticV = "static int v;";
2348auto *AnonV = "namespace { extern int v; }";
2349
2350// First value in tuple: Compile options.
2351// Second value in tuple: Source code to be used in the test.
2352using ImportVisibilityChainParams =
2353 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
2354// Fixture to test the redecl chain of Decls with the same visibility. Gtest
2355// makes it possible to have either value-parameterized or type-parameterized
2356// fixtures. However, we cannot have both value- and type-parameterized test
2357// fixtures. This is a value-parameterized test fixture in the gtest sense. We
2358// intend to mimic gtest's type-parameters via the PatternFactory template
2359// parameter. We manually instantiate the different tests with the each types.
2360template <typename PatternFactory>
2361class ImportVisibilityChain
2362 : public ASTImporterTestBase, public ImportVisibilityChainParams {
2363protected:
2364 using DeclTy = typename PatternFactory::DeclTy;
2365 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2366 std::string getCode() const { return std::get<1>(GetParam()); }
2367 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2368
2369 // Type-parameterized test.
2370 void TypedTest_ImportChain() {
2371 std::string Code = getCode() + getCode();
2372 auto Pattern = getPattern();
2373
2374 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
2375
2376 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
2377 auto *FromF1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
2378
2379 auto *ToF0 = Import(FromF0, Lang_CXX);
2380 auto *ToF1 = Import(FromF1, Lang_CXX);
2381
2382 EXPECT_TRUE(ToF0);
2383 ASSERT_TRUE(ToF1);
2384 EXPECT_NE(ToF0, ToF1);
2385 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2386 }
2387};
2388
2389// Manual instantiation of the fixture with each type.
2390using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
2391using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
2392// Value-parameterized test for the first type.
2393TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
2394 TypedTest_ImportChain();
2395}
2396// Value-parameterized test for the second type.
2397TEST_P(ImportVariablesVisibilityChain, ImportChain) {
2398 TypedTest_ImportChain();
2399}
2400
2401// Automatic instantiation of the value-parameterized tests.
2402INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
2403 ::testing::Combine(
2404 DefaultTestValuesForRunOptions,
2405 ::testing::Values(ExternF, StaticF, AnonF)), );
2406INSTANTIATE_TEST_CASE_P(
2407 ParameterizedTests, ImportVariablesVisibilityChain,
2408 ::testing::Combine(
2409 DefaultTestValuesForRunOptions,
2410 // There is no point to instantiate with StaticV, because in C++ we can
2411 // forward declare a variable only with the 'extern' keyword.
2412 // Consequently, each fwd declared variable has external linkage. This
2413 // is different in the C language where any declaration without an
2414 // initializer is a tentative definition, subsequent definitions may be
2415 // provided but they must have the same linkage. See also the test
2416 // ImportVariableChainInC which test for this special C Lang case.
2417 ::testing::Values(ExternV, AnonV)), );
2418
2419// First value in tuple: Compile options.
2420// Second value in tuple: Tuple with informations for the test.
2421// Code for first import (or initial code), code to import, whether the `f`
2422// functions are expected to be linked in a declaration chain.
2423// One value of this tuple is combined with every value of compile options.
2424// The test can have a single tuple as parameter only.
2425using ImportVisibilityParams = ::testing::WithParamInterface<
2426 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
2427
2428template <typename PatternFactory>
2429class ImportVisibility
2430 : public ASTImporterTestBase,
2431 public ImportVisibilityParams {
2432protected:
2433 using DeclTy = typename PatternFactory::DeclTy;
2434 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
2435 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
2436 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
2437 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
2438 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
2439
2440 void TypedTest_ImportAfter() {
2441 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
2442 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2443
2444 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
2445 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
2446
2447 auto *ToF1 = Import(FromF1, Lang_CXX);
2448
2449 ASSERT_TRUE(ToF0);
2450 ASSERT_TRUE(ToF1);
2451 EXPECT_NE(ToF0, ToF1);
2452
2453 if (shouldBeLinked())
2454 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2455 else
2456 EXPECT_FALSE(ToF1->getPreviousDecl());
2457 }
2458
2459 void TypedTest_ImportAfterImport() {
2460 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
2461 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
2462 auto *FromF0 =
2463 FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
2464 auto *FromF1 =
2465 FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
2466 auto *ToF0 = Import(FromF0, Lang_CXX);
2467 auto *ToF1 = Import(FromF1, Lang_CXX);
2468 ASSERT_TRUE(ToF0);
2469 ASSERT_TRUE(ToF1);
2470 EXPECT_NE(ToF0, ToF1);
2471 if (shouldBeLinked())
2472 EXPECT_EQ(ToF1->getPreviousDecl(), ToF0);
2473 else
2474 EXPECT_FALSE(ToF1->getPreviousDecl());
2475 }
2476};
2477using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
2478using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
2479
2480// FunctionDecl.
2481TEST_P(ImportFunctionsVisibility, ImportAfter) {
2482 TypedTest_ImportAfter();
2483}
2484TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
2485 TypedTest_ImportAfterImport();
2486}
2487// VarDecl.
2488TEST_P(ImportVariablesVisibility, ImportAfter) {
2489 TypedTest_ImportAfter();
2490}
2491TEST_P(ImportVariablesVisibility, ImportAfterImport) {
2492 TypedTest_ImportAfterImport();
2493}
2494
2495bool ExpectLink = true;
2496bool ExpectNotLink = false;
2497
2498INSTANTIATE_TEST_CASE_P(
2499 ParameterizedTests, ImportFunctionsVisibility,
2500 ::testing::Combine(
2501 DefaultTestValuesForRunOptions,
2502 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
2503 std::make_tuple(ExternF, StaticF, ExpectNotLink),
2504 std::make_tuple(ExternF, AnonF, ExpectNotLink),
2505 std::make_tuple(StaticF, ExternF, ExpectNotLink),
2506 std::make_tuple(StaticF, StaticF, ExpectNotLink),
2507 std::make_tuple(StaticF, AnonF, ExpectNotLink),
2508 std::make_tuple(AnonF, ExternF, ExpectNotLink),
2509 std::make_tuple(AnonF, StaticF, ExpectNotLink),
2510 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
2511INSTANTIATE_TEST_CASE_P(
2512 ParameterizedTests, ImportVariablesVisibility,
2513 ::testing::Combine(
2514 DefaultTestValuesForRunOptions,
2515 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
2516 std::make_tuple(ExternV, StaticV, ExpectNotLink),
2517 std::make_tuple(ExternV, AnonV, ExpectNotLink),
2518 std::make_tuple(StaticV, ExternV, ExpectNotLink),
2519 std::make_tuple(StaticV, StaticV, ExpectNotLink),
2520 std::make_tuple(StaticV, AnonV, ExpectNotLink),
2521 std::make_tuple(AnonV, ExternV, ExpectNotLink),
2522 std::make_tuple(AnonV, StaticV, ExpectNotLink),
2523 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
2524
2525} // namespace TypeAndValueParameterizedTests
2526
2527TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2528 std::string Code = "static int v; static int v = 0;";
2529 auto Pattern = varDecl(hasName("v"));
2530
2531 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2532
2533 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2534 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2535
2536 auto *To0 = Import(From0, Lang_C);
2537 auto *To1 = Import(From1, Lang_C);
2538
2539 EXPECT_TRUE(To0);
2540 ASSERT_TRUE(To1);
2541 EXPECT_NE(To0, To1);
2542 EXPECT_EQ(To1->getPreviousDecl(), To0);
2543}
2544
2545TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2546 TranslationUnitDecl *FromTu = getTuDecl(
2547 "namespace NS0 { namespace { void f(); } }"
2548 "namespace NS1 { namespace { void f(); } }",
2549 Lang_CXX, "input0.cc");
2550 auto Pattern = functionDecl(hasName("f"));
2551
2552 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2553 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2554
2555 auto *ToF0 = Import(FromF0, Lang_CXX);
2556 auto *ToF1 = Import(FromF1, Lang_CXX);
2557
2558 EXPECT_TRUE(ToF0);
2559 ASSERT_TRUE(ToF1);
2560 EXPECT_NE(ToF0, ToF1);
2561 EXPECT_FALSE(ToF1->getPreviousDecl());
2562}
2563
2564TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2565 {
2566 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2567 Lang_CXX, "input0.cc");
2568 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2569 FromTU, functionDecl(hasName("g0")));
2570
2571 Import(FromD, Lang_CXX);
2572 }
2573 {
2574 Decl *FromTU =
2575 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2576 Lang_CXX, "input1.cc");
2577 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2578 FromTU, functionDecl(hasName("g1")));
2579 Import(FromD, Lang_CXX);
2580 }
2581
2582 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2583 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2584 2u);
2585}
2586
Gabor Marton302f3002019-02-15 12:04:05 +00002587TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2588 Decl *FromTU = getTuDecl(
2589 R"(
2590 void foo() {
2591 (void)[]() { ; };
2592 }
2593 )",
2594 Lang_CXX11);
2595 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2596 FromTU, functionDecl(hasName("foo")));
2597 auto *ToD = Import(FromD, Lang_CXX);
2598 EXPECT_TRUE(ToD);
2599 CXXRecordDecl *LambdaRec =
2600 cast<LambdaExpr>(cast<CStyleCastExpr>(
2601 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2602 ->getSubExpr())
2603 ->getLambdaClass();
2604 EXPECT_TRUE(LambdaRec->getDestructor());
2605}
2606
Gabor Marton5254e642018-06-27 13:32:50 +00002607struct ImportFriendFunctions : ImportFunctions {};
2608
2609TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2610 auto Pattern = functionDecl(hasName("f"));
2611
2612 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2613 "void f();",
2614 Lang_CXX,
2615 "input0.cc");
2616 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2617
2618 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2619 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2620 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2621 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2622 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2623 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2624 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2625}
2626
2627TEST_P(ImportFriendFunctions,
2628 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2629 auto Pattern = functionDecl(hasName("f"));
2630
2631 Decl *FromTU = getTuDecl("void f();"
2632 "struct X { friend void f(); };",
2633 Lang_CXX, "input0.cc");
2634 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2635
2636 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2637 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2638 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2639 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2640 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2641 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2642 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2643}
2644
2645TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2646 auto Pattern = functionDecl(hasName("f"));
2647
2648 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2649 "void f();",
2650 Lang_CXX,
2651 "input0.cc");
2652 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2653
2654 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2655 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2656 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2657 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2658 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2659 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2660 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2661}
2662
2663TEST_P(ImportFriendFunctions,
2664 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2665 auto Pattern = functionDecl(hasName("f"));
2666
2667 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2668 "void f(){}",
2669 Lang_CXX, "input0.cc");
2670 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2671
2672 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2673 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2674 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2675 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2676 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2677 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2678 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2679}
2680
Gabor Marton26f72a92018-07-12 09:42:05 +00002681// Disabled temporarily, because the new structural equivalence check
2682// (https://reviews.llvm.org/D48628) breaks it.
2683// PreviousDecl is not set because there is no structural match.
2684// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002685TEST_P(ImportFriendFunctions,
2686 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2687 auto Pattern = functionDecl(hasName("f"));
2688
2689 Decl *FromTU = getTuDecl(
2690 R"(
2691 class X;
2692 void f(X *x){}
2693 class X{
2694 friend void f(X *x);
2695 };
2696 )",
2697 Lang_CXX, "input0.cc");
2698 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2699
2700 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2701 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2702 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2703 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2704 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2705 .match(ToTU, friendDecl())
2706 ->getFriendDecl());
2707 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2708 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2709 // The parameters must refer the same type
2710 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2711 (*ImportedD->param_begin())->getOriginalType());
2712}
2713
Gabor Marton26f72a92018-07-12 09:42:05 +00002714// Disabled temporarily, because the new structural equivalence check
2715// (https://reviews.llvm.org/D48628) breaks it.
2716// PreviousDecl is not set because there is no structural match.
2717// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002718TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002719 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002720 auto Pattern = functionDecl(hasName("f"));
2721
2722 Decl *FromTU = getTuDecl(
2723 R"(
2724 class X;
2725 void f(X *x){}
2726 class X{
2727 friend void f(X *x);
2728 };
2729 )",
2730 Lang_CXX, "input0.cc");
2731 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2732
2733 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2734 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2735 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2736 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2737 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2738 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2739
2740 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2741 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2742 // The parameters must refer the same type
2743 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2744 (*ImportedD->param_begin())->getOriginalType());
2745}
2746
2747TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2748 auto Pattern = functionDecl(hasName("f"));
2749
2750 FunctionDecl *ImportedD;
2751 {
2752 Decl *FromTU =
2753 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2754 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2755 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2756 }
2757 FunctionDecl *ImportedD1;
2758 {
2759 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2760 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2761 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2762 }
2763
2764 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2765 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2766 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2767 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2768 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2769}
2770
Balazs Keri89632b82018-08-21 14:32:21 +00002771TEST_P(ImportFriendFunctions, Lookup) {
2772 auto FunctionPattern = functionDecl(hasName("f"));
2773 auto ClassPattern = cxxRecordDecl(hasName("X"));
2774
2775 TranslationUnitDecl *FromTU =
2776 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2777 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2778 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2779 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2780 {
2781 auto FromName = FromD->getDeclName();
2782 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2783 auto LookupRes = Class->noload_lookup(FromName);
2784 ASSERT_EQ(LookupRes.size(), 0u);
2785 LookupRes = FromTU->noload_lookup(FromName);
2786 ASSERT_EQ(LookupRes.size(), 1u);
2787 }
2788
2789 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2790 auto ToName = ToD->getDeclName();
2791
2792 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2793 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2794 auto LookupRes = Class->noload_lookup(ToName);
2795 EXPECT_EQ(LookupRes.size(), 0u);
2796 LookupRes = ToTU->noload_lookup(ToName);
2797 EXPECT_EQ(LookupRes.size(), 1u);
2798
2799 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2800 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2801 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2802 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2803}
2804
2805TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2806 auto FunctionPattern = functionDecl(hasName("f"));
2807 auto ClassPattern = cxxRecordDecl(hasName("X"));
2808
2809 TranslationUnitDecl *FromTU = getTuDecl(
2810 "struct X { friend void f(); };"
2811 // This proto decl makes f available to normal
2812 // lookup, otherwise it is hidden.
2813 // Normal C++ lookup (implemented in
2814 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2815 // returns the found `NamedDecl` only if the set IDNS is matched
2816 "void f();",
2817 Lang_CXX, "input0.cc");
2818 auto *FromFriend =
2819 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2820 auto *FromNormal =
2821 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2822 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2823 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2824 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2825 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2826
2827 auto FromName = FromFriend->getDeclName();
2828 auto *FromClass =
2829 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2830 auto LookupRes = FromClass->noload_lookup(FromName);
2831 ASSERT_EQ(LookupRes.size(), 0u);
2832 LookupRes = FromTU->noload_lookup(FromName);
2833 ASSERT_EQ(LookupRes.size(), 1u);
2834
2835 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2836 auto ToName = ToFriend->getDeclName();
2837
2838 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2839 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2840 LookupRes = ToClass->noload_lookup(ToName);
2841 EXPECT_EQ(LookupRes.size(), 0u);
2842 LookupRes = ToTU->noload_lookup(ToName);
2843 // Test is disabled because this result is 2.
2844 EXPECT_EQ(LookupRes.size(), 1u);
2845
2846 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2847 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2848 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2849 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2850 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2851 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2852 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2853}
2854
2855TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2856 auto FunctionPattern = functionDecl(hasName("f"));
2857 auto ClassPattern = cxxRecordDecl(hasName("X"));
2858
2859 TranslationUnitDecl *FromTU = getTuDecl(
2860 "void f();"
2861 "struct X { friend void f(); };",
2862 Lang_CXX, "input0.cc");
2863 auto *FromNormal =
2864 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2865 auto *FromFriend =
2866 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2867 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2868 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2869 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2870 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2871
2872 auto FromName = FromNormal->getDeclName();
2873 auto *FromClass =
2874 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2875 auto LookupRes = FromClass->noload_lookup(FromName);
2876 ASSERT_EQ(LookupRes.size(), 0u);
2877 LookupRes = FromTU->noload_lookup(FromName);
2878 ASSERT_EQ(LookupRes.size(), 1u);
2879
2880 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2881 auto ToName = ToNormal->getDeclName();
2882 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2883
2884 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2885 LookupRes = ToClass->noload_lookup(ToName);
2886 EXPECT_EQ(LookupRes.size(), 0u);
2887 LookupRes = ToTU->noload_lookup(ToName);
2888 EXPECT_EQ(LookupRes.size(), 1u);
2889
2890 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2891 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2892 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2893 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2894 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2895 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2896 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2897}
2898
2899TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2900 auto Pattern = functionDecl(hasName("f"));
2901
2902 TranslationUnitDecl *FromNormalTU =
2903 getTuDecl("void f();", Lang_CXX, "input0.cc");
2904 auto *FromNormalF =
2905 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2906 TranslationUnitDecl *FromFriendTU =
2907 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2908 auto *FromFriendF =
2909 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2910 auto FromNormalName = FromNormalF->getDeclName();
2911 auto FromFriendName = FromFriendF->getDeclName();
2912
2913 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2914 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2915 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2916 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2917 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2918 ASSERT_EQ(LookupRes.size(), 1u);
2919 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2920 ASSERT_EQ(LookupRes.size(), 1u);
2921
2922 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2923 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2924 auto ToName = ToNormalF->getDeclName();
2925 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2926 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2927 LookupRes = ToTU->noload_lookup(ToName);
2928 EXPECT_EQ(LookupRes.size(), 1u);
2929 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002930
Balazs Keri89632b82018-08-21 14:32:21 +00002931 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2932 LookupRes = ToTU->noload_lookup(ToName);
2933 EXPECT_EQ(LookupRes.size(), 1u);
2934 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2935
2936 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2937 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2938
2939 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2940 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2941}
2942
2943TEST_P(ImportFriendFunctions, ImportFriendList) {
2944 TranslationUnitDecl *FromTU = getTuDecl(
2945 "struct X { friend void f(); };"
2946 "void f();",
2947 Lang_CXX, "input0.cc");
2948 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2949 FromTU, functionDecl(hasName("f")));
2950
2951 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2952 FromTU, cxxRecordDecl(hasName("X")));
2953 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2954 auto FromFriends = FromClass->friends();
2955 unsigned int FrN = 0;
2956 for (auto Fr : FromFriends) {
2957 ASSERT_EQ(Fr, FromFriend);
2958 ++FrN;
2959 }
2960 ASSERT_EQ(FrN, 1u);
2961
2962 Import(FromFriendF, Lang_CXX);
2963 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2964 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2965 ToTU, cxxRecordDecl(hasName("X")));
2966 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2967 auto ToFriends = ToClass->friends();
2968 FrN = 0;
2969 for (auto Fr : ToFriends) {
2970 EXPECT_EQ(Fr, ToFriend);
2971 ++FrN;
2972 }
2973 EXPECT_EQ(FrN, 1u);
2974}
2975
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002976AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2977 InnerMatcher) {
2978 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2979 return InnerMatcher.matches(*Typedef, Finder, Builder);
2980 return false;
2981}
2982
Gabor Marton19f4f392018-06-25 13:04:37 +00002983TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002984 CodeFiles Samples{{"main.c",
2985 {"void foo();"
2986 "void moo();"
2987 "int main() { foo(); moo(); }",
2988 Lang_C}},
2989
2990 {"foo.c",
2991 {"typedef enum { THING_VALUE } thing_t;"
2992 "void conflict(thing_t type);"
2993 "void foo() { (void)THING_VALUE; }"
2994 "void conflict(thing_t type) {}",
2995 Lang_C}},
2996
2997 {"moo.c",
2998 {"typedef enum { THING_VALUE } thing_t;"
2999 "void conflict(thing_t type);"
3000 "void moo() { conflict(THING_VALUE); }",
3001 Lang_C}}};
3002
3003 auto VerificationMatcher =
3004 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
3005 hasTypedefForAnonDecl(hasName("thing_t")));
3006
3007 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
3008 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
3009
3010 testImportSequence(
3011 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
3012 // Just check that there is only one enum decl in the result AST.
3013 "main.c", enumDecl(), VerificationMatcher);
3014
3015 // For different import order, result should be the same.
3016 testImportSequence(
3017 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
3018 // Check that there is only one enum decl in the result AST.
3019 "main.c", enumDecl(), VerificationMatcher);
3020}
3021
Peter Szecsice7f3182018-05-07 12:08:27 +00003022const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
3023 dependentScopeDeclRefExpr;
3024
Gabor Marton19f4f392018-06-25 13:04:37 +00003025TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003026 MatchVerifier<Decl> Verifier;
3027 testImport("template <typename T> struct S { static T foo; };"
3028 "template <typename T> void declToImport() {"
3029 " (void) S<T>::foo;"
3030 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00003031 "void instantiate() { declToImport<int>(); }"
3032 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00003033 Lang_CXX11, "", Lang_CXX11, Verifier,
3034 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3035 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3036
3037 testImport("template <typename T> struct S {"
3038 "template<typename S> static void foo(){};"
3039 "};"
3040 "template <typename T> void declToImport() {"
3041 " S<T>::template foo<T>();"
3042 "}"
3043 "void instantiate() { declToImport<int>(); }",
3044 Lang_CXX11, "", Lang_CXX11, Verifier,
3045 functionTemplateDecl(has(functionDecl(has(compoundStmt(
3046 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3047}
3048
3049const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
3050 dependentNameType;
3051
Gabor Marton19f4f392018-06-25 13:04:37 +00003052TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003053 MatchVerifier<Decl> Verifier;
3054 testImport("template <typename T> struct declToImport {"
3055 " typedef typename T::type dependent_name;"
3056 "};",
3057 Lang_CXX11, "", Lang_CXX11, Verifier,
3058 classTemplateDecl(has(
3059 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3060}
3061
Gabor Marton19f4f392018-06-25 13:04:37 +00003062TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00003063 MatchVerifier<Decl> Verifier;
3064 testImport("struct S { template <typename T> void mem(); };"
3065 "template <typename U> void declToImport() {"
3066 " S s;"
3067 " s.mem<U>();"
3068 "}"
3069 "void instantiate() { declToImport<int>(); }",
3070 Lang_CXX11, "", Lang_CXX11, Verifier,
3071 functionTemplateDecl(has(functionDecl(has(
3072 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3073}
3074
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003075class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003076public:
3077 static constexpr auto DefaultCode = R"(
3078 struct A { int x; };
3079 void f() {
3080 A a;
3081 A a1(a);
3082 A a2(A{});
3083 a = a1;
3084 a = A{};
3085 a.~A();
3086 })";
3087
3088 template <typename MatcherType>
3089 void testImportOf(
3090 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3091 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3092 }
3093
3094 template <typename MatcherType>
3095 void testNoImportOf(
3096 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3097 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3098 }
3099
3100private:
3101 template <typename MatcherType>
3102 void test(const MatcherType &MethodMatcher,
3103 const char *Code, unsigned int ExpectedCount) {
3104 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3105
3106 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3107 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3108 ToTU, ClassMatcher);
3109
Balazs Keri2f752ba2018-07-16 14:05:18 +00003110 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003111
3112 {
3113 CXXMethodDecl *Method =
3114 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3115 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00003116 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003117 }
3118
Balazs Keri2f752ba2018-07-16 14:05:18 +00003119 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003120
3121 Decl *ImportedClass = nullptr;
3122 {
3123 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3124 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3125 FromTU, ClassMatcher);
3126 ImportedClass = Import(FromClass, Lang_CXX11);
3127 }
3128
3129 EXPECT_EQ(ToClass, ImportedClass);
3130 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3131 ExpectedCount);
3132 }
3133};
3134
3135TEST_P(ImportImplicitMethods, DefaultConstructor) {
3136 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3137}
3138
3139TEST_P(ImportImplicitMethods, CopyConstructor) {
3140 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3141}
3142
3143TEST_P(ImportImplicitMethods, MoveConstructor) {
3144 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3145}
3146
3147TEST_P(ImportImplicitMethods, Destructor) {
3148 testImportOf(cxxDestructorDecl());
3149}
3150
3151TEST_P(ImportImplicitMethods, CopyAssignment) {
3152 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3153}
3154
3155TEST_P(ImportImplicitMethods, MoveAssignment) {
3156 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3157}
3158
3159TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3160 auto Code = R"(
3161 struct A { A() { int x; } };
3162 )";
3163 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3164}
3165
3166TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3167 auto Code = R"(
3168 struct A { A() = default; };
3169 )";
3170 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3171}
3172
3173TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3174 auto Code = R"(
3175 struct A { A() = delete; };
3176 )";
3177 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3178}
3179
3180TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3181 auto Code = R"(
3182 struct A { void f() { } };
3183 )";
3184 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3185}
3186
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003187TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003188 Decl *ToR1;
3189 {
3190 Decl *FromTU = getTuDecl(
3191 "struct A { };", Lang_CXX, "input0.cc");
3192 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3193 FromTU, cxxRecordDecl(hasName("A")));
3194
3195 ToR1 = Import(FromR, Lang_CXX);
3196 }
3197
3198 Decl *ToR2;
3199 {
3200 Decl *FromTU = getTuDecl(
3201 "struct A { };", Lang_CXX, "input1.cc");
3202 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3203 FromTU, cxxRecordDecl(hasName("A")));
3204
3205 ToR2 = Import(FromR, Lang_CXX);
3206 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003207
Balazs Keric7797c42018-07-11 09:37:24 +00003208 EXPECT_EQ(ToR1, ToR2);
3209}
3210
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003211TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003212 Decl *ToR1;
3213 {
3214 Decl *FromTU = getTuDecl(
3215 "struct A { int x; };", Lang_CXX, "input0.cc");
3216 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3217 FromTU, cxxRecordDecl(hasName("A")));
3218 ToR1 = Import(FromR, Lang_CXX);
3219 }
3220 Decl *ToR2;
3221 {
3222 Decl *FromTU = getTuDecl(
3223 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3224 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3225 FromTU, cxxRecordDecl(hasName("A")));
3226 ToR2 = Import(FromR, Lang_CXX);
3227 }
3228 EXPECT_NE(ToR1, ToR2);
3229}
3230
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003231TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003232 Decl *ToF1;
3233 {
3234 Decl *FromTU = getTuDecl(
3235 "struct A { int x; };", Lang_CXX, "input0.cc");
3236 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3237 FromTU, fieldDecl(hasName("x")));
3238 ToF1 = Import(FromF, Lang_CXX);
3239 }
3240 Decl *ToF2;
3241 {
3242 Decl *FromTU = getTuDecl(
3243 "struct A { int x; };", Lang_CXX, "input1.cc");
3244 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3245 FromTU, fieldDecl(hasName("x")));
3246 ToF2 = Import(FromF, Lang_CXX);
3247 }
3248 EXPECT_EQ(ToF1, ToF2);
3249}
3250
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003251TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003252 Decl *ToF1;
3253 {
3254 Decl *FromTU = getTuDecl(
3255 "struct A { int x; };", Lang_CXX, "input0.cc");
3256 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3257 FromTU, fieldDecl(hasName("x")));
3258 ToF1 = Import(FromF, Lang_CXX);
3259 }
3260 Decl *ToF2;
3261 {
3262 Decl *FromTU = getTuDecl(
3263 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3264 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3265 FromTU, fieldDecl(hasName("x")));
3266 ToF2 = Import(FromF, Lang_CXX);
3267 }
3268 EXPECT_NE(ToF1, ToF2);
3269}
3270
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003271TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003272 Decl *ToM1;
3273 {
3274 Decl *FromTU = getTuDecl(
3275 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3276 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3277 FromTU, functionDecl(hasName("x"), isDefinition()));
3278 ToM1 = Import(FromM, Lang_CXX);
3279 }
3280 Decl *ToM2;
3281 {
3282 Decl *FromTU = getTuDecl(
3283 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3284 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3285 FromTU, functionDecl(hasName("x"), isDefinition()));
3286 ToM2 = Import(FromM, Lang_CXX);
3287 }
3288 EXPECT_EQ(ToM1, ToM2);
3289}
3290
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003291TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003292 Decl *ToM1;
3293 {
3294 Decl *FromTU = getTuDecl(
3295 "struct A { void x(); }; void A::x() { }",
3296 Lang_CXX, "input0.cc");
3297 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3298 FromTU, functionDecl(hasName("x"), isDefinition()));
3299 ToM1 = Import(FromM, Lang_CXX);
3300 }
3301 Decl *ToM2;
3302 {
3303 Decl *FromTU = getTuDecl(
3304 "struct A { void x() const; }; void A::x() const { }",
3305 Lang_CXX, "input1.cc");
3306 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3307 FromTU, functionDecl(hasName("x"), isDefinition()));
3308 ToM2 = Import(FromM, Lang_CXX);
3309 }
3310 EXPECT_NE(ToM1, ToM2);
3311}
3312
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003313TEST_P(ASTImporterOptionSpecificTestBase,
3314 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003315 Decl *FromTU = getTuDecl(
3316 R"(
3317 struct A {
3318 struct {
3319 struct A *next;
3320 } entry0;
3321 struct {
3322 struct A *next;
3323 } entry1;
3324 };
3325 )",
3326 Lang_C, "input0.cc");
3327 auto *From =
3328 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3329
3330 Import(From, Lang_C);
3331
3332 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3333 auto *Entry0 =
3334 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3335 auto *Entry1 =
3336 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3337 auto *R0 = getRecordDecl(Entry0);
3338 auto *R1 = getRecordDecl(Entry1);
3339 EXPECT_NE(R0, R1);
3340 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3341 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3342 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3343 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3344}
3345
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003346TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003347 Decl *FromTU = getTuDecl(
3348 R"(
3349 void f(int X, int Y, bool Z) {
3350 (void)[X, Y, Z] { (void)Z; };
3351 }
3352 )",
3353 Lang_CXX11, "input0.cc");
3354 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3355 FromTU, functionDecl(hasName("f")));
3356 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3357 EXPECT_TRUE(ToF);
3358
3359 CXXRecordDecl *FromLambda =
3360 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3361 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3362
3363 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3364 EXPECT_TRUE(ToLambda);
3365
3366 // Check if the fields of the lambda class are imported in correct order.
3367 unsigned FromIndex = 0u;
3368 for (auto *FromField : FromLambda->fields()) {
3369 ASSERT_FALSE(FromField->getDeclName());
3370 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3371 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003372 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3373 EXPECT_TRUE(ToIndex);
3374 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003375 ++FromIndex;
3376 }
3377
3378 EXPECT_EQ(FromIndex, 3u);
3379}
3380
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003381TEST_P(ASTImporterOptionSpecificTestBase,
3382 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003383 std::string ClassTemplate =
3384 R"(
3385 template <typename T>
3386 struct X {
3387 int a{0}; // FieldDecl with InitListExpr
3388 X(char) : a(3) {} // (1)
3389 X(int) {} // (2)
3390 };
3391 )";
3392 Decl *ToTU = getToTuDecl(ClassTemplate +
3393 R"(
3394 void foo() {
3395 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3396 X<char> xc('c');
3397 }
3398 )", Lang_CXX11);
3399 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3400 ToTU, classTemplateSpecializationDecl(hasName("X")));
3401 // FieldDecl without InitlistExpr:
3402 auto *ToField = *ToSpec->field_begin();
3403 ASSERT_TRUE(ToField);
3404 ASSERT_FALSE(ToField->getInClassInitializer());
3405 Decl *FromTU = getTuDecl(ClassTemplate +
3406 R"(
3407 void bar() {
3408 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3409 X<char> xc(1);
3410 }
3411 )", Lang_CXX11);
3412 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3413 FromTU, classTemplateSpecializationDecl(hasName("X")));
3414 // FieldDecl with InitlistExpr:
3415 auto *FromField = *FromSpec->field_begin();
3416 ASSERT_TRUE(FromField);
3417 ASSERT_TRUE(FromField->getInClassInitializer());
3418
3419 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3420 ASSERT_TRUE(ImportedSpec);
3421 EXPECT_EQ(ImportedSpec, ToSpec);
3422 // After the import, the FieldDecl has to be merged, thus it should have the
3423 // InitListExpr.
3424 EXPECT_TRUE(ToField->getInClassInitializer());
3425}
3426
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003427TEST_P(ASTImporterOptionSpecificTestBase,
3428 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003429 std::string ClassTemplate =
3430 R"(
3431 template <typename T>
3432 struct X {
3433 void f() {}
3434 void g() {}
3435 };
3436 )";
3437 Decl *ToTU = getToTuDecl(ClassTemplate +
3438 R"(
3439 void foo() {
3440 X<char> x;
3441 x.f();
3442 }
3443 )", Lang_CXX11);
3444 Decl *FromTU = getTuDecl(ClassTemplate +
3445 R"(
3446 void bar() {
3447 X<char> x;
3448 x.g();
3449 }
3450 )", Lang_CXX11);
3451 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3452 FromTU, classTemplateSpecializationDecl(hasName("X")));
3453 auto FunPattern = functionDecl(hasName("g"),
3454 hasParent(classTemplateSpecializationDecl()));
3455 auto *FromFun =
3456 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3457 auto *ToFun =
3458 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3459 ASSERT_TRUE(FromFun->hasBody());
3460 ASSERT_FALSE(ToFun->hasBody());
3461 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3462 ASSERT_TRUE(ImportedSpec);
3463 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3464 ToTU, classTemplateSpecializationDecl(hasName("X")));
3465 EXPECT_EQ(ImportedSpec, ToSpec);
3466 EXPECT_TRUE(ToFun->hasBody());
3467}
3468
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003469TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003470 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3471 std::string ClassTemplate =
3472 R"(
3473 template <typename T>
3474 struct X {};
3475 )";
3476 Decl *ToTU = getToTuDecl(ClassTemplate +
3477 R"(
3478 template <>
3479 struct X<char> {
3480 int a;
3481 };
3482 void foo() {
3483 X<char> x;
3484 }
3485 )",
3486 Lang_CXX11);
3487 Decl *FromTU = getTuDecl(ClassTemplate +
3488 R"(
3489 template <>
3490 struct X<char> {
3491 int b;
3492 };
3493 void foo() {
3494 X<char> x;
3495 }
3496 )",
3497 Lang_CXX11);
3498 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3499 FromTU, classTemplateSpecializationDecl(hasName("X")));
3500 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3501
3502 // We expect one (ODR) warning during the import.
3503 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3504
3505 // The second specialization is different from the first, thus it violates
3506 // ODR, consequently we expect to keep the first specialization only, which is
3507 // already in the "To" context.
3508 EXPECT_TRUE(ImportedSpec);
3509 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3510 ToTU, classTemplateSpecializationDecl(hasName("X")));
3511 EXPECT_EQ(ImportedSpec, ToSpec);
3512 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3513 ToTU, classTemplateSpecializationDecl()));
3514}
3515
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003516TEST_P(ASTImporterOptionSpecificTestBase,
3517 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003518 std::string ClassTemplate =
3519 R"(
3520 template <typename T>
3521 struct X {
3522 X(char) {}
3523 X(int) {}
3524 };
3525 )";
3526 Decl *ToTU = getToTuDecl(ClassTemplate +
3527 R"(
3528 void foo() {
3529 X<char> x('c');
3530 }
3531 )", Lang_CXX11);
3532 Decl *FromTU = getTuDecl(ClassTemplate +
3533 R"(
3534 void bar() {
3535 X<char> x(1);
3536 }
3537 )", Lang_CXX11);
3538 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3539 FromTU, classTemplateSpecializationDecl(hasName("X")));
3540 // Match the void(int) ctor.
3541 auto CtorPattern =
3542 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3543 hasParent(classTemplateSpecializationDecl()));
3544 auto *FromCtor =
3545 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3546 auto *ToCtor =
3547 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3548 ASSERT_TRUE(FromCtor->hasBody());
3549 ASSERT_FALSE(ToCtor->hasBody());
3550 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3551 ASSERT_TRUE(ImportedSpec);
3552 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3553 ToTU, classTemplateSpecializationDecl(hasName("X")));
3554 EXPECT_EQ(ImportedSpec, ToSpec);
3555 EXPECT_TRUE(ToCtor->hasBody());
3556}
3557
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003558TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003559 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3560 auto Code =
3561 R"(
3562 // primary template
3563 template<class T1, class T2, int I>
3564 class A {};
3565
3566 // partial specialization
3567 template<class T, int I>
3568 class A<T, T*, I> {};
3569 )";
3570 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3571 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3572 auto *FromSpec =
3573 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3574 FromTU, classTemplatePartialSpecializationDecl());
3575 auto *ToSpec =
3576 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3577 ToTU, classTemplatePartialSpecializationDecl());
3578
3579 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3580 EXPECT_EQ(ImportedSpec, ToSpec);
3581 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3582 ToTU, classTemplatePartialSpecializationDecl()));
3583}
3584
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003585TEST_P(ASTImporterOptionSpecificTestBase,
3586 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003587 auto Code =
3588 R"(
3589 // primary template
3590 template<class T1, class T2, int I>
3591 class A {};
3592
3593 // full specialization
3594 template<>
3595 class A<int, int, 1> {};
3596 )";
3597 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3598 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3599 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3600 FromTU, classTemplateSpecializationDecl());
3601 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3602 ToTU, classTemplateSpecializationDecl());
3603
3604 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3605 EXPECT_EQ(ImportedSpec, ToSpec);
3606 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3607 ToTU, classTemplateSpecializationDecl()));
3608}
3609
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003610TEST_P(ASTImporterOptionSpecificTestBase,
3611 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003612 std::string PrimaryTemplate =
3613 R"(
3614 template<class T1, class T2, int I>
3615 class A {};
3616 )";
3617 auto PartialSpec =
3618 R"(
3619 template<class T, int I>
3620 class A<T, T*, I> {};
3621 )";
3622 auto FullSpec =
3623 R"(
3624 template<>
3625 class A<int, int, 1> {};
3626 )";
3627 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3628 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3629 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3630 FromTU, classTemplateSpecializationDecl());
3631
3632 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3633 EXPECT_TRUE(ImportedSpec);
3634 // Check the number of partial specializations.
3635 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3636 ToTU, classTemplatePartialSpecializationDecl()));
3637 // Check the number of full specializations.
3638 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3639 ToTU, classTemplateSpecializationDecl(
3640 unless(classTemplatePartialSpecializationDecl()))));
3641}
3642
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003643TEST_P(ASTImporterOptionSpecificTestBase,
3644 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003645 Decl *TU = getTuDecl(
3646 R"(
3647 const int &init();
3648 void foo() { const int &a{init()}; }
3649 )", Lang_CXX11, "input0.cc");
3650 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3651 ASSERT_TRUE(FromD->getAnyInitializer());
3652 auto *InitExpr = FromD->getAnyInitializer();
3653 ASSERT_TRUE(InitExpr);
3654 ASSERT_TRUE(InitExpr->isGLValue());
3655
3656 auto *ToD = Import(FromD, Lang_CXX11);
3657 EXPECT_TRUE(ToD);
3658 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3659 EXPECT_TRUE(ToInitExpr);
3660 EXPECT_TRUE(ToInitExpr->isGLValue());
3661}
3662
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003663struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003664
3665TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3666 Decl *FromTU = getTuDecl(
3667 R"(
3668 struct A {
3669 static const int a = 1 + 2;
3670 };
3671 const int A::a;
3672 )", Lang_CXX, "input1.cc");
3673
3674 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3675 FromTU, varDecl(hasName("a"))); // Decl with init
3676 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3677 FromTU, varDecl(hasName("a"))); // Decl with definition
3678 ASSERT_NE(FromDWithInit, FromDWithDef);
3679 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3680
3681 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3682 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3683 ASSERT_TRUE(ToD0);
3684 ASSERT_TRUE(ToD1);
3685 EXPECT_NE(ToD0, ToD1);
3686 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3687}
3688
3689TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3690 auto StructA =
3691 R"(
3692 struct A {
3693 static const int a = 1 + 2;
3694 };
3695 )";
3696 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3697 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3698 "input1.cc");
3699
3700 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3701 FromTU, varDecl(hasName("a"))); // Decl with init
3702 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3703 FromTU, varDecl(hasName("a"))); // Decl with definition
3704 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3705 ASSERT_TRUE(FromDWithInit->getInit());
3706 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3707 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3708 ASSERT_FALSE(FromDWithDef->getInit());
3709
3710 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3711 ToTU, varDecl(hasName("a"))); // Decl with init
3712 ASSERT_TRUE(ToD->getInit());
3713 ASSERT_FALSE(ToD->getDefinition());
3714
3715 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3716 EXPECT_TRUE(ImportedD->getAnyInitializer());
3717 EXPECT_TRUE(ImportedD->getDefinition());
3718}
3719
3720TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3721 auto StructA =
3722 R"(
3723 struct A {
3724 static const int a;
3725 };
3726 )";
3727 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3728 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3729 Lang_CXX, "input1.cc");
3730
3731 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3732 FromTU, varDecl(hasName("a")));
3733 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3734 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3735 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3736 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3737 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3738 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3739 ASSERT_TRUE(FromDWithDef->getInit());
3740
3741 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3742 ToTU, varDecl(hasName("a")));
3743 ASSERT_FALSE(ToD->getInit());
3744 ASSERT_FALSE(ToD->getDefinition());
3745
3746 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3747 EXPECT_TRUE(ImportedD->getAnyInitializer());
3748 EXPECT_TRUE(ImportedD->getDefinition());
3749}
3750
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003751struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003752
Gabor Marton54058b52018-12-17 13:53:12 +00003753TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3754 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3755 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3756 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3757 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3758 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3759
3760 Decl *ImportedDef = Import(FromDef, Lang_C);
3761
3762 EXPECT_NE(ImportedDef, ToProto);
3763 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3764 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3765 EXPECT_TRUE(ImportedDef == ToDef);
3766 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3767 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3768 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3769}
3770
3771TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3772 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3773 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3774 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3775 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3776 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3777
3778 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3779
3780 EXPECT_NE(ImportedDef, ToProto);
3781 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3782 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3783 EXPECT_TRUE(ImportedDef == ToDef);
3784 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3785 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3786 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3787}
3788
3789TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3790 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3791 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3792 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3793 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3794 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3795
3796 Decl *ImportedProto = Import(FromProto, Lang_C);
3797 Decl *ImportedDef = Import(FromDef, Lang_C);
3798 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3799
3800 EXPECT_NE(ImportedDef, ImportedProto);
3801 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3802 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3803 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3804 EXPECT_TRUE(ImportedDef == ToDef);
3805 EXPECT_TRUE(ImportedProto == ToProto);
3806 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3807 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3808 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3809}
3810
Gabor Martonfc03fc62019-02-18 11:09:56 +00003811// FIXME put these structs and the tests rely on them into their own separate
3812// test file!
3813struct Function {
3814 using DeclTy = FunctionDecl;
3815 static constexpr auto *Prototype = "void X();";
3816 static constexpr auto *Definition = "void X() {}";
3817 BindableMatcher<Decl> getPattern() {
3818 return functionDecl(hasName("X"), unless(isImplicit()));
3819 }
3820};
Gabor Marton7df342a2018-12-17 12:42:12 +00003821
Gabor Martonfc03fc62019-02-18 11:09:56 +00003822struct Class {
3823 using DeclTy = CXXRecordDecl;
3824 static constexpr auto *Prototype = "class X;";
3825 static constexpr auto *Definition = "class X {};";
3826 BindableMatcher<Decl> getPattern() {
3827 return cxxRecordDecl(hasName("X"), unless(isImplicit()));
3828 }
3829};
Gabor Marton7df342a2018-12-17 12:42:12 +00003830
Gabor Martonfc03fc62019-02-18 11:09:56 +00003831struct Variable {
3832 using DeclTy = VarDecl;
3833 static constexpr auto *Prototype = "extern int X;";
3834 static constexpr auto *Definition = "int X;";
3835 BindableMatcher<Decl> getPattern() {
3836 return varDecl(hasName("X"));
3837 }
3838};
Gabor Marton7df342a2018-12-17 12:42:12 +00003839
Gabor Martonfc03fc62019-02-18 11:09:56 +00003840struct FunctionTemplate {
3841 using DeclTy = FunctionTemplateDecl;
3842 static constexpr auto *Prototype = "template <class T> void X();";
3843 static constexpr auto *Definition =
3844 R"(
3845 template <class T> void X() {};
3846 // Explicit instantiation is a must because of -fdelayed-template-parsing:
3847 template void X<int>();
3848 )";
3849 BindableMatcher<Decl> getPattern() {
3850 return functionTemplateDecl(hasName("X"), unless(isImplicit()));
3851 }
3852};
Gabor Marton7df342a2018-12-17 12:42:12 +00003853
Gabor Martonfc03fc62019-02-18 11:09:56 +00003854struct ClassTemplate {
3855 using DeclTy = ClassTemplateDecl;
3856 static constexpr auto *Prototype = "template <class T> class X;";
3857 static constexpr auto *Definition = "template <class T> class X {};";
3858 BindableMatcher<Decl> getPattern() {
3859 return classTemplateDecl(hasName("X"), unless(isImplicit()));
3860 }
3861};
Gabor Marton7df342a2018-12-17 12:42:12 +00003862
Gabor Martonfc03fc62019-02-18 11:09:56 +00003863struct FunctionTemplateSpec {
3864 using DeclTy = FunctionDecl;
3865 static constexpr auto *Prototype =
3866 R"(
3867 // Proto of the primary template.
3868 template <class T>
3869 void X();
3870 // Proto of the specialization.
3871 template <>
3872 void X<int>();
3873 )";
3874 static constexpr auto *Definition =
3875 R"(
3876 // Proto of the primary template.
3877 template <class T>
3878 void X();
3879 // Specialization and definition.
3880 template <>
3881 void X<int>() {}
3882 )";
3883 BindableMatcher<Decl> getPattern() {
3884 return functionDecl(hasName("X"), isExplicitTemplateSpecialization());
3885 }
3886};
Gabor Marton7df342a2018-12-17 12:42:12 +00003887
Gabor Martonfc03fc62019-02-18 11:09:56 +00003888template <typename TypeParam>
3889struct RedeclChain : ASTImporterOptionSpecificTestBase {
Gabor Marton7df342a2018-12-17 12:42:12 +00003890
Gabor Martonfc03fc62019-02-18 11:09:56 +00003891 using DeclTy = typename TypeParam::DeclTy;
3892 std::string getPrototype() { return TypeParam::Prototype; }
3893 std::string getDefinition() { return TypeParam::Definition; }
3894 BindableMatcher<Decl> getPattern() const { return TypeParam().getPattern(); }
Gabor Marton7df342a2018-12-17 12:42:12 +00003895
Gabor Martonfc03fc62019-02-18 11:09:56 +00003896 void
3897 TypedTest_PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition() {
3898 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX);
3899 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3900 ASSERT_FALSE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003901
Gabor Martonfc03fc62019-02-18 11:09:56 +00003902 Decl *ImportedD = Import(FromD, Lang_CXX);
3903 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003904
Gabor Martonfc03fc62019-02-18 11:09:56 +00003905 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3906 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3907 EXPECT_TRUE(ImportedD == ToD);
3908 EXPECT_FALSE(ToD->isThisDeclarationADefinition());
3909 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3910 EXPECT_TRUE(ToT->getTemplatedDecl());
3911 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003912
Gabor Martonfc03fc62019-02-18 11:09:56 +00003913 void TypedTest_DefinitionShouldBeImportedAsADefinition() {
3914 Decl *FromTU = getTuDecl(getDefinition(), Lang_CXX);
3915 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3916 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003917
Gabor Martonfc03fc62019-02-18 11:09:56 +00003918 Decl *ImportedD = Import(FromD, Lang_CXX);
3919 Decl *ToTU = ImportedD->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003920
Gabor Martonfc03fc62019-02-18 11:09:56 +00003921 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
3922 auto *ToD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3923 EXPECT_TRUE(ToD->isThisDeclarationADefinition());
3924 if (auto *ToT = dyn_cast<TemplateDecl>(ToD))
3925 EXPECT_TRUE(ToT->getTemplatedDecl());
3926 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003927
Gabor Martonfc03fc62019-02-18 11:09:56 +00003928 void TypedTest_ImportPrototypeAfterImportedPrototype() {
3929 Decl *FromTU = getTuDecl(
3930 getPrototype() + getPrototype(), Lang_CXX);
3931 auto *From0 =
3932 FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3933 auto *From1 = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3934 ASSERT_FALSE(From0->isThisDeclarationADefinition());
3935 ASSERT_FALSE(From1->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003936
Gabor Martonfc03fc62019-02-18 11:09:56 +00003937 Decl *Imported0 = Import(From0, Lang_CXX);
3938 Decl *Imported1 = Import(From1, Lang_CXX);
3939 Decl *ToTU = Imported0->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003940
Gabor Martonfc03fc62019-02-18 11:09:56 +00003941 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3942 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3943 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3944 EXPECT_TRUE(Imported0 == To0);
3945 EXPECT_TRUE(Imported1 == To1);
3946 EXPECT_FALSE(To0->isThisDeclarationADefinition());
3947 EXPECT_FALSE(To1->isThisDeclarationADefinition());
3948 EXPECT_EQ(To1->getPreviousDecl(), To0);
3949 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
3950 auto *ToT1 = cast<TemplateDecl>(To1);
3951 ASSERT_TRUE(ToT0->getTemplatedDecl());
3952 ASSERT_TRUE(ToT1->getTemplatedDecl());
3953 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
3954 ToT0->getTemplatedDecl());
3955 }
3956 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003957
Gabor Martonfc03fc62019-02-18 11:09:56 +00003958 void TypedTest_ImportDefinitionAfterImportedPrototype() {
3959 Decl *FromTU = getTuDecl(
3960 getPrototype() + getDefinition(), Lang_CXX);
3961 auto *FromProto = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3962 auto *FromDef = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3963 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
3964 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003965
Gabor Martonfc03fc62019-02-18 11:09:56 +00003966 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3967 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3968 Decl *ToTU = ImportedProto->getTranslationUnitDecl();
Gabor Marton7df342a2018-12-17 12:42:12 +00003969
Gabor Martonfc03fc62019-02-18 11:09:56 +00003970 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
3971 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
3972 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
3973 EXPECT_TRUE(ImportedProto == ToProto);
3974 EXPECT_TRUE(ImportedDef == ToDef);
3975 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3976 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3977 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3978 if (auto *ToProtoT = dyn_cast<TemplateDecl>(ToProto)) {
3979 auto *ToDefT = cast<TemplateDecl>(ToDef);
3980 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
3981 ASSERT_TRUE(ToDefT->getTemplatedDecl());
3982 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
3983 ToProtoT->getTemplatedDecl());
3984 }
3985 }
Gabor Marton7df342a2018-12-17 12:42:12 +00003986
Gabor Martonfc03fc62019-02-18 11:09:56 +00003987 void TypedTest_ImportPrototypeAfterImportedDefinition() {
3988 Decl *FromTU = getTuDecl(
3989 getDefinition() + getPrototype(), Lang_CXX);
3990 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
3991 auto *FromProto = LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
3992 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
3993 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
Gabor Marton7df342a2018-12-17 12:42:12 +00003994
Gabor Martonfc03fc62019-02-18 11:09:56 +00003995 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3996 Decl *ImportedProto = Import(FromProto, Lang_CXX);
3997 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3998
3999 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4000 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4001 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4002 EXPECT_TRUE(ImportedDef == ToDef);
4003 EXPECT_TRUE(ImportedProto == ToProto);
4004 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4005 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4006 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
4007 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4008 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4009 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4010 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4011 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
4012 ToDefT->getTemplatedDecl());
4013 }
4014 }
4015
4016 void TypedTest_ImportPrototypes() {
4017 Decl *FromTU0 = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4018 Decl *FromTU1 = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4019 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4020 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4021 ASSERT_FALSE(From0->isThisDeclarationADefinition());
4022 ASSERT_FALSE(From1->isThisDeclarationADefinition());
4023
4024 Decl *Imported0 = Import(From0, Lang_CXX);
4025 Decl *Imported1 = Import(From1, Lang_CXX);
4026 Decl *ToTU = Imported0->getTranslationUnitDecl();
4027
4028 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4029 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4030 auto *To1 = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4031 EXPECT_TRUE(Imported0 == To0);
4032 EXPECT_TRUE(Imported1 == To1);
4033 EXPECT_FALSE(To0->isThisDeclarationADefinition());
4034 EXPECT_FALSE(To1->isThisDeclarationADefinition());
4035 EXPECT_EQ(To1->getPreviousDecl(), To0);
4036 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0)) {
4037 auto *ToT1 = cast<TemplateDecl>(To1);
4038 ASSERT_TRUE(ToT0->getTemplatedDecl());
4039 ASSERT_TRUE(ToT1->getTemplatedDecl());
4040 EXPECT_EQ(ToT1->getTemplatedDecl()->getPreviousDecl(),
4041 ToT0->getTemplatedDecl());
4042 }
4043 // Extra check for specializations.
4044 // FIXME Add this check to other tests too (possibly factor out into a
4045 // function), when they start to pass.
4046 if (auto *From0F = dyn_cast<FunctionDecl>(From0)) {
4047 auto *To0F = cast<FunctionDecl>(To0);
4048 if (From0F->getTemplatedKind() ==
4049 FunctionDecl::TK_FunctionTemplateSpecialization) {
4050 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4051 ToTU, functionTemplateDecl());
4052 auto *FirstSpecD = *(TemplateD->spec_begin());
4053 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0F->getCanonicalDecl());
4054 }
4055 }
4056 }
4057
4058 void TypedTest_ImportDefinitions() {
4059 Decl *FromTU0 = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4060 Decl *FromTU1 = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4061 auto *From0 = FirstDeclMatcher<DeclTy>().match(FromTU0, getPattern());
4062 auto *From1 = FirstDeclMatcher<DeclTy>().match(FromTU1, getPattern());
4063 ASSERT_TRUE(From0->isThisDeclarationADefinition());
4064 ASSERT_TRUE(From1->isThisDeclarationADefinition());
4065
4066 Decl *Imported0 = Import(From0, Lang_CXX);
4067 Decl *Imported1 = Import(From1, Lang_CXX);
4068 Decl *ToTU = Imported0->getTranslationUnitDecl();
4069
4070 EXPECT_EQ(Imported0, Imported1);
4071 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
4072 auto *To0 = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4073 EXPECT_TRUE(Imported0 == To0);
4074 EXPECT_TRUE(To0->isThisDeclarationADefinition());
4075 if (auto *ToT0 = dyn_cast<TemplateDecl>(To0))
4076 EXPECT_TRUE(ToT0->getTemplatedDecl());
4077 }
4078
4079 void TypedTest_ImportDefinitionThenPrototype() {
4080 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input0.cc");
4081 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input1.cc");
4082 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4083 auto *FromProto =
4084 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4085 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4086 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4087
4088 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4089 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4090 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4091
4092 EXPECT_NE(ImportedDef, ImportedProto);
4093 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4094 auto *ToDef = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4095 auto *ToProto = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4096 EXPECT_TRUE(ImportedDef == ToDef);
4097 EXPECT_TRUE(ImportedProto == ToProto);
4098 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4099 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4100 EXPECT_EQ(ToProto->getPreviousDecl(), ToDef);
4101 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4102 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4103 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4104 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4105 EXPECT_EQ(ToProtoT->getTemplatedDecl()->getPreviousDecl(),
4106 ToDefT->getTemplatedDecl());
4107 }
4108 }
4109
4110 void TypedTest_ImportPrototypeThenDefinition() {
4111 Decl *FromTUProto = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4112 Decl *FromTUDef = getTuDecl(getDefinition(), Lang_CXX, "input1.cc");
4113 auto *FromProto =
4114 FirstDeclMatcher<DeclTy>().match(FromTUProto, getPattern());
4115 auto *FromDef = FirstDeclMatcher<DeclTy>().match(FromTUDef, getPattern());
4116 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4117 ASSERT_FALSE(FromProto->isThisDeclarationADefinition());
4118
4119 Decl *ImportedProto = Import(FromProto, Lang_CXX);
4120 Decl *ImportedDef = Import(FromDef, Lang_CXX);
4121 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4122
4123 EXPECT_NE(ImportedDef, ImportedProto);
4124 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4125 auto *ToProto = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4126 auto *ToDef = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4127 EXPECT_TRUE(ImportedDef == ToDef);
4128 EXPECT_TRUE(ImportedProto == ToProto);
4129 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4130 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4131 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4132 if (auto *ToDefT = dyn_cast<TemplateDecl>(ToDef)) {
4133 auto *ToProtoT = cast<TemplateDecl>(ToProto);
4134 ASSERT_TRUE(ToDefT->getTemplatedDecl());
4135 ASSERT_TRUE(ToProtoT->getTemplatedDecl());
4136 EXPECT_EQ(ToDefT->getTemplatedDecl()->getPreviousDecl(),
4137 ToProtoT->getTemplatedDecl());
4138 }
4139 }
4140
4141 void TypedTest_WholeRedeclChainIsImportedAtOnce() {
4142 Decl *FromTU = getTuDecl(getPrototype() + getDefinition(), Lang_CXX);
4143 auto *FromD = // Definition
4144 LastDeclMatcher<DeclTy>().match(FromTU, getPattern());
4145 ASSERT_TRUE(FromD->isThisDeclarationADefinition());
4146
4147 Decl *ImportedD = Import(FromD, Lang_CXX);
4148 Decl *ToTU = ImportedD->getTranslationUnitDecl();
4149
4150 // The whole redecl chain is imported at once.
4151 EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
4152 EXPECT_TRUE(cast<DeclTy>(ImportedD)->isThisDeclarationADefinition());
4153 }
4154
4155 void TypedTest_ImportPrototypeThenProtoAndDefinition() {
4156 {
4157 Decl *FromTU = getTuDecl(getPrototype(), Lang_CXX, "input0.cc");
4158 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4159 Import(FromD, Lang_CXX);
4160 }
4161 {
4162 Decl *FromTU =
4163 getTuDecl(getPrototype() + getDefinition(), Lang_CXX, "input1.cc");
4164 auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
4165 Import(FromD, Lang_CXX);
4166 }
4167
4168 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4169
4170 ASSERT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 3u);
4171 DeclTy *ProtoD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
4172 EXPECT_FALSE(ProtoD->isThisDeclarationADefinition());
4173
4174 DeclTy *DefinitionD = LastDeclMatcher<DeclTy>().match(ToTU, getPattern());
4175 EXPECT_TRUE(DefinitionD->isThisDeclarationADefinition());
4176
4177 EXPECT_TRUE(DefinitionD->getPreviousDecl());
4178 EXPECT_FALSE(
4179 DefinitionD->getPreviousDecl()->isThisDeclarationADefinition());
4180 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
4181 }
4182};
4183
4184#define ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(BaseTemplate, TypeParam, \
4185 NamePrefix, TestCase) \
4186 using BaseTemplate##TypeParam = BaseTemplate<TypeParam>; \
4187 TEST_P(BaseTemplate##TypeParam, NamePrefix##TestCase) { \
4188 TypedTest_##TestCase(); \
4189 }
4190
4191ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4192 RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004193 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004194ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4195 RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004196 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004197ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4198 RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004199 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004200// FIXME Enable this test, once we import function templates chains correctly.
4201ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4202 RedeclChain, FunctionTemplate, DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004203 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004204ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4205 RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004206 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004207ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4208 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004209 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004210
4211ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004212 RedeclChain, Function, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004213ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004214 RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004215ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004216 RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004217// FIXME Enable this test, once we import function templates chains correctly.
4218ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4219 RedeclChain, FunctionTemplate, DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004220 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004221ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
Gabor Marton038100a2019-02-20 16:57:41 +00004222 RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004223ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(
4224 RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004225 DefinitionShouldBeImportedAsADefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004226
4227ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004228 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004229ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004230 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004231ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004232 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004233// FIXME Enable this test, once we import function templates chains correctly.
4234ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4235 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004236 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004237ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004238 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004239ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004240 ImportPrototypeAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004241
4242ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004243 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004244ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004245 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004246ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004247 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004248// FIXME Enable this test, once we import function templates chains correctly.
4249ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4250 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004251 ImportDefinitionAfterImportedPrototype)
Gabor Marton41e38922019-03-05 11:23:24 +00004252ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004253 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004254ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004255 ImportDefinitionAfterImportedPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004256
4257ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004258 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004259ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004260 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004261ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004262 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004263// FIXME Enable this test, once we import function templates chains correctly.
4264ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4265 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004266 ImportPrototypeAfterImportedDefinition)
Gabor Marton41e38922019-03-05 11:23:24 +00004267ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004268 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004269ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004270 ImportPrototypeAfterImportedDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004271
4272ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004273 ImportPrototypes)
Gabor Marton038100a2019-02-20 16:57:41 +00004274ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004275ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton2ac9ee32019-02-20 19:07:36 +00004276 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004277// FIXME Enable this test, once we import function templates chains correctly.
4278ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
Gabor Marton038100a2019-02-20 16:57:41 +00004279 DISABLED_, ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004280ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004281 ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004282// FIXME This does not pass, possible error with Spec import.
4283ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
Gabor Marton038100a2019-02-20 16:57:41 +00004284 DISABLED_, ImportPrototypes)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004285
4286ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004287 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004288ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004289 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004290ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004291 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004292// FIXME Enable this test, once we import function templates chains correctly.
4293ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
Gabor Marton038100a2019-02-20 16:57:41 +00004294 DISABLED_, ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004295ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004296 ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004297// FIXME This does not pass, possible error with Spec import.
4298ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
Gabor Marton038100a2019-02-20 16:57:41 +00004299 DISABLED_, ImportDefinitions)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004300
4301ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004302 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004303ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004304 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004305ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004306 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004307// FIXME Enable this test, once we import function templates chains correctly.
4308ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4309 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004310 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004311ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004312 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004313// FIXME This does not pass, possible error with Spec import.
4314ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4315 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004316 ImportDefinitionThenPrototype)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004317
4318ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004319 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004320ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004321 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004322ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004323 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004324// FIXME Enable this test, once we import function templates chains correctly.
4325ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4326 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004327 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004328ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004329 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004330// FIXME This does not pass, possible error with Spec import.
4331ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4332 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004333 ImportPrototypeThenDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004334
4335ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004336 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004337ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004338 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004339// FIXME Enable this test, once we import function templates chains correctly.
4340ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4341 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004342 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004343ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004344 WholeRedeclChainIsImportedAtOnce)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004345
4346ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Function, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004347 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004348ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, ,
Gabor Marton038100a2019-02-20 16:57:41 +00004349 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004350// FIXME Enable this test, once we import function templates chains correctly.
4351ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate,
4352 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004353 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004354// FIXME This does not pass, possible error with Spec import.
4355ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec,
4356 DISABLED_,
Gabor Marton038100a2019-02-20 16:57:41 +00004357 ImportPrototypeThenProtoAndDefinition)
Gabor Martonfc03fc62019-02-18 11:09:56 +00004358
4359INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunction,
4360 DefaultTestValuesForRunOptions, );
4361INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClass,
4362 DefaultTestValuesForRunOptions, );
4363INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainVariable,
4364 DefaultTestValuesForRunOptions, );
4365INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplate,
4366 DefaultTestValuesForRunOptions, );
4367INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainClassTemplate,
4368 DefaultTestValuesForRunOptions, );
4369INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedeclChainFunctionTemplateSpec,
4370 DefaultTestValuesForRunOptions, );
4371
4372
Gabor Marton7df342a2018-12-17 12:42:12 +00004373
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004374struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00004375
4376TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4377 Decl *FromTU = getTuDecl(
4378 R"(
4379 class A {
4380 template <int I> class F {};
4381 class X {
4382 template <int I> friend class F;
4383 };
4384 };
4385 )",
4386 Lang_CXX, "input0.cc");
4387
4388 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4389 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4390 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4391 FromTU, cxxRecordDecl(hasName("F")));
4392
4393 ASSERT_TRUE(FromClass);
4394 ASSERT_TRUE(FromFriendClass);
4395 ASSERT_NE(FromClass, FromFriendClass);
4396 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4397 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4398 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4399 FromClass->getDescribedClassTemplate());
4400
4401 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
4402 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
4403
4404 EXPECT_TRUE(ToClass);
4405 EXPECT_TRUE(ToFriendClass);
4406 EXPECT_NE(ToClass, ToFriendClass);
4407 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4408 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4409 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4410 ToClass->getDescribedClassTemplate());
4411}
4412
4413TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4414 Decl *FromTu = getTuDecl(
4415 R"(
4416 class declToImport {
4417 friend class declToImport;
4418 };
4419 )",
4420 Lang_CXX, "input.cc");
4421
4422 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4423 FromTu, cxxRecordDecl(hasName("declToImport")));
4424 auto *ToD = Import(FromD, Lang_CXX);
4425 auto Pattern = cxxRecordDecl(has(friendDecl()));
4426 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4427 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4428}
4429
4430TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4431 Decl *FromTu = getTuDecl(
4432 R"(
4433 template<class A> class declToImport {
4434 template<class A1> friend class declToImport;
4435 };
4436 )",
4437 Lang_CXX, "input.cc");
4438
4439 auto *FromD =
4440 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
4441 auto *ToD = Import(FromD, Lang_CXX);
4442
4443 auto Pattern = classTemplateDecl(
4444 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4445 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4446 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4447
4448 auto *Class =
4449 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
4450 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4451 EXPECT_NE(Friend->getFriendDecl(), Class);
4452 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
4453}
4454
4455TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4456 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
4457
4458 ClassTemplateSpecializationDecl *Imported1;
4459 {
4460 Decl *FromTU = getTuDecl("template<class T> class X;"
4461 "struct Y { friend class X<int>; };",
4462 Lang_CXX, "input0.cc");
4463 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4464 FromTU, Pattern);
4465
4466 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4467 }
4468 ClassTemplateSpecializationDecl *Imported2;
4469 {
4470 Decl *FromTU = getTuDecl("template<class T> class X;"
4471 "template<> class X<int>{};"
4472 "struct Z { friend class X<int>; };",
4473 Lang_CXX, "input1.cc");
4474 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4475 FromTU, Pattern);
4476
4477 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
4478 }
4479
4480 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4481 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4482 2u);
4483 ASSERT_TRUE(Imported2->getPreviousDecl());
4484 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4485}
4486
4487TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4488 Decl *FromTU0 = getTuDecl(
4489 R"(
4490 class X {
4491 class Y;
4492 };
4493 class X::Y {
4494 template <typename T>
4495 friend class F; // The decl context of F is the global namespace.
4496 };
4497 )",
4498 Lang_CXX, "input0.cc");
4499 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4500 FromTU0, classTemplateDecl(hasName("F")));
4501 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4502 Decl *FromTU1 = getTuDecl(
4503 R"(
4504 template <typename T>
4505 class F {};
4506 )",
4507 Lang_CXX, "input1.cc");
4508 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4509 FromTU1, classTemplateDecl(hasName("F")));
4510 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4511 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4512 Imported1->getTemplatedDecl()->getTypeForDecl());
4513}
4514
4515TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4516 Decl *From, *To;
4517 std::tie(From, To) =
4518 getImportedDecl("class declToImport {};", Lang_CXX,
4519 "class Y { friend class declToImport; };", Lang_CXX);
4520 auto *Imported = cast<CXXRecordDecl>(To);
4521
4522 EXPECT_TRUE(Imported->getPreviousDecl());
4523}
4524
4525TEST_P(ImportFriendClasses,
4526 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4527 Decl *ToTU = getToTuDecl(
4528 R"(
4529 class X {
4530 class Y;
4531 };
4532 class X::Y {
4533 template <typename T>
4534 friend class F; // The decl context of F is the global namespace.
4535 };
4536 )",
4537 Lang_CXX);
4538 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4539 ToTU, classTemplateDecl(hasName("F")));
4540 Decl *FromTU = getTuDecl(
4541 R"(
4542 template <typename T>
4543 class F {};
4544 )",
4545 Lang_CXX, "input0.cc");
4546 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4547 FromTU, classTemplateDecl(hasName("F")));
4548 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4549 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4550 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4551 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4552 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4553}
4554
4555TEST_P(ImportFriendClasses,
4556 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4557 Decl *FromTU0 = getTuDecl(
4558 R"(
4559 class X {
4560 class Y;
4561 };
4562 class X::Y {
4563 template <typename T>
4564 friend class F; // The decl context of F is the global namespace.
4565 };
4566 )",
4567 Lang_CXX, "input0.cc");
4568 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4569 FromTU0, classTemplateDecl(hasName("F")));
4570 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
4571 Decl *FromTU1 = getTuDecl(
4572 R"(
4573 template <typename T>
4574 class F {};
4575 )",
4576 Lang_CXX, "input1.cc");
4577 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4578 FromTU1, classTemplateDecl(hasName("F")));
4579 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
4580 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4581 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4582 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4583 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4584}
4585
4586TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4587 Decl *FromTU0 = getTuDecl(
4588 R"(
4589 class X {
4590 class Y;
4591 };
4592 class X::Y {
4593 friend class F; // The decl context of F is the global namespace.
4594 };
4595 )",
4596 Lang_CXX, "input0.cc");
4597 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4598 QualType FT = Friend->getFriendType()->getType();
4599 FT = FromTU0->getASTContext().getCanonicalType(FT);
4600 auto *Fwd = cast<TagType>(FT)->getDecl();
4601 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4602 Decl *FromTU1 = getTuDecl(
4603 R"(
4604 class F {};
4605 )",
4606 Lang_CXX, "input1.cc");
4607 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4608 FromTU1, cxxRecordDecl(hasName("F")));
4609 auto *ImportedDef = Import(Definition, Lang_CXX);
4610 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4611 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4612}
4613
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004614TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004615 auto *Code = R"(
4616 template <class T>
4617 struct X {
4618 friend void foo(){}
4619 };
4620 )";
4621 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4622 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4623 ToTU, functionDecl(hasName("foo")));
4624
4625 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4626 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4627 FromTU, functionDecl(hasName("foo")));
4628 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4629 EXPECT_EQ(ImportedFoo, ToFoo);
4630}
4631
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004632struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004633
4634TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4635 Decl *TU = getTuDecl(
4636 R"(
4637 namespace NS {
4638
4639 template <typename T>
4640 struct S {};
4641 template struct S<int>;
4642
4643 inline namespace INS {
4644 template <typename T>
4645 struct S {};
4646 template struct S<int>;
4647 }
4648
4649 }
4650 )", Lang_CXX11, "input0.cc");
4651 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4652 TU, namespaceDecl());
4653 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4654 TU, classTemplateSpecializationDecl());
4655 ASSERT_TRUE(NS->containsDecl(Spec));
4656
4657 NS->removeDecl(Spec);
4658 EXPECT_FALSE(NS->containsDecl(Spec));
4659}
4660
Gabor Marton7df342a2018-12-17 12:42:12 +00004661TEST_P(DeclContextTest,
4662 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4663 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4664 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4665 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4666
4667 // Investigate the list.
4668 auto *DC = A0->getDeclContext();
4669 ASSERT_TRUE(DC->containsDecl(A0));
4670 ASSERT_TRUE(DC->containsDecl(A1));
4671
4672 // Investigate the lookup table.
4673 auto *Map = DC->getLookupPtr();
4674 ASSERT_TRUE(Map);
4675 auto I = Map->find(A0->getDeclName());
4676 ASSERT_NE(I, Map->end());
4677 StoredDeclsList &L = I->second;
4678 // The lookup table contains the most recent decl of A.
4679 ASSERT_NE(L.getAsDecl(), A0);
4680 ASSERT_EQ(L.getAsDecl(), A1);
4681
4682 ASSERT_TRUE(L.getAsDecl());
4683 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4684 // The point here is to have a Vec with only one element, which is not the
4685 // one we are going to delete from the DC later.
4686 L.setHasExternalDecls();
4687 ASSERT_TRUE(L.getAsVector());
4688 ASSERT_EQ(1u, L.getAsVector()->size());
4689
4690 // This asserts in the old implementation.
4691 DC->removeDecl(A0);
4692 EXPECT_FALSE(DC->containsDecl(A0));
4693}
4694
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004695struct ImportFunctionTemplateSpecializations
4696 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004697
4698TEST_P(ImportFunctionTemplateSpecializations,
4699 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4700
4701 Decl *FromTU = getTuDecl(
4702 R"(
4703 template<class T>
4704 int f() { return 0; }
4705 void foo() { f<int>(); }
4706 )",
4707 Lang_CXX, "input0.cc");
4708
4709 // Check that the function template instantiation is NOT the child of the TU.
4710 auto Pattern = translationUnitDecl(
4711 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4712 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4713
4714 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4715 FromTU, functionDecl(hasName("foo")));
4716 ASSERT_TRUE(Import(Foo, Lang_CXX));
4717
4718 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4719 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4720}
4721
4722TEST_P(ImportFunctionTemplateSpecializations,
4723 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4724
4725 Decl *FromTU = getTuDecl(
4726 R"(
4727 template<class T>
4728 int f() { return 0; }
4729 template int f<int>();
4730 )",
4731 Lang_CXX, "input0.cc");
4732
4733 // Check that the function template instantiation is NOT the child of the TU.
4734 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4735 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4736 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4737
4738 ASSERT_TRUE(
4739 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4740
4741 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4742 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4743}
4744
4745TEST_P(ImportFunctionTemplateSpecializations,
4746 TUshouldContainFunctionTemplateSpecialization) {
4747
4748 Decl *FromTU = getTuDecl(
4749 R"(
4750 template<class T>
4751 int f() { return 0; }
4752 template <> int f<int>() { return 4; }
4753 )",
4754 Lang_CXX, "input0.cc");
4755
4756 // Check that the function template specialization is the child of the TU.
4757 auto Specialization =
4758 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4759 auto Pattern = translationUnitDecl(has(Specialization));
4760 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4761
4762 ASSERT_TRUE(
4763 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4764
4765 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4766 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4767}
4768
4769TEST_P(ImportFunctionTemplateSpecializations,
4770 FunctionTemplateSpecializationRedeclChain) {
4771
4772 Decl *FromTU = getTuDecl(
4773 R"(
4774 template<class T>
4775 int f() { return 0; }
4776 template <> int f<int>() { return 4; }
4777 )",
4778 Lang_CXX, "input0.cc");
4779
4780 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4781 hasParent(translationUnitDecl()));
4782 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4783 {
4784 auto *TU = FromTU;
4785 auto *SpecD = FromSpecD;
4786 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4787 TU, functionTemplateDecl());
4788 auto *FirstSpecD = *(TemplateD->spec_begin());
4789 ASSERT_EQ(SpecD, FirstSpecD);
4790 ASSERT_TRUE(SpecD->getPreviousDecl());
4791 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4792 ->doesThisDeclarationHaveABody());
4793 }
4794
4795 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4796
4797 {
4798 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4799 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4800 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4801 TU, functionTemplateDecl());
4802 auto *FirstSpecD = *(TemplateD->spec_begin());
4803 EXPECT_EQ(SpecD, FirstSpecD);
4804 ASSERT_TRUE(SpecD->getPreviousDecl());
4805 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4806 ->doesThisDeclarationHaveABody());
4807 }
4808}
4809
4810TEST_P(ImportFunctionTemplateSpecializations,
4811 MatchNumberOfFunctionTemplateSpecializations) {
4812
4813 Decl *FromTU = getTuDecl(
4814 R"(
4815 template <typename T> constexpr int f() { return 0; }
4816 template <> constexpr int f<int>() { return 4; }
4817 void foo() {
4818 static_assert(f<char>() == 0, "");
4819 static_assert(f<int>() == 4, "");
4820 }
4821 )",
4822 Lang_CXX11, "input0.cc");
4823 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4824 FromTU, functionDecl(hasName("foo")));
4825
4826 Import(FromD, Lang_CXX11);
4827 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4828 EXPECT_EQ(
4829 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4830 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4831}
4832
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004833TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004834 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4835 {
4836 Decl *FromTU = getTuDecl(
4837 R"(
4838 template <typename T>
4839 struct B;
4840 )",
4841 Lang_CXX, "input0.cc");
4842 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4843 FromTU, classTemplateDecl(hasName("B")));
4844
4845 Import(FromD, Lang_CXX);
4846 }
4847
4848 {
4849 Decl *FromTU = getTuDecl(
4850 R"(
4851 template <typename T>
4852 struct B {
4853 void f();
4854 B* b;
4855 };
4856 )",
4857 Lang_CXX, "input1.cc");
4858 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4859 FromTU, functionDecl(hasName("f")));
4860 Import(FromD, Lang_CXX);
4861 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4862 FromTU, classTemplateDecl(hasName("B")));
4863 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4864 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4865
4866 // We expect no (ODR) warning during the import.
4867 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4868 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4869 }
4870}
4871
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004872TEST_P(ASTImporterOptionSpecificTestBase,
4873 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004874 // We already have an incomplete underlying type in the "To" context.
4875 auto Code =
4876 R"(
4877 template <typename T>
4878 struct S {
4879 void foo();
4880 };
4881 using U = S<int>;
4882 )";
4883 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4884 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4885 typedefNameDecl(hasName("U")));
4886 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4887
4888 // The "From" context has the same typedef, but the underlying type is
4889 // complete this time.
4890 Decl *FromTU = getTuDecl(std::string(Code) +
4891 R"(
4892 void foo(U* u) {
4893 u->foo();
4894 }
4895 )", Lang_CXX11);
4896 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4897 typedefNameDecl(hasName("U")));
4898 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4899
4900 // The imported type should be complete.
4901 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4902 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4903}
4904
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004905struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004906
4907TEST_P(ASTImporterLookupTableTest, OneDecl) {
4908 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4909 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4910 ASTImporterLookupTable LT(*ToTU);
4911 auto Res = LT.lookup(ToTU, D->getDeclName());
4912 ASSERT_EQ(Res.size(), 1u);
4913 EXPECT_EQ(*Res.begin(), D);
4914}
4915
4916static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4917 for (Decl *D : DC->decls()) {
4918 if (auto *ND = dyn_cast<NamedDecl>(D))
4919 if (ND->getDeclName() == Name)
4920 return ND;
4921 }
4922 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004923}
Gabor Marton54058b52018-12-17 13:53:12 +00004924
4925TEST_P(ASTImporterLookupTableTest,
4926 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4927 auto *Code = R"(
4928 template <class T>
4929 struct X {
4930 friend void foo(){}
4931 };
4932 )";
4933 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4934 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4935 ToTU, classTemplateDecl(hasName("X")));
4936 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4937 ToTU, functionDecl(hasName("foo")));
4938 DeclContext *FooDC = Foo->getDeclContext();
4939 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4940 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4941 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4942 DeclarationName FooName = Foo->getDeclName();
4943
4944 // Cannot find in the LookupTable of its DC (TUDecl)
4945 SmallVector<NamedDecl *, 2> FoundDecls;
4946 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4947 EXPECT_EQ(FoundDecls.size(), 0u);
4948
4949 // Cannot find in the LookupTable of its LexicalDC (X)
4950 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4951 EXPECT_EQ(FoundDecls.size(), 0u);
4952
4953 // Can't find in the list of Decls of the DC.
4954 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4955
4956 // Can't find in the list of Decls of the LexicalDC
4957 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4958
4959 // ASTImporter specific lookup finds it.
4960 ASTImporterLookupTable LT(*ToTU);
4961 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4962 ASSERT_EQ(Res.size(), 1u);
4963 EXPECT_EQ(*Res.begin(), Foo);
4964}
4965
4966TEST_P(ASTImporterLookupTableTest,
4967 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4968 TranslationUnitDecl *ToTU =
4969 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4970 auto *Foo =
4971 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4972 auto *A =
4973 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4974 DeclContext *FooDC = Foo->getDeclContext();
4975 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4976 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4977 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4978 DeclarationName FooName = Foo->getDeclName();
4979
4980 // Cannot find in the LookupTable of its DC (TUDecl).
4981 SmallVector<NamedDecl *, 2> FoundDecls;
4982 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4983 EXPECT_EQ(FoundDecls.size(), 0u);
4984
4985 // Cannot find in the LookupTable of its LexicalDC (A).
4986 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4987 EXPECT_EQ(FoundDecls.size(), 0u);
4988
4989 // Can't find in the list of Decls of the DC.
4990 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4991
4992 // Can find in the list of Decls of the LexicalDC.
4993 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4994
4995 // ASTImporter specific lookup finds it.
4996 ASTImporterLookupTable LT(*ToTU);
4997 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4998 ASSERT_EQ(Res.size(), 1u);
4999 EXPECT_EQ(*Res.begin(), Foo);
5000}
5001
5002TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5003 TranslationUnitDecl *ToTU =
5004 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
5005 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5006 .match(ToTU, varDecl(hasName("V")))
5007 ->getDeclName();
5008 auto *A =
5009 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
5010 auto *B =
5011 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
5012
5013 ASTImporterLookupTable LT(*ToTU);
5014
5015 auto Res = LT.lookup(cast<DeclContext>(A), VName);
5016 ASSERT_EQ(Res.size(), 1u);
5017 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5018 ToTU, fieldDecl(hasName("V"),
5019 hasParent(recordDecl(hasName("A"))))));
5020 Res = LT.lookup(cast<DeclContext>(B), VName);
5021 ASSERT_EQ(Res.size(), 1u);
5022 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5023 ToTU, fieldDecl(hasName("V"),
5024 hasParent(recordDecl(hasName("B"))))));
5025 Res = LT.lookup(ToTU, VName);
5026 ASSERT_EQ(Res.size(), 1u);
5027 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5028 ToTU, varDecl(hasName("V"),
5029 hasParent(translationUnitDecl()))));
5030}
5031
5032TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5033 TranslationUnitDecl *ToTU = getToTuDecl(
5034 R"(
5035 void foo();
5036 void foo(int);
5037 void foo(int, int);
5038 )",
5039 Lang_CXX);
5040
5041 ASTImporterLookupTable LT(*ToTU);
5042 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5043 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5044 DeclarationName Name = F0->getDeclName();
5045 auto Res = LT.lookup(ToTU, Name);
5046 EXPECT_EQ(Res.size(), 3u);
5047 EXPECT_EQ(Res.count(F0), 1u);
5048 EXPECT_EQ(Res.count(F2), 1u);
5049}
5050
Gabor Martona9cab312019-02-08 09:19:34 +00005051TEST_P(ASTImporterLookupTableTest,
5052 DifferentOperatorsShouldHaveDifferentResultSet) {
5053 TranslationUnitDecl *ToTU = getToTuDecl(
5054 R"(
5055 struct X{};
5056 void operator+(X, X);
5057 void operator-(X, X);
5058 )",
5059 Lang_CXX);
5060
5061 ASTImporterLookupTable LT(*ToTU);
5062 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5063 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5064 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5065 ToTU, functionDecl(hasOverloadedOperatorName("-")));
5066 DeclarationName NamePlus = FPlus->getDeclName();
5067 auto ResPlus = LT.lookup(ToTU, NamePlus);
5068 EXPECT_EQ(ResPlus.size(), 1u);
5069 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5070 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5071 DeclarationName NameMinus = FMinus->getDeclName();
5072 auto ResMinus = LT.lookup(ToTU, NameMinus);
5073 EXPECT_EQ(ResMinus.size(), 1u);
5074 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5075 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5076 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5077}
5078
5079TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5080 TranslationUnitDecl *ToTU = getToTuDecl(
5081 R"(
5082 struct X {};
5083 void operator+(X, X);
5084 )",
5085 Lang_CXX);
5086 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5087 ToTU, functionDecl(hasOverloadedOperatorName("+")));
5088
5089 Decl *FromTU = getTuDecl(
5090 R"(
5091 struct X {};
5092 void operator+(X, X);
5093 )",
5094 Lang_CXX);
5095 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5096 FromTU, functionDecl(hasOverloadedOperatorName("+")));
5097
5098 // FromPlus have a different TU, thus its DeclarationName is different too.
5099 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5100
5101 ASTImporterLookupTable LT(*ToTU);
5102 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
5103 ASSERT_EQ(Res.size(), 1u);
5104 EXPECT_EQ(*Res.begin(), ToPlus);
5105
5106 // FromPlus have a different TU, thus its DeclarationName is different too.
5107 Res = LT.lookup(ToTU, FromPlus->getDeclName());
5108 ASSERT_EQ(Res.size(), 0u);
5109}
5110
Gabor Marton54058b52018-12-17 13:53:12 +00005111static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
5112 QualType Ty = FD->getFriendType()->getType();
5113 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
5114 return cast<RecordType>(NamedTy)->getDecl();
5115}
5116
5117TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
5118 TranslationUnitDecl *ToTU = getToTuDecl(
5119 R"(
5120 class Y { friend class F; };
5121 )",
5122 Lang_CXX);
5123
5124 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5125 // So we must dig up the underlying CXXRecordDecl.
5126 ASTImporterLookupTable LT(*ToTU);
5127 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5128 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5129 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5130 ToTU, cxxRecordDecl(hasName("Y")));
5131
5132 DeclarationName Name = RD->getDeclName();
5133 auto Res = LT.lookup(ToTU, Name);
5134 EXPECT_EQ(Res.size(), 1u);
5135 EXPECT_EQ(*Res.begin(), RD);
5136
5137 Res = LT.lookup(Y, Name);
5138 EXPECT_EQ(Res.size(), 0u);
5139}
5140
5141TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5142 TranslationUnitDecl *ToTU = getToTuDecl(
5143 R"(
5144 class Y { template <class T> friend class F; };
5145 )",
5146 Lang_CXX);
5147
5148 ASTImporterLookupTable LT(*ToTU);
5149 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5150 ToTU, classTemplateDecl(hasName("F")));
5151 DeclarationName Name = F->getDeclName();
5152 auto Res = LT.lookup(ToTU, Name);
5153 EXPECT_EQ(Res.size(), 2u);
5154 EXPECT_EQ(Res.count(F), 1u);
5155 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5156}
5157
5158TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5159 TranslationUnitDecl *ToTU = getToTuDecl(
5160 R"(
5161 template <typename T>
5162 class F;
5163
5164 template <typename T>
5165 class Y {
5166 friend class F<T>;
5167 };
5168 )",
5169 Lang_CXX);
5170
5171 ASTImporterLookupTable LT(*ToTU);
5172 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5173 ToTU, classTemplateDecl(hasName("F")));
5174 DeclarationName Name = F->getDeclName();
5175 auto Res = LT.lookup(ToTU, Name);
5176 EXPECT_EQ(Res.size(), 2u);
5177 EXPECT_EQ(Res.count(F), 1u);
5178 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5179}
5180
5181TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5182 TranslationUnitDecl *ToTU = getToTuDecl(
5183 R"(
5184 template <typename T>
5185 class F;
5186
5187 class Y {
5188 friend class F<int>;
5189 };
5190 )",
5191 Lang_CXX);
5192
5193 ASTImporterLookupTable LT(*ToTU);
5194 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5195 ToTU, classTemplateDecl(hasName("F")));
5196 DeclarationName Name = F->getDeclName();
5197 auto Res = LT.lookup(ToTU, Name);
5198 ASSERT_EQ(Res.size(), 3u);
5199 EXPECT_EQ(Res.count(F), 1u);
5200 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5201 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5202}
5203
5204TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5205 TranslationUnitDecl *ToTU = getToTuDecl(
5206 R"(
5207 class Y { friend void F(); };
5208 )",
5209 Lang_CXX);
5210
5211 ASTImporterLookupTable LT(*ToTU);
5212 auto *F =
5213 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
5214 DeclarationName Name = F->getDeclName();
5215 auto Res = LT.lookup(ToTU, Name);
5216 EXPECT_EQ(Res.size(), 1u);
5217 EXPECT_EQ(*Res.begin(), F);
5218}
5219
5220TEST_P(ASTImporterLookupTableTest,
5221 LookupFindsDeclsInClassTemplateSpecialization) {
5222 TranslationUnitDecl *ToTU = getToTuDecl(
5223 R"(
5224 template <typename T>
5225 struct X {
5226 int F;
5227 };
5228 void foo() {
5229 X<char> xc;
5230 }
5231 )",
5232 Lang_CXX);
5233
5234 ASTImporterLookupTable LT(*ToTU);
5235
5236 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5237 ToTU, classTemplateDecl(hasName("X")));
5238 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5239 ToTU,
5240 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5241
5242 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5243 ToTU, classTemplateSpecializationDecl(hasName("X")));
5244 FieldDecl *FieldInSpec = *Spec->field_begin();
5245 ASSERT_TRUE(FieldInSpec);
5246
5247 DeclarationName Name = FieldInSpec->getDeclName();
5248 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5249
5250 SmallVector<NamedDecl *, 2> FoundDecls;
5251 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5252 EXPECT_EQ(FoundDecls.size(), 1u);
5253 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5254
5255 auto Res = LT.lookup(TemplateDC, Name);
5256 ASSERT_EQ(Res.size(), 1u);
5257 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5258
5259 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5260 FoundDecls);
5261 EXPECT_EQ(FoundDecls.size(), 1u);
5262 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5263
5264 Res = LT.lookup(cast<DeclContext>(Spec), Name);
5265 ASSERT_EQ(Res.size(), 1u);
5266 EXPECT_EQ(*Res.begin(), FieldInSpec);
5267}
5268
5269TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5270 TranslationUnitDecl *ToTU = getToTuDecl(
5271 R"(
5272 class Y { template <class T> friend void F(); };
5273 )",
5274 Lang_CXX);
5275
5276 ASTImporterLookupTable LT(*ToTU);
5277 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
5278 ToTU, functionTemplateDecl(hasName("F")));
5279 DeclarationName Name = F->getDeclName();
5280 auto Res = LT.lookup(ToTU, Name);
5281 EXPECT_EQ(Res.size(), 2u);
5282 EXPECT_EQ(Res.count(F), 1u);
5283 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5284}
5285
5286TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
5287 TranslationUnitDecl *ToTU = getToTuDecl(
5288 R"(
5289 struct X;
5290 struct A {
5291 friend struct X;
5292 };
5293 struct B {
5294 friend struct X;
5295 };
5296 )",
5297 Lang_CXX);
5298
5299 ASTImporterLookupTable LT(*ToTU);
5300 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
5301 ToTU, cxxRecordDecl(hasName("X")));
5302 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5303 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5304 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
5305 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
5306 ASSERT_EQ(RD0, RD1);
5307 ASSERT_EQ(RD1, X);
5308
5309 DeclarationName Name = X->getDeclName();
5310 auto Res = LT.lookup(ToTU, Name);
5311 EXPECT_EQ(Res.size(), 1u);
5312 EXPECT_EQ(*Res.begin(), X);
5313}
5314
5315TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
5316 TranslationUnitDecl *ToTU = getToTuDecl(
5317 R"(
5318 enum E {
5319 A,
5320 B
5321 };
5322 )",
5323 Lang_C);
5324
5325 ASTImporterLookupTable LT(*ToTU);
5326 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
5327 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
5328 ToTU, enumConstantDecl(hasName("A")));
5329
5330 DeclarationName Name = A->getDeclName();
5331 // Redecl context is the TU.
5332 ASSERT_EQ(E->getRedeclContext(), ToTU);
5333
5334 SmallVector<NamedDecl *, 2> FoundDecls;
5335 // Normal lookup finds in the DC.
5336 E->localUncachedLookup(Name, FoundDecls);
5337 EXPECT_EQ(FoundDecls.size(), 1u);
5338
5339 // Normal lookup finds in the Redecl context.
5340 ToTU->localUncachedLookup(Name, FoundDecls);
5341 EXPECT_EQ(FoundDecls.size(), 1u);
5342
5343 // Import specific lookup finds in the DC.
5344 auto Res = LT.lookup(E, Name);
5345 ASSERT_EQ(Res.size(), 1u);
5346 EXPECT_EQ(*Res.begin(), A);
5347
5348 // Import specific lookup finds in the Redecl context.
5349 Res = LT.lookup(ToTU, Name);
5350 ASSERT_EQ(Res.size(), 1u);
5351 EXPECT_EQ(*Res.begin(), A);
5352}
5353
5354TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
5355 TranslationUnitDecl *ToTU = getToTuDecl(
5356 R"(
5357 namespace N {
5358 int A;
5359 }
5360 namespace N {
5361 }
5362 )",
5363 Lang_CXX);
5364 auto *N1 =
5365 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
5366 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
5367 DeclarationName Name = A->getDeclName();
5368
5369 ASTImporterLookupTable LT(*ToTU);
5370 auto Res = LT.lookup(N1, Name);
5371 ASSERT_EQ(Res.size(), 1u);
5372 EXPECT_EQ(*Res.begin(), A);
5373}
5374
Gabor Marton19f4f392018-06-25 13:04:37 +00005375INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5376 ::testing::Values(ArgVector()), );
5377
Gabor Marton5254e642018-06-27 13:32:50 +00005378INSTANTIATE_TEST_CASE_P(
5379 ParameterizedTests, CanonicalRedeclChain,
5380 ::testing::Values(ArgVector()),);
5381
Gabor Marton0e04ebd2019-02-11 10:27:58 +00005382// FIXME This test is disabled currently, upcoming patches will make it
5383// possible to enable.
5384TEST_P(ASTImporterOptionSpecificTestBase,
5385 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
5386 Decl *FromTU = getTuDecl(
5387 R"(
5388 namespace NS {
5389 struct X;
5390 struct Y {
5391 static const int I = 3;
5392 };
5393 }
5394 namespace NS {
5395 struct X { // <--- To be imported
5396 void method(int i = Y::I) {}
5397 int f;
5398 };
5399 }
5400 )",
5401 Lang_CXX);
5402 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5403 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5404 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
5405 FromTU,
5406 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
5407 ASSERT_NE(FromFwd, FromDef);
5408 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
5409 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
5410 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
5411
5412 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
5413 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
5414 EXPECT_NE(ToFwd, ToDef);
5415 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
5416 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
5417 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
5418 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5419 // We expect no (ODR) warning during the import.
5420 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5421}
5422
Gabor Martone331e632019-02-18 13:09:27 +00005423struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
5424
5425TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
5426 Decl *ToTU = getToTuDecl(
5427 R"(
5428 class X {
5429 template <typename T> friend void foo();
5430 };
5431 )",
5432 Lang_CXX);
5433 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
5434 ToTU, functionTemplateDecl(hasName("foo")));
5435
5436 Decl *FromTU = getTuDecl(
5437 R"(
5438 template <typename T> void foo();
5439 )",
5440 Lang_CXX);
5441 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
5442 FromTU, functionTemplateDecl(hasName("foo")));
5443 auto *Imported = Import(FromFoo, Lang_CXX);
5444
5445 // FIXME Currently chains of FunctionTemplateDecls are not implemented.
5446 //EXPECT_EQ(Imported->getPreviousDecl(), Friend);
5447 EXPECT_EQ(Imported, Friend);
5448}
5449
Gabor Marton54058b52018-12-17 13:53:12 +00005450INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5451 DefaultTestValuesForRunOptions, );
5452
Gabor Marton19f4f392018-06-25 13:04:37 +00005453INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5454 DefaultTestValuesForRunOptions, );
5455
5456INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5457 DefaultTestValuesForRunOptions, );
5458
5459INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5460 DefaultTestValuesForRunOptions, );
5461
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005462INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005463 DefaultTestValuesForRunOptions, );
5464
5465INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5466 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005467
Gabor Martone331e632019-02-18 13:09:27 +00005468INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5469 DefaultTestValuesForRunOptions, );
5470
Gabor Marton54058b52018-12-17 13:53:12 +00005471INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005472 DefaultTestValuesForRunOptions, );
5473
Gabor Marton54058b52018-12-17 13:53:12 +00005474INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005475 DefaultTestValuesForRunOptions, );
5476
Gabor Marton7df342a2018-12-17 12:42:12 +00005477INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5478 DefaultTestValuesForRunOptions, );
5479
Gabor Marton5254e642018-06-27 13:32:50 +00005480INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5481 ImportFunctionTemplateSpecializations,
5482 DefaultTestValuesForRunOptions, );
5483
Gabor Martonac3a5d62018-09-17 12:04:52 +00005484INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5485 DefaultTestValuesForRunOptions, );
5486
5487INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5488 DefaultTestValuesForRunOptions, );
5489
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005490} // end namespace ast_matchers
5491} // end namespace clang