From 19e07e1390da8a5b96bdefc8daf854b2daf84e2a Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Tue, 20 Jun 2017 21:06:00 +0000 Subject: [PATCH] Preserve CXX method overrides in ASTImporter Summary: The ASTImporter should import CXX method overrides from the source context when it imports a method decl. Reviewers: spyffe, rsmith, doug.gregor Reviewed By: spyffe Differential Revision: https://reviews.llvm.org/D34371 llvm-svn: 305850 --- clang/lib/AST/ASTDumper.cpp | 22 +++++++++++++ clang/lib/AST/ASTImporter.cpp | 14 ++++++++ .../clang-import-test/clang-import-test.cpp | 32 +++++++++++++------ 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index d89be0d9e6fa4..95a02deb33eb0 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -1184,6 +1184,28 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { I != E; ++I) dumpCXXCtorInitializer(*I); + if (const CXXMethodDecl *MD = dyn_cast(D)) + if (MD->size_overridden_methods() != 0) { + auto dumpOverride = + [=](const CXXMethodDecl *D) { + SplitQualType T_split = D->getType().split(); + OS << D << " " << D->getParent()->getName() << "::" + << D->getName() << " '" + << QualType::getAsString(T_split) << "'"; + }; + + dumpChild([=] { + auto FirstOverrideItr = MD->begin_overridden_methods(); + OS << "Overrides: [ "; + dumpOverride(*FirstOverrideItr); + for (const auto *Override : + llvm::make_range(FirstOverrideItr + 1, + MD->end_overridden_methods())) + dumpOverride(Override); + OS << " ]"; + }); + } + if (D->doesThisDeclarationHaveABody()) dumpStmt(D->getBody()); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 493cb6df8b83b..6e33b98d2f18c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -319,6 +319,9 @@ namespace clang { bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } + + // Importing overrides. + void ImportOverrides(CXXMethodDecl *ToMethod, CXXMethodDecl *FromMethod); }; } @@ -2025,6 +2028,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Add this function to the lexical context. LexicalDC->addDeclInternal(ToFunction); + if (auto *FromCXXMethod = dyn_cast(D)) + ImportOverrides(cast(ToFunction), FromCXXMethod); + return ToFunction; } @@ -5499,6 +5505,14 @@ Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr( Replacement); } +void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod, + CXXMethodDecl *FromMethod) { + for (auto *FromOverriddenMethod : FromMethod->overridden_methods()) + ToMethod->addOverriddenMethod( + cast(Importer.Import(const_cast( + FromOverriddenMethod)))); +} + ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager, ASTContext &FromContext, FileManager &FromFileManager, bool MinimalImport) diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index 567a4bb4f0a26..db4dc76eded54 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -17,7 +17,9 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" @@ -51,6 +53,10 @@ static llvm::cl::list llvm::cl::desc("Argument to pass to the CompilerInvocation"), llvm::cl::CommaSeparated); +static llvm::cl::opt +DumpAST("dump-ast", llvm::cl::init(false), + llvm::cl::desc("Dump combined AST")); + namespace init_convenience { class TestDiagnosticConsumer : public DiagnosticConsumer { private: @@ -233,7 +239,7 @@ std::unique_ptr BuildIndirect(std::unique_ptr> Parse(const std::string &Path, - llvm::ArrayRef> Imports) { + llvm::ArrayRef> Imports, + bool ShouldDumpAST) { std::vector ClangArgv(ClangArgs.size()); std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(), [](const std::string &s) -> const char * { return s.data(); }); @@ -261,14 +268,20 @@ Parse(const std::string &Path, if (Imports.size()) AddExternalSource(*CI, Imports); + std::vector> ASTConsumers; + auto LLVMCtx = llvm::make_unique(); - std::unique_ptr CG = - init_convenience::BuildCodeGen(*CI, *LLVMCtx); - CG->Initialize(CI->getASTContext()); + ASTConsumers.push_back(init_convenience::BuildCodeGen(*CI, *LLVMCtx)); + + if (ShouldDumpAST) + ASTConsumers.push_back(CreateASTDumper("", true, false, false)); CI->getDiagnosticClient().BeginSourceFile(CI->getLangOpts(), &CI->getPreprocessor()); - if (llvm::Error PE = ParseSource(Path, *CI, *CG)) { + MultiplexConsumer Consumers(std::move(ASTConsumers)); + Consumers.Initialize(CI->getASTContext()); + + if (llvm::Error PE = ParseSource(Path, *CI, Consumers)) { return std::move(PE); } CI->getDiagnosticClient().EndSourceFile(); @@ -288,7 +301,8 @@ int main(int argc, const char **argv) { llvm::cl::ParseCommandLineOptions(argc, argv); std::vector> ImportCIs; for (auto I : Imports) { - llvm::Expected> ImportCI = Parse(I, {}); + llvm::Expected> ImportCI = + Parse(I, {}, false); if (auto E = ImportCI.takeError()) { llvm::errs() << llvm::toString(std::move(E)); exit(-1); @@ -310,7 +324,7 @@ int main(int argc, const char **argv) { } } llvm::Expected> ExpressionCI = - Parse(Expression, Direct ? ImportCIs : IndirectCIs); + Parse(Expression, Direct ? ImportCIs : IndirectCIs, DumpAST); if (auto E = ExpressionCI.takeError()) { llvm::errs() << llvm::toString(std::move(E)); exit(-1);