12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792 |
- //===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // Tests for the correct import of AST nodes from one AST context to another.
- //
- //===----------------------------------------------------------------------===//
- #include "MatchVerifier.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTImporter.h"
- #include "clang/ASTMatchers/ASTMatchFinder.h"
- #include "clang/ASTMatchers/ASTMatchers.h"
- #include "clang/Tooling/Tooling.h"
- #include "DeclMatcher.h"
- #include "Language.h"
- #include "gmock/gmock.h"
- #include "llvm/ADT/StringMap.h"
- namespace clang {
- namespace ast_matchers {
- using internal::Matcher;
- using internal::BindableMatcher;
- using llvm::StringMap;
- // Creates a virtual file and assigns that to the context of given AST. If the
- // file already exists then the file will not be created again as a duplicate.
- static void
- createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
- std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
- assert(ToAST);
- ASTContext &ToCtx = ToAST->getASTContext();
- auto *OFS = static_cast<vfs::OverlayFileSystem *>(
- ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
- auto *MFS =
- static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
- MFS->addFile(FileName, 0, std::move(Buffer));
- }
- static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
- StringRef Code) {
- return createVirtualFileIfNeeded(ToAST, FileName,
- llvm::MemoryBuffer::getMemBuffer(Code));
- }
- const StringRef DeclToImportID = "declToImport";
- const StringRef DeclToVerifyID = "declToVerify";
- // Common base for the different families of ASTImporter tests that are
- // parameterized on the compiler options which may result a different AST. E.g.
- // -fms-compatibility or -fdelayed-template-parsing.
- struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
- // Returns the argument vector used for a specific language option, this set
- // can be tweaked by the test parameters.
- ArgVector getArgVectorForLanguage(Language Lang) const {
- ArgVector Args = getBasicRunOptionsForLanguage(Lang);
- ArgVector ExtraArgs = GetParam();
- for (const auto &Arg : ExtraArgs) {
- Args.push_back(Arg);
- }
- return Args;
- }
- };
- // Base class for those tests which use the family of `testImport` functions.
- class TestImportBase : public ParameterizedTestsFixture {
- template <typename NodeType>
- NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
- NodeType Node) {
- ASTContext &ToCtx = To->getASTContext();
- // Add 'From' file to virtual file system so importer can 'find' it
- // while importing SourceLocations. It is safe to add same file multiple
- // times - it just isn't replaced.
- StringRef FromFileName = From->getMainFileName();
- createVirtualFileIfNeeded(To, FromFileName,
- From->getBufferForFile(FromFileName));
- auto Imported = Importer.Import(Node);
- // This should dump source locations and assert if some source locations
- // were not imported.
- SmallString<1024> ImportChecker;
- llvm::raw_svector_ostream ToNothing(ImportChecker);
- ToCtx.getTranslationUnitDecl()->print(ToNothing);
- // This traverses the AST to catch certain bugs like poorly or not
- // implemented subtrees.
- Imported->dump(ToNothing);
- return Imported;
- }
- template <typename NodeType>
- testing::AssertionResult
- testImport(const std::string &FromCode, const ArgVector &FromArgs,
- const std::string &ToCode, const ArgVector &ToArgs,
- MatchVerifier<NodeType> &Verifier,
- const BindableMatcher<NodeType> &SearchMatcher,
- const BindableMatcher<NodeType> &VerificationMatcher) {
- const char *const InputFileName = "input.cc";
- const char *const OutputFileName = "output.cc";
- std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
- FromCode, FromArgs, InputFileName),
- ToAST = tooling::buildASTFromCodeWithArgs(
- ToCode, ToArgs, OutputFileName);
- ASTContext &FromCtx = FromAST->getASTContext(),
- &ToCtx = ToAST->getASTContext();
- ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
- FromAST->getFileManager(), false);
- auto FoundNodes = match(SearchMatcher, FromCtx);
- if (FoundNodes.size() != 1)
- return testing::AssertionFailure()
- << "Multiple potential nodes were found!";
- auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
- if (!ToImport)
- return testing::AssertionFailure() << "Node type mismatch!";
- // Sanity check: the node being imported should match in the same way as
- // the result node.
- BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
- EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
- auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
- if (!Imported)
- return testing::AssertionFailure() << "Import failed, nullptr returned!";
- return Verifier.match(Imported, WrapperMatcher);
- }
- template <typename NodeType>
- testing::AssertionResult
- testImport(const std::string &FromCode, const ArgVector &FromArgs,
- const std::string &ToCode, const ArgVector &ToArgs,
- MatchVerifier<NodeType> &Verifier,
- const BindableMatcher<NodeType> &VerificationMatcher) {
- return testImport(
- FromCode, FromArgs, ToCode, ToArgs, Verifier,
- translationUnitDecl(
- has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
- VerificationMatcher);
- }
- public:
- /// Test how AST node named "declToImport" located in the translation unit
- /// of "FromCode" virtual file is imported to "ToCode" virtual file.
- /// The verification is done by running AMatcher over the imported node.
- template <typename NodeType, typename MatcherType>
- void testImport(const std::string &FromCode, Language FromLang,
- const std::string &ToCode, Language ToLang,
- MatchVerifier<NodeType> &Verifier,
- const MatcherType &AMatcher) {
- ArgVector FromArgs = getArgVectorForLanguage(FromLang),
- ToArgs = getArgVectorForLanguage(ToLang);
- EXPECT_TRUE(
- testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
- }
- struct ImportAction {
- StringRef FromFilename;
- StringRef ToFilename;
- // FIXME: Generalize this to support other node kinds.
- BindableMatcher<Decl> ImportPredicate;
- ImportAction(StringRef FromFilename, StringRef ToFilename,
- DeclarationMatcher ImportPredicate)
- : FromFilename(FromFilename), ToFilename(ToFilename),
- ImportPredicate(ImportPredicate) {}
- ImportAction(StringRef FromFilename, StringRef ToFilename,
- const std::string &DeclName)
- : FromFilename(FromFilename), ToFilename(ToFilename),
- ImportPredicate(namedDecl(hasName(DeclName))) {}
- };
- using SingleASTUnit = std::unique_ptr<ASTUnit>;
- using AllASTUnits = StringMap<SingleASTUnit>;
- struct CodeEntry {
- std::string CodeSample;
- Language Lang;
- };
- using CodeFiles = StringMap<CodeEntry>;
- /// Builds an ASTUnit for one potential compile options set.
- SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
- ArgVector Args = getArgVectorForLanguage(CE.Lang);
- auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
- EXPECT_TRUE(AST.get());
- return AST;
- }
- /// Test an arbitrary sequence of imports for a set of given in-memory files.
- /// The verification is done by running VerificationMatcher against a
- /// specified AST node inside of one of given files.
- /// \param CodeSamples Map whose key is the file name and the value is the
- /// file content.
- /// \param ImportActions Sequence of imports. Each import in sequence
- /// specifies "from file" and "to file" and a matcher that is used for
- /// searching a declaration for import in "from file".
- /// \param FileForFinalCheck Name of virtual file for which the final check is
- /// applied.
- /// \param FinalSelectPredicate Matcher that specifies the AST node in the
- /// FileForFinalCheck for which the verification will be done.
- /// \param VerificationMatcher Matcher that will be used for verification
- /// after all imports in sequence are done.
- void testImportSequence(const CodeFiles &CodeSamples,
- const std::vector<ImportAction> &ImportActions,
- StringRef FileForFinalCheck,
- BindableMatcher<Decl> FinalSelectPredicate,
- BindableMatcher<Decl> VerificationMatcher) {
- AllASTUnits AllASTs;
- using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
- llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
- auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
- if (!AllASTs.count(Filename)) {
- auto Found = CodeSamples.find(Filename);
- assert(Found != CodeSamples.end() && "Wrong file for import!");
- AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
- }
- };
- for (const ImportAction &Action : ImportActions) {
- StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
- GenASTsIfNeeded(FromFile);
- GenASTsIfNeeded(ToFile);
- ASTUnit *From = AllASTs[FromFile].get();
- ASTUnit *To = AllASTs[ToFile].get();
- // Create a new importer if needed.
- std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
- if (!ImporterRef)
- ImporterRef.reset(new ASTImporter(
- To->getASTContext(), To->getFileManager(), From->getASTContext(),
- From->getFileManager(), false));
- // Find the declaration and import it.
- auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
- From->getASTContext());
- EXPECT_TRUE(FoundDecl.size() == 1);
- const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
- auto Imported = importNode(From, To, *ImporterRef, ToImport);
- EXPECT_TRUE(Imported);
- }
- // Find the declaration and import it.
- auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
- AllASTs[FileForFinalCheck]->getASTContext());
- EXPECT_TRUE(FoundDecl.size() == 1);
- const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
- MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(
- Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
- }
- };
- // This class provides generic methods to write tests which can check internal
- // attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
- // this fixture makes it possible to import from several "From" contexts.
- class ASTImporterTestBase : public ParameterizedTestsFixture {
- const char *const InputFileName = "input.cc";
- const char *const OutputFileName = "output.cc";
- // Buffer for the To context, must live in the test scope.
- std::string ToCode;
- // Represents a "From" translation unit and holds an importer object which we
- // use to import from this translation unit.
- struct TU {
- // Buffer for the context, must live in the test scope.
- std::string Code;
- std::string FileName;
- std::unique_ptr<ASTUnit> Unit;
- TranslationUnitDecl *TUDecl = nullptr;
- std::unique_ptr<ASTImporter> Importer;
- TU(StringRef Code, StringRef FileName, ArgVector Args)
- : Code(Code), FileName(FileName),
- Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
- this->FileName)),
- TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
- Unit->enableSourceFileDiagnostics();
- }
- Decl *import(ASTUnit *ToAST, Decl *FromDecl) {
- assert(ToAST);
- if (!Importer) {
- Importer.reset(new ASTImporter(
- ToAST->getASTContext(), ToAST->getFileManager(),
- Unit->getASTContext(), Unit->getFileManager(), false));
- }
- return Importer->Import(FromDecl);
- }
- };
- // We may have several From contexts and related translation units. In each
- // AST, the buffers for the source are handled via references and are set
- // during the creation of the AST. These references must point to a valid
- // buffer until the AST is alive. Thus, we must use a list in order to avoid
- // moving of the stored objects because that would mean breaking the
- // references in the AST. By using a vector a move could happen when the
- // vector is expanding, with the list we won't have these issues.
- std::list<TU> FromTUs;
- public:
- // We may have several From context but only one To context.
- std::unique_ptr<ASTUnit> ToAST;
- // Creates an AST both for the From and To source code and imports the Decl
- // of the identifier into the To context.
- // Must not be called more than once within the same test.
- std::tuple<Decl *, Decl *>
- getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
- Language ToLang, StringRef Identifier = DeclToImportID) {
- ArgVector FromArgs = getArgVectorForLanguage(FromLang),
- ToArgs = getArgVectorForLanguage(ToLang);
- FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
- TU &FromTU = FromTUs.back();
- ToCode = ToSrcCode;
- assert(!ToAST);
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
- ToAST->enableSourceFileDiagnostics();
- ASTContext &FromCtx = FromTU.Unit->getASTContext();
- createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
- IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
- assert(ImportedII && "Declaration with the given identifier "
- "should be specified in test!");
- DeclarationName ImportDeclName(ImportedII);
- SmallVector<NamedDecl *, 4> FoundDecls;
- FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
- FoundDecls);
- assert(FoundDecls.size() == 1);
- Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front());
- assert(Imported);
- return std::make_tuple(*FoundDecls.begin(), Imported);
- }
- // Creates a TU decl for the given source code which can be used as a From
- // context. May be called several times in a given test (with different file
- // name).
- TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
- StringRef FileName = "input.cc") {
- assert(
- std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
- return E.FileName == FileName;
- }) == FromTUs.end());
- ArgVector Args = getArgVectorForLanguage(Lang);
- FromTUs.emplace_back(SrcCode, FileName, Args);
- TU &Tu = FromTUs.back();
- return Tu.TUDecl;
- }
- // Creates the To context with the given source code and returns the TU decl.
- TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
- ArgVector ToArgs = getArgVectorForLanguage(ToLang);
- ToCode = ToSrcCode;
- assert(!ToAST);
- ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
- ToAST->enableSourceFileDiagnostics();
- return ToAST->getASTContext().getTranslationUnitDecl();
- }
- // Import the given Decl into the ToCtx.
- // May be called several times in a given test.
- // The different instances of the param From may have different ASTContext.
- Decl *Import(Decl *From, Language ToLang) {
- if (!ToAST) {
- ArgVector ToArgs = getArgVectorForLanguage(ToLang);
- // Build the AST from an empty file.
- ToAST =
- tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
- ToAST->enableSourceFileDiagnostics();
- }
- // Create a virtual file in the To Ctx which corresponds to the file from
- // which we want to import the `From` Decl. Without this source locations
- // will be invalid in the ToCtx.
- auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
- return E.TUDecl == From->getTranslationUnitDecl();
- });
- assert(It != FromTUs.end());
- createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
- return It->import(ToAST.get(), From);
- }
- ~ASTImporterTestBase() {
- if (!::testing::Test::HasFailure()) return;
- for (auto &Tu : FromTUs) {
- assert(Tu.Unit);
- llvm::errs() << "FromAST:\n";
- Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
- llvm::errs() << "\n";
- }
- if (ToAST) {
- llvm::errs() << "ToAST:\n";
- ToAST->getASTContext().getTranslationUnitDecl()->dump();
- }
- }
- };
- struct ImportExpr : TestImportBase {};
- struct ImportType : TestImportBase {};
- struct ImportDecl : TestImportBase {};
- struct CanonicalRedeclChain : ASTImporterTestBase {};
- TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto Redecls = getCanonicalForwardRedeclChain(D0);
- ASSERT_EQ(Redecls.size(), 1u);
- EXPECT_EQ(D0, Redecls[0]);
- }
- TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
- Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- FunctionDecl *D1 = D2->getPreviousDecl();
- auto Redecls = getCanonicalForwardRedeclChain(D0);
- ASSERT_EQ(Redecls.size(), 3u);
- EXPECT_EQ(D0, Redecls[0]);
- EXPECT_EQ(D1, Redecls[1]);
- EXPECT_EQ(D2, Redecls[2]);
- }
- TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
- Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- FunctionDecl *D1 = D2->getPreviousDecl();
- auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
- auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
- auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
- EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
- EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
- }
- TEST_P(ImportExpr, ImportStringLiteral) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const char [4]"))))));
- testImport(
- "void declToImport() { (void)L\"foo\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const wchar_t [4]"))))));
- testImport(
- "void declToImport() { (void) \"foo\" \"bar\"; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- stringLiteral(hasType(asString("const char [7]"))))));
- }
- TEST_P(ImportExpr, ImportGNUNullExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)__null; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
- }
- TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)nullptr; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
- }
- TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)1.0; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- floatLiteral(equals(1.0), hasType(asString("double"))))));
- testImport(
- "void declToImport() { (void)1.0e-5f; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
- }
- TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct s { int x; long y; unsigned z; }; "
- " (void)(struct s){ 42, 0L, 1U }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- compoundLiteralExpr(
- hasType(asString("struct s")),
- has(initListExpr(
- hasType(asString("struct s")),
- has(integerLiteral(
- equals(42), hasType(asString("int")))),
- has(integerLiteral(
- equals(0), hasType(asString("long")))),
- has(integerLiteral(
- equals(1), hasType(asString("unsigned int"))))))))));
- }
- TEST_P(ImportExpr, ImportCXXThisExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "class declToImport { void f() { (void)this; } };",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(
- hasMethod(
- hasDescendant(
- cxxThisExpr(
- hasType(
- asString("class declToImport *")))))));
- }
- TEST_P(ImportExpr, ImportAtomicExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- atomicExpr(
- has(ignoringParenImpCasts(
- declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
- hasType(asString("int *"))))),
- has(integerLiteral(equals(1), hasType(asString("int"))))))));
- }
- TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { loop: goto loop; (void)&&loop; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(
- hasDescendant(
- labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
- hasDescendant(
- addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
- }
- AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
- internal::Matcher<NamedDecl>, InnerMatcher) {
- const NamedDecl *Template = Node.getTemplatedDecl();
- return Template && InnerMatcher.matches(*Template, Finder, Builder);
- }
- TEST_P(ImportExpr, ImportParenListExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> class dummy { void f() { dummy X(*this); } };"
- "typedef dummy<int> declToImport;"
- "template class dummy<int>;",
- Lang_CXX, "", Lang_CXX, Verifier,
- typedefDecl(hasType(templateSpecializationType(
- hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
- classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
- hasName("f"),
- hasBody(compoundStmt(has(declStmt(hasSingleDecl(
- varDecl(hasInitializer(parenListExpr(has(unaryOperator(
- hasOperatorName("*"),
- hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
- }
- TEST_P(ImportExpr, ImportSwitch) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { int b; switch (b) { case 1: break; } }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- switchStmt(has(compoundStmt(has(caseStmt())))))));
- }
- TEST_P(ImportExpr, ImportStmtExpr) {
- MatchVerifier<Decl> Verifier;
- // NOTE: has() ignores implicit casts, using hasDescendant() to match it
- testImport(
- "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- varDecl(
- hasName("C"),
- hasType(asString("int")),
- hasInitializer(
- stmtExpr(
- hasAnySubstatement(declStmt(hasSingleDecl(
- varDecl(
- hasName("X"),
- hasType(asString("int")),
- hasInitializer(
- integerLiteral(equals(4))))))),
- hasDescendant(
- implicitCastExpr())))))));
- }
- TEST_P(ImportExpr, ImportConditionalOperator) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)(true ? 1 : -5); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- conditionalOperator(
- hasCondition(cxxBoolLiteral(equals(true))),
- hasTrueExpression(integerLiteral(equals(1))),
- hasFalseExpression(
- unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
- )));
- }
- TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { (void)(1 ?: -5); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- binaryConditionalOperator(
- hasCondition(
- implicitCastExpr(
- hasSourceExpression(opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasType(booleanType()))),
- hasTrueExpression(
- opaqueValueExpr(
- hasSourceExpression(integerLiteral(equals(1))))),
- hasFalseExpression(
- unaryOperator(
- hasOperatorName("-"),
- hasUnaryOperand(integerLiteral(equals(5)))))))));
- }
- TEST_P(ImportExpr, ImportDesignatedInitExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " struct point ptarray[10] = "
- "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(
- initListExpr(
- has(designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(equals(1.0))),
- has(integerLiteral(equals(2))))),
- has(designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(equals(2.0))),
- has(integerLiteral(equals(2))))),
- has(designatedInitExpr(
- designatorCountIs(2),
- has(floatLiteral(equals(1.0))),
- has(integerLiteral(equals(0)))))))));
- }
- TEST_P(ImportExpr, ImportPredefinedExpr) {
- MatchVerifier<Decl> Verifier;
- // __func__ expands as StringLiteral("declToImport")
- testImport(
- "void declToImport() { (void)__func__; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- predefinedExpr(
- hasType(
- asString("const char [13]")),
- has(stringLiteral(hasType(
- asString("const char [13]"))))))));
- }
- TEST_P(ImportExpr, ImportInitListExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() {"
- " struct point { double x; double y; };"
- " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
- " [0].x = 1.0 }; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- initListExpr(
- has(
- cxxConstructExpr(
- requiresZeroInitialization())),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(1.0))),
- has(implicitValueInitExpr(
- hasType(asString("double")))))),
- has(
- initListExpr(
- hasType(asString("struct point")),
- has(floatLiteral(equals(2.0))),
- has(floatLiteral(equals(1.0)))))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
- TEST_P(ImportExpr, ImportVAArgExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport(__builtin_va_list list, ...) {"
- " (void)__builtin_va_arg(list, int); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
- }
- TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "struct C {};"
- "void declToImport() { C c = C(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- exprWithCleanups(has(cxxConstructExpr(
- has(materializeTemporaryExpr(has(implicitCastExpr(
- has(cxxTemporaryObjectExpr())))))))))));
- }
- TEST_P(ImportType, ImportAtomicType) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { typedef _Atomic(int) a_int; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
- }
- TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> void declToImport() { };",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl());
- }
- const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
- cxxDependentScopeMemberExpr;
- TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (void)d.t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (void)(&d)->t;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
- }
- TEST_P(ImportType, ImportTypeAliasTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <int K>"
- "struct dummy { static const int i = K; };"
- "template <int K> using dummy2 = dummy<K>;"
- "int declToImport() { return dummy2<3>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasDescendant(implicitCastExpr(has(declRefExpr()))),
- unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
- varTemplateSpecializationDecl;
- TEST_P(ImportDecl, ImportVarTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T>"
- "T pi = T(3.1415926535897932385L);"
- "void declToImport() { (void)pi<int>; }",
- Lang_CXX14, "", Lang_CXX14, Verifier,
- functionDecl(
- hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
- unless(hasAncestor(translationUnitDecl(has(varDecl(
- hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
- }
- TEST_P(ImportType, ImportPackExpansion) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename... Args>"
- "struct dummy {"
- " dummy(Args... args) {}"
- " static const int i = 4;"
- "};"
- "int declToImport() { return dummy<int>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(hasDescendant(
- returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Type,
- DependentTemplateSpecializationType>
- dependentTemplateSpecializationType;
- TEST_P(ImportType, ImportDependentTemplateSpecialization) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T>"
- "struct A;"
- "template<typename T>"
- "struct declToImport {"
- " typename A<T>::template B<T> a;"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(has(cxxRecordDecl(has(
- fieldDecl(hasType(dependentTemplateSpecializationType())))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
- sizeOfPackExpr;
- TEST_P(ImportExpr, ImportSizeOfPackExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename... Ts>"
- "void declToImport() {"
- " const int i = sizeof...(Ts);"
- "};"
- "void g() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
- testImport(
- "template <typename... Ts>"
- "using X = int[sizeof...(Ts)];"
- "template <typename... Us>"
- "struct Y {"
- " X<Us..., int, double, int, Us...> f;"
- "};"
- "Y<float, int> declToImport;",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
- hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
- }
- /// \brief Matches __builtin_types_compatible_p:
- /// GNU extension to check equivalent types
- /// Given
- /// \code
- /// __builtin_types_compatible_p(int, int)
- /// \endcode
- // will generate TypeTraitExpr <...> 'int'
- const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
- TEST_P(ImportExpr, ImportTypeTraitExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "void declToImport() { "
- " (void)__builtin_types_compatible_p(int, int);"
- "}",
- Lang_C, "", Lang_C, Verifier,
- functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
- TEST_P(ImportExpr, ImportCXXTypeidExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace std { class type_info {}; }"
- "void declToImport() {"
- " int x;"
- " auto a = typeid(int); auto b = typeid(x);"
- "}",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasDescendant(varDecl(
- hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
- hasDescendant(varDecl(
- hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
- }
- TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> struct declToImport {"
- " void m() { (void)__is_pod(T); }"
- "};"
- "void f() { declToImport<int>().m(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(has(cxxRecordDecl(has(
- functionDecl(hasDescendant(
- typeTraitExpr(hasType(booleanType())))))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
- cxxPseudoDestructorExpr;
- TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "typedef int T;"
- "void declToImport(int *p) {"
- " T t;"
- " p->T::~T();"
- "}",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(
- callExpr(has(cxxPseudoDestructorExpr())))));
- }
- TEST_P(ImportDecl, ImportUsingDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace foo { int bar; }"
- "void declToImport() { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionDecl(hasDescendant(usingDecl())));
- }
- /// \brief Matches shadow declarations introduced into a scope by a
- /// (resolved) using declaration.
- ///
- /// Given
- /// \code
- /// namespace n { int f; }
- /// namespace declToImport { using n::f; }
- /// \endcode
- /// usingShadowDecl()
- /// matches \code f \endcode
- const internal::VariadicDynCastAllOfMatcher<Decl,
- UsingShadowDecl> usingShadowDecl;
- TEST_P(ImportDecl, ImportUsingShadowDecl) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "namespace foo { int bar; }"
- "namespace declToImport { using foo::bar; }",
- Lang_CXX, "", Lang_CXX, Verifier,
- namespaceDecl(has(usingShadowDecl())));
- }
- TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T> int foo();"
- "template <typename T> void declToImport() {"
- " (void)::foo<T>;"
- " (void)::template foo<T>;"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
- }
- TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " d.t = T();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- binaryOperator(has(cxxUnresolvedConstructExpr())))));
- testImport(
- "template <typename T> struct C { T t; };"
- "template <typename T> void declToImport() {"
- " C<T> d;"
- " (&d)->t = T();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasDescendant(
- binaryOperator(has(cxxUnresolvedConstructExpr())))));
- }
- /// Check that function "declToImport()" (which is the templated function
- /// for corresponding FunctionTemplateDecl) is not added into DeclContext.
- /// Same for class template declarations.
- TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template <typename T> void declToImport() { T a = 1; }"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- functionTemplateDecl(hasAncestor(translationUnitDecl(
- unless(has(functionDecl(hasName("declToImport"))))))));
- testImport(
- "template <typename T> struct declToImport { T t; };"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(hasAncestor(translationUnitDecl(
- unless(has(cxxRecordDecl(hasName("declToImport"))))))));
- }
- TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
- MatchVerifier<Decl> Verifier;
- auto Code =
- R"s(
- struct declToImport {
- template <typename T0> struct X;
- template <typename T0> struct X<T0 *> {};
- };
- )s";
- testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
- recordDecl(has(classTemplateDecl()),
- has(classTemplateSpecializationDecl())));
- }
- TEST_P(ImportExpr, CXXOperatorCallExpr) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "class declToImport {"
- " void f() { *this = declToImport(); }"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
- cxxOperatorCallExpr())))));
- }
- TEST_P(ImportExpr, DependentSizedArrayType) {
- MatchVerifier<Decl> Verifier;
- testImport(
- "template<typename T, int Size> class declToImport {"
- " T data[Size];"
- "};",
- Lang_CXX, "", Lang_CXX, Verifier,
- classTemplateDecl(has(cxxRecordDecl(
- has(fieldDecl(hasType(dependentSizedArrayType())))))));
- }
- TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
- auto From =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
- ASSERT_TRUE(From);
- auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
- ASSERT_TRUE(To);
- Decl *ToTemplated = To->getTemplatedDecl();
- Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
- EXPECT_TRUE(ToTemplated1);
- EXPECT_EQ(ToTemplated1, ToTemplated);
- }
- TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
- auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
- FromTU, functionTemplateDecl());
- ASSERT_TRUE(From);
- auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
- ASSERT_TRUE(To);
- Decl *ToTemplated = To->getTemplatedDecl();
- Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
- EXPECT_TRUE(ToTemplated1);
- EXPECT_EQ(ToTemplated1, ToTemplated);
- }
- TEST_P(ASTImporterTestBase,
- ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
- auto FromFT =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
- ASSERT_TRUE(FromFT);
- auto ToTemplated =
- cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated);
- auto ToTU = ToTemplated->getTranslationUnitDecl();
- auto ToFT =
- FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
- EXPECT_TRUE(ToFT);
- }
- TEST_P(ASTImporterTestBase,
- DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
- Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
- auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
- FromTU, functionTemplateDecl());
- ASSERT_TRUE(FromFT);
- auto ToTemplated =
- cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated);
- auto ToTU = ToTemplated->getTranslationUnitDecl();
- auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl());
- EXPECT_TRUE(ToFT);
- }
- TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
- auto Code =
- R"(
- namespace x {
- template<class X> struct S1{};
- template<class X> struct S2{};
- template<class X> struct S3{};
- }
- )";
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- auto FromNs =
- FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
- auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
- ASSERT_TRUE(ToNs);
- auto From =
- FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
- classTemplateDecl(
- hasName("S2")));
- auto To =
- FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
- classTemplateDecl(
- hasName("S2")));
- ASSERT_TRUE(From);
- ASSERT_TRUE(To);
- auto ToTemplated = To->getTemplatedDecl();
- auto ToTemplated1 =
- cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
- EXPECT_TRUE(ToTemplated1);
- ASSERT_EQ(ToTemplated1, ToTemplated);
- }
- TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template <typename T> struct X {};
- void declToImport(int y, X<int> &x) {}
- template <> struct X<int> {
- void g() {
- X<int> x;
- declToImport(0, x);
- }
- };
- )",
- Lang_CXX, "", Lang_CXX);
- MatchVerifier<Decl> Verifier;
- auto Matcher = functionDecl(hasName("declToImport"),
- parameterCountIs(2),
- hasParameter(0, hasName("y")),
- hasParameter(1, hasName("x")),
- hasParameter(1, hasType(asString("X<int> &"))));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
- }
- TEST_P(ASTImporterTestBase,
- TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX);
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
- if (FD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any FunctionDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
- }
- TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("template <typename T> struct declToImport { T t; };"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX, "", Lang_CXX);
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
- if (RD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any CXXRecordDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
- }
- TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl(
- "template <typename T> struct X {};"
- "template <typename T> using declToImport = X<T>;"
- "void instantiate() { declToImport<int> a; }",
- Lang_CXX11, "", Lang_CXX11);
- auto Check = [](Decl *D) -> bool {
- auto TU = D->getTranslationUnitDecl();
- for (auto Child : TU->decls()) {
- if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
- if (AD->getNameAsString() == "declToImport") {
- GTEST_NONFATAL_FAILURE_(
- "TU should not contain any TypeAliasDecl with name declToImport");
- return false;
- }
- }
- }
- return true;
- };
- ASSERT_TRUE(Check(From));
- EXPECT_TRUE(Check(To));
- }
- TEST_P(
- ASTImporterTestBase,
- TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base {};
- class declToImport : public Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
- // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
- auto Pattern =
- translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
- // Check that the ClassTemplateSpecializationDecl is the child of the
- // ClassTemplateDecl.
- Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"), has(classTemplateSpecializationDecl()))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
- }
- AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
- size_t Index = 0;
- for (FieldDecl *Field : Node.fields()) {
- if (Index == Order.size())
- return false;
- if (Field->getName() != Order[Index])
- return false;
- ++Index;
- }
- return Index == Order.size();
- }
- TEST_P(ASTImporterTestBase,
- TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- namespace NS {
- template<class T>
- class X {};
- template class X<int>;
- }
- )",
- Lang_CXX, "", Lang_CXX, "NS");
- // Check that the ClassTemplateSpecializationDecl is NOT the child of the
- // ClassTemplateDecl.
- auto Pattern = namespaceDecl(has(classTemplateDecl(
- hasName("X"), unless(has(classTemplateSpecializationDecl())))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
- // Check that the ClassTemplateSpecializationDecl is the child of the
- // NamespaceDecl.
- Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
- }
- TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl(
- "struct declToImport { int a; int b; };",
- Lang_CXX11, "", Lang_CXX11);
- MatchVerifier<Decl> Verifier;
- ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
- EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
- }
- TEST_P(ASTImporterTestBase,
- DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- // The original recursive algorithm of ASTImporter first imports 'c' then
- // 'b' and lastly 'a'. Therefore we must restore the order somehow.
- R"s(
- struct declToImport {
- int a = c + b;
- int b = 1;
- int c = 2;
- };
- )s",
- Lang_CXX11, "", Lang_CXX11);
- MatchVerifier<Decl> Verifier;
- ASSERT_TRUE(
- Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
- EXPECT_TRUE(
- Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
- }
- TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- struct declToImport {
- };
- )",
- Lang_CXX, "", Lang_CXX);
- MatchVerifier<Decl> Verifier;
- // Match the implicit Decl.
- auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
- }
- TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template <typename U>
- struct declToImport {
- };
- )",
- Lang_CXX, "", Lang_CXX);
- MatchVerifier<Decl> Verifier;
- // Match the implicit Decl.
- auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
- }
- TEST_P(
- ASTImporterTestBase,
- ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base {};
- class declToImport : public Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
- auto hasImplicitClass = has(cxxRecordDecl());
- auto Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"),
- has(classTemplateSpecializationDecl(hasImplicitClass)))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
- }
- TEST_P(ASTImporterTestBase, IDNSOrdinary) {
- Decl *From, *To;
- std::tie(From, To) =
- getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
- MatchVerifier<Decl> Verifier;
- auto Matcher = functionDecl();
- ASSERT_TRUE(Verifier.match(From, Matcher));
- EXPECT_TRUE(Verifier.match(To, Matcher));
- EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
- }
- TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
- Decl *FromTU = getTuDecl(
- R"(
- struct X {};
- void operator<<(int, X);
- )",
- Lang_CXX);
- Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
- const Decl *To = Import(From, Lang_CXX);
- EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
- }
- TEST_P(ASTImporterTestBase,
- ShouldImportMembersOfClassTemplateSpecializationDecl) {
- Decl *From, *To;
- std::tie(From, To) = getImportedDecl(
- R"(
- template<class T>
- class Base { int a; };
- class declToImport : Base<declToImport> {};
- )",
- Lang_CXX, "", Lang_CXX);
- auto Pattern = translationUnitDecl(has(classTemplateDecl(
- hasName("Base"),
- has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
- ASSERT_TRUE(
- MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
- EXPECT_TRUE(
- MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
- }
- TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B;
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("f")));
- Import(FromD, Lang_CXX);
- auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
- auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
- EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
- }
- }
- TEST_P(ASTImporterTestBase,
- ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
- Decl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
- template <typename T>
- struct B;
- )",
- Lang_CXX);
- ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
- [](const ClassTemplateDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateDecl()));
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
- FromTU, classTemplateDecl(hasName("B")));
- Import(FromD, Lang_CXX);
- // We should have only one definition.
- EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
- [](const ClassTemplateDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateDecl()));
- }
- TEST_P(ASTImporterTestBase,
- ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
- Decl *ToTU = getToTuDecl(
- R"(
- struct B {
- void f();
- };
- struct B;
- )",
- Lang_CXX);
- ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(unless(isImplicit()))));
- Decl *FromTU = getTuDecl(
- R"(
- struct B {
- void f();
- };
- )",
- Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("B")));
- Import(FromD, Lang_CXX);
- EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
- ToTU, cxxRecordDecl(unless(isImplicit()))));
- }
- static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
- EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
- EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
- EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
- EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
- }
- static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
- SourceManager &SM1, SourceManager &SM2) {
- CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
- FullSourceLoc{ Range2.getBegin(), SM2 });
- CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
- FullSourceLoc{ Range2.getEnd(), SM2 });
- }
- TEST_P(ASTImporterTestBase, ImportSourceLocs) {
- Decl *FromTU = getTuDecl(
- R"(
- #define MFOO(arg) arg = arg + 1
- void foo() {
- int a = 5;
- MFOO(a);
- }
- )",
- Lang_CXX);
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- auto ToD = Import(FromD, Lang_CXX);
- auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
- auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
- auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
- auto FromRHS =
- LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
- SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
- SourceManager &FromSM = FromD->getASTContext().getSourceManager();
- CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
- FromSM);
- CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
- FromSM);
- CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
- FromSM);
- }
- TEST_P(ASTImporterTestBase, ImportNestedMacro) {
- Decl *FromTU = getTuDecl(
- R"(
- #define FUNC_INT void declToImport
- #define FUNC FUNC_INT
- FUNC(int a);
- )",
- Lang_CXX);
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- auto ToD = Import(FromD, Lang_CXX);
- SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
- SourceManager &FromSM = FromD->getASTContext().getSourceManager();
- CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
- FromSM);
- }
- TEST_P(
- ASTImporterTestBase,
- ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
- {
- Decl *ToTU = getToTuDecl(
- R"(
- template <typename T>
- struct B;
- template <>
- struct B<int> {};
- template <>
- struct B<int>;
- )",
- Lang_CXX);
- // We should have only one definition.
- ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
- [](const ClassTemplateSpecializationDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateSpecializationDecl()));
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T>
- struct B;
- template <>
- struct B<int> {};
- )",
- Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- FromTU, classTemplateSpecializationDecl(hasName("B")));
- Import(FromD, Lang_CXX);
- // We should have only one definition.
- EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
- [](const ClassTemplateSpecializationDecl *T) {
- return T->isThisDeclarationADefinition();
- })
- .match(ToTU, classTemplateSpecializationDecl()));
- }
- TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
- Decl *FromTU = getTuDecl(
- R"(
- struct { int a; int b; } object0 = { 2, 3 };
- struct { int x; int y; int z; } object1;
- )",
- Lang_CXX, "input0.cc");
- auto getRecordDecl = [](VarDecl *VD) {
- auto *ET = cast<ElaboratedType>(VD->getType().getTypePtr());
- return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
- };
- auto *Obj0 =
- FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
- auto *From0 = getRecordDecl(Obj0);
- auto *Obj1 =
- FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
- auto *From1 = getRecordDecl(Obj1);
- auto *To0 = Import(From0, Lang_CXX);
- auto *To1 = Import(From1, Lang_CXX);
- EXPECT_TRUE(To0);
- EXPECT_TRUE(To1);
- EXPECT_NE(To0, To1);
- EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
- }
- TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) {
- auto Pattern = varDecl(hasName("x"));
- VarDecl *Imported1;
- {
- Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
- }
- VarDecl *Imported2;
- {
- Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
- }
- EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
- EXPECT_FALSE(Imported2->isUsed(false));
- {
- Decl *FromTU =
- getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
- auto *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- Import(FromD, Lang_CXX);
- }
- EXPECT_TRUE(Imported2->isUsed(false));
- }
- TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) {
- auto Pattern = varDecl(hasName("x"));
- Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
- auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
- ASSERT_FALSE(Imported1->isUsed(false));
- FromD->setIsUsed();
- auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
- EXPECT_EQ(Imported1, Imported2);
- EXPECT_TRUE(Imported2->isUsed(false));
- }
- struct ImportFunctions : ASTImporterTestBase {};
- TEST_P(ImportFunctions,
- DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
- Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- FunctionDecl *FromD = // Definition
- LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
- }
- TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
- Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Decl *ImportedD = Import(FromD, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
- }
- TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
- Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *From =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
- Decl *ImportedD = Import(From, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
- Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
- auto Pattern = functionDecl(hasName("f"));
- auto *From =
- LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
- Decl *ImportedD = Import(From, Lang_CXX);
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctions, ImportPrototypes) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctions, ImportDefinitions) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- }
- TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
- auto Pattern = functionDecl(hasName("f"));
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
- FunctionDecl *FromD =
- FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
- FunctionDecl *DefinitionD =
- LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
- EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
- }
- TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
- auto Pattern = functionDecl(hasName("f"));
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
- FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
- FunctionDecl *DefinitionD =
- LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
- EXPECT_TRUE(DefinitionD->getPreviousDecl());
- EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
- EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
- }
- TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
- auto Code =
- R"(
- struct B { virtual void f(); };
- void B::f() {}
- struct D : B { void f(); };
- )";
- auto Pattern =
- cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- CXXMethodDecl *Proto =
- FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
- ASSERT_EQ(Proto->size_overridden_methods(), 1u);
- CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
- EXPECT_EQ(To->size_overridden_methods(), 1u);
- }
- TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
- auto Code =
- R"(
- struct B { virtual void f(); };
- void B::f() {}
- )";
- auto Pattern =
- cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
- Decl *FromTU = getTuDecl(Code, Lang_CXX);
- CXXMethodDecl *Proto =
- FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
- CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
- ASSERT_TRUE(Proto->isVirtual());
- ASSERT_TRUE(Def->isVirtual());
- CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
- EXPECT_TRUE(To->isVirtual());
- }
- TEST_P(ImportFunctions,
- ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
- Decl *ToTU = getToTuDecl(
- R"(
- void f() {}
- void f();
- )",
- Lang_CXX);
- ASSERT_EQ(1u,
- DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
- return FD->doesThisDeclarationHaveABody();
- }).match(ToTU, functionDecl()));
- Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
- Import(FromD, Lang_CXX);
- EXPECT_EQ(1u,
- DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
- return FD->doesThisDeclarationHaveABody();
- }).match(ToTU, functionDecl()));
- }
- struct ImportFriendFunctions : ImportFunctions {};
- TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl("struct X { friend void f(); };"
- "void f();",
- Lang_CXX,
- "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
- }
- TEST_P(ImportFriendFunctions,
- ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl("void f();"
- "struct X { friend void f(); };",
- Lang_CXX, "input0.cc");
- auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
- }
- TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
- "void f();",
- Lang_CXX,
- "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
- }
- TEST_P(ImportFriendFunctions,
- ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl("struct X { friend void f(); };"
- "void f(){}",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
- }
- // Disabled temporarily, because the new structural equivalence check
- // (https://reviews.llvm.org/D48628) breaks it.
- // PreviousDecl is not set because there is no structural match.
- // FIXME Enable!
- TEST_P(ImportFriendFunctions,
- DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl(
- R"(
- class X;
- void f(X *x){}
- class X{
- friend void f(X *x);
- };
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
- .match(ToTU, friendDecl())
- ->getFriendDecl());
- EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
- // The parameters must refer the same type
- EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
- (*ImportedD->param_begin())->getOriginalType());
- }
- // Disabled temporarily, because the new structural equivalence check
- // (https://reviews.llvm.org/D48628) breaks it.
- // PreviousDecl is not set because there is no structural match.
- // FIXME Enable!
- TEST_P(ImportFriendFunctions,
- DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
- auto Pattern = functionDecl(hasName("f"));
- Decl *FromTU = getTuDecl(
- R"(
- class X;
- void f(X *x){}
- class X{
- friend void f(X *x);
- };
- )",
- Lang_CXX, "input0.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
- auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
- ToTU, functionDecl(unless(hasParent(friendDecl()))));
- EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
- EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
- // The parameters must refer the same type
- EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
- (*ImportedD->param_begin())->getOriginalType());
- }
- TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
- auto Pattern = functionDecl(hasName("f"));
- FunctionDecl *ImportedD;
- {
- Decl *FromTU =
- getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- }
- FunctionDecl *ImportedD1;
- {
- Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
- }
- Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
- EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
- EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
- }
- AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
- InnerMatcher) {
- if (auto *Typedef = Node.getTypedefNameForAnonDecl())
- return InnerMatcher.matches(*Typedef, Finder, Builder);
- return false;
- }
- TEST_P(ImportDecl, ImportEnumSequential) {
- CodeFiles Samples{{"main.c",
- {"void foo();"
- "void moo();"
- "int main() { foo(); moo(); }",
- Lang_C}},
- {"foo.c",
- {"typedef enum { THING_VALUE } thing_t;"
- "void conflict(thing_t type);"
- "void foo() { (void)THING_VALUE; }"
- "void conflict(thing_t type) {}",
- Lang_C}},
- {"moo.c",
- {"typedef enum { THING_VALUE } thing_t;"
- "void conflict(thing_t type);"
- "void moo() { conflict(THING_VALUE); }",
- Lang_C}}};
- auto VerificationMatcher =
- enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
- hasTypedefForAnonDecl(hasName("thing_t")));
- ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
- ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
- testImportSequence(
- Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
- // Just check that there is only one enum decl in the result AST.
- "main.c", enumDecl(), VerificationMatcher);
- // For different import order, result should be the same.
- testImportSequence(
- Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
- // Check that there is only one enum decl in the result AST.
- "main.c", enumDecl(), VerificationMatcher);
- }
- const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
- dependentScopeDeclRefExpr;
- TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("template <typename T> struct S { static T foo; };"
- "template <typename T> void declToImport() {"
- " (void) S<T>::foo;"
- "}"
- "void instantiate() { declToImport<int>(); }"
- "template <typename T> T S<T>::foo;",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
- testImport("template <typename T> struct S {"
- "template<typename S> static void foo(){};"
- "};"
- "template <typename T> void declToImport() {"
- " S<T>::template foo<T>();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(compoundStmt(
- has(callExpr(has(dependentScopeDeclRefExpr())))))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
- dependentNameType;
- TEST_P(ImportExpr, DependentNameType) {
- MatchVerifier<Decl> Verifier;
- testImport("template <typename T> struct declToImport {"
- " typedef typename T::type dependent_name;"
- "};",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- classTemplateDecl(has(
- cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
- }
- const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
- unresolvedMemberExpr;
- TEST_P(ImportExpr, UnresolvedMemberExpr) {
- MatchVerifier<Decl> Verifier;
- testImport("struct S { template <typename T> void mem(); };"
- "template <typename U> void declToImport() {"
- " S s;"
- " s.mem<U>();"
- "}"
- "void instantiate() { declToImport<int>(); }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionTemplateDecl(has(functionDecl(has(
- compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
- }
- TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
- Decl *ToR1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { };", Lang_CXX, "input0.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR1 = Import(FromR, Lang_CXX);
- }
- Decl *ToR2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { };", Lang_CXX, "input1.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR2 = Import(FromR, Lang_CXX);
- }
-
- EXPECT_EQ(ToR1, ToR2);
- }
- TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
- Decl *ToR1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR1 = Import(FromR, Lang_CXX);
- }
- Decl *ToR2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { unsigned x; };", Lang_CXX, "input1.cc");
- auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
- FromTU, cxxRecordDecl(hasName("A")));
- ToR2 = Import(FromR, Lang_CXX);
- }
- EXPECT_NE(ToR1, ToR2);
- }
- TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
- Decl *ToF1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF1 = Import(FromF, Lang_CXX);
- }
- Decl *ToF2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input1.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF2 = Import(FromF, Lang_CXX);
- }
- EXPECT_EQ(ToF1, ToF2);
- }
- TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
- Decl *ToF1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { int x; };", Lang_CXX, "input0.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF1 = Import(FromF, Lang_CXX);
- }
- Decl *ToF2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { unsigned x; };", Lang_CXX, "input1.cc");
- auto *FromF = FirstDeclMatcher<FieldDecl>().match(
- FromTU, fieldDecl(hasName("x")));
- ToF2 = Import(FromF, Lang_CXX);
- }
- EXPECT_NE(ToF1, ToF2);
- }
- TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
- Decl *ToM1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM1 = Import(FromM, Lang_CXX);
- }
- Decl *ToM2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM2 = Import(FromM, Lang_CXX);
- }
- EXPECT_EQ(ToM1, ToM2);
- }
- TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
- Decl *ToM1;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x(); }; void A::x() { }",
- Lang_CXX, "input0.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM1 = Import(FromM, Lang_CXX);
- }
- Decl *ToM2;
- {
- Decl *FromTU = getTuDecl(
- "struct A { void x() const; }; void A::x() const { }",
- Lang_CXX, "input1.cc");
- auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("x"), isDefinition()));
- ToM2 = Import(FromM, Lang_CXX);
- }
- EXPECT_NE(ToM1, ToM2);
- }
- struct DeclContextTest : ASTImporterTestBase {};
- TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
- Decl *TU = getTuDecl(
- R"(
- namespace NS {
- template <typename T>
- struct S {};
- template struct S<int>;
- inline namespace INS {
- template <typename T>
- struct S {};
- template struct S<int>;
- }
- }
- )", Lang_CXX11, "input0.cc");
- auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
- TU, namespaceDecl());
- auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
- TU, classTemplateSpecializationDecl());
- ASSERT_TRUE(NS->containsDecl(Spec));
- NS->removeDecl(Spec);
- EXPECT_FALSE(NS->containsDecl(Spec));
- }
- struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
- TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldNotContainFunctionTemplateImplicitInstantiation) {
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- void foo() { f<int>(); }
- )",
- Lang_CXX, "input0.cc");
- // Check that the function template instantiation is NOT the child of the TU.
- auto Pattern = translationUnitDecl(
- unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
- auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("foo")));
- ASSERT_TRUE(Import(Foo, Lang_CXX));
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
- }
- TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldNotContainFunctionTemplateExplicitInstantiation) {
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template int f<int>();
- )",
- Lang_CXX, "input0.cc");
- // Check that the function template instantiation is NOT the child of the TU.
- auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
- auto Pattern = translationUnitDecl(unless(has(Instantiation)));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
- ASSERT_TRUE(
- Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
- }
- TEST_P(ImportFunctionTemplateSpecializations,
- TUshouldContainFunctionTemplateSpecialization) {
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template <> int f<int>() { return 4; }
- )",
- Lang_CXX, "input0.cc");
- // Check that the function template specialization is the child of the TU.
- auto Specialization =
- functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Pattern = translationUnitDecl(has(Specialization));
- ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
- ASSERT_TRUE(
- Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
- }
- TEST_P(ImportFunctionTemplateSpecializations,
- FunctionTemplateSpecializationRedeclChain) {
- Decl *FromTU = getTuDecl(
- R"(
- template<class T>
- int f() { return 0; }
- template <> int f<int>() { return 4; }
- )",
- Lang_CXX, "input0.cc");
- auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
- hasParent(translationUnitDecl()));
- auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
- {
- auto *TU = FromTU;
- auto *SpecD = FromSpecD;
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- TU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- ASSERT_EQ(SpecD, FirstSpecD);
- ASSERT_TRUE(SpecD->getPreviousDecl());
- ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
- ->doesThisDeclarationHaveABody());
- }
- ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
- {
- auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
- auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- TU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- EXPECT_EQ(SpecD, FirstSpecD);
- ASSERT_TRUE(SpecD->getPreviousDecl());
- EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
- ->doesThisDeclarationHaveABody());
- }
- }
- TEST_P(ImportFunctionTemplateSpecializations,
- MatchNumberOfFunctionTemplateSpecializations) {
- Decl *FromTU = getTuDecl(
- R"(
- template <typename T> constexpr int f() { return 0; }
- template <> constexpr int f<int>() { return 4; }
- void foo() {
- static_assert(f<char>() == 0, "");
- static_assert(f<int>() == 4, "");
- }
- )",
- Lang_CXX11, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
- FromTU, functionDecl(hasName("foo")));
- Import(FromD, Lang_CXX11);
- auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
- EXPECT_EQ(
- DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
- DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
- }
- TEST_P(ImportFunctionTemplateSpecializations,
- ImportPrototypes) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Proto of the specialization.
- template <>
- void f<int>();
- )";
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
- auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- // Check that they are part of the same redecl chain.
- EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
- }
- TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization and definition.
- template <>
- void f<int>() {}
- )";
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
- ToTU, functionTemplateDecl());
- auto *FirstSpecD = *(TemplateD->spec_begin());
- EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
- }
- TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization proto.
- template <>
- void f<int>();
- // Specialization proto.
- template <>
- void f<int>();
- )";
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization proto.
- template <>
- void f<int>();
- // Specialization definition.
- template <>
- void f<int>() {}
- )";
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
- EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
- auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
- auto Code =
- R"(
- // Proto of the primary template.
- template <class T>
- void f();
- // Specialization definition.
- template <>
- void f<int>() {}
- // Specialization proto.
- template <>
- void f<int>();
- )";
- Decl *ImportedD;
- {
- Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
- auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
- ImportedD = Import(FromD, Lang_CXX);
- }
- Decl *ToTU = ImportedD->getTranslationUnitDecl();
- EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
- auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
- EXPECT_TRUE(ImportedD == To0);
- EXPECT_TRUE(ImportedD != To1);
- EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
- EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
- EXPECT_EQ(To1->getPreviousDecl(), To0);
- }
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
- ::testing::Values(ArgVector()), );
- INSTANTIATE_TEST_CASE_P(
- ParameterizedTests, CanonicalRedeclChain,
- ::testing::Values(ArgVector()),);
- auto DefaultTestValuesForRunOptions = ::testing::Values(
- ArgVector(),
- ArgVector{"-fdelayed-template-parsing"},
- ArgVector{"-fms-compatibility"},
- ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
- DefaultTestValuesForRunOptions, );
- INSTANTIATE_TEST_CASE_P(ParameterizedTests,
- ImportFunctionTemplateSpecializations,
- DefaultTestValuesForRunOptions, );
- } // end namespace ast_matchers
- } // end namespace clang
|