Index: unittests/AST/ASTImporterFixtures.h =================================================================== --- unittests/AST/ASTImporterFixtures.h +++ unittests/AST/ASTImporterFixtures.h @@ -42,6 +42,8 @@ void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName, StringRef Code); +void checkImportedSourceLocations(const Decl *FromD, const Decl *ToD); + // 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. Index: unittests/AST/ASTImporterFixtures.cpp =================================================================== --- unittests/AST/ASTImporterFixtures.cpp +++ unittests/AST/ASTImporterFixtures.cpp @@ -18,6 +18,8 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Tooling/Tooling.h" +#include + namespace clang { namespace ast_matchers { @@ -38,6 +40,82 @@ llvm::MemoryBuffer::getMemBuffer(Code)); } +void checkImportedSourceLocations(const Decl *FromD, const Decl *ToD) { + // Check AST dump for matching source locations in From and To AST. + // The first line of the AST dump contains information about the root node and + // some of the SourceLocation info, but certainly not everything. + // Still it is worth to check these. The test can be extended to check the + // whole AST dump but for this to work the ordering of imported Decls must be + // the same which is not the case now. + // The AST dump additionally traverses the AST and can catch certain bugs like + // poorly or not implemented subtrees. + + // Print debug information? + const bool Print = false; + + SmallString<1024> ToPrinted; + SmallString<1024> FromPrinted; + llvm::raw_svector_ostream ToStream(ToPrinted); + llvm::raw_svector_ostream FromStream(FromPrinted); + + ToD->dump(ToStream); + FromD->dump(FromStream); + + // search for SourceLocation strings: + // :: + // or + // line:: + // or + // col: + // or + // '' + // If a component (filename or line) is same as in the last location + // it is not printed. + // Filename component is grouped into sub-expression to make it extractable. + std::regex MatchSourceLoc( + "|((\\w|\\.)+):\\d+:\\d+|line:\\d+:\\d+|col:\\d+"); + + std::string ToString(ToStream.str()); + std::string FromString(FromStream.str()); + int ToEndl = ToString.find('\n'); + if (ToEndl == std::string::npos) + ToEndl = ToString.size(); + int FromEndl = FromString.find('\n'); + if (FromEndl == std::string::npos) + FromEndl = FromString.size(); + auto ToLoc = std::sregex_iterator(ToString.begin(), ToString.begin() + ToEndl, + MatchSourceLoc); + auto FromLoc = std::sregex_iterator( + FromString.begin(), FromString.begin() + FromEndl, MatchSourceLoc); + if (Print) { + llvm::errs() << ToString << "\n\n\n" << FromString << "\n"; + llvm::errs() << "----\n"; + } + if (ToLoc->size() > 1 && FromLoc->size() > 1 && (*ToLoc)[1] != (*FromLoc)[1]) + // Different filenames in To and From. + // This should mean that a to-be-imported decl was mapped to an existing + // (these normally reside in different files) and the check is + // not applicable. + return; + + bool SourceLocationMismatch = false; + while (ToLoc != std::sregex_iterator() && FromLoc != std::sregex_iterator()) { + if (Print) + llvm::errs() << ToLoc->str() << "|" << FromLoc->str() << "\n"; + SourceLocationMismatch = + SourceLocationMismatch || (ToLoc->str() != FromLoc->str()); + ++ToLoc; + ++FromLoc; + } + if (Print) + llvm::errs() << "----\n"; + + if (FromLoc != std::sregex_iterator() || ToLoc != std::sregex_iterator()) + SourceLocationMismatch = true; + + EXPECT_FALSE(SourceLocationMismatch); +} + ASTImporterTestBase::TU::TU(StringRef Code, StringRef FileName, ArgVector Args, ImporterConstructor C) : Code(Code), FileName(FileName), @@ -179,7 +257,10 @@ lazyInitToAST(ToLang, "", OutputFileName); TU *FromTU = findFromTU(From); assert(LookupTablePtr); - return FromTU->import(*LookupTablePtr, ToAST.get(), From); + Decl *To = FromTU->import(*LookupTablePtr, ToAST.get(), From); + if (To) + checkImportedSourceLocations(From, To); + return To; } QualType ASTImporterTestBase::ImportType(QualType FromType, Decl *TUDecl, Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -49,9 +49,8 @@ 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); + // Additional SourceLocation checks. + checkImportedSourceLocations(Node, *Imported); } return Imported;