Index: lib/AST/ASTDumper.cpp =================================================================== --- lib/AST/ASTDumper.cpp +++ lib/AST/ASTDumper.cpp @@ -1184,6 +1184,28 @@ 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()); } Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -319,6 +319,9 @@ bool ImportArrayChecked(const InContainerTy &InContainer, OIter Obegin) { return ImportArrayChecked(InContainer.begin(), InContainer.end(), Obegin); } + + // Importing overrides. + void ImportOverrides(CXXMethodDecl *Method); }; } @@ -2025,6 +2028,9 @@ // Add this function to the lexical context. LexicalDC->addDeclInternal(ToFunction); + if (auto *FromCXXMethod = dyn_cast(D)) + ImportOverrides(FromCXXMethod); + return ToFunction; } @@ -5499,6 +5505,16 @@ Replacement); } +void ASTNodeImporter::ImportOverrides(CXXMethodDecl *FromMethod) { + auto *ToMethod = + cast(Importer.GetAlreadyImportedOrNull(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) Index: test/Import/import-method-overrides/Inputs/S.cpp =================================================================== --- /dev/null +++ test/Import/import-method-overrides/Inputs/S.cpp @@ -0,0 +1,7 @@ +struct Base { + virtual void foo() {} +}; + +struct Derived : public Base { + void foo() override {} +}; Index: test/Import/import-method-overrides/test.cpp =================================================================== --- /dev/null +++ test/Import/import-method-overrides/test.cpp @@ -0,0 +1,8 @@ +// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s + +// CHECK: CXXRecordDecl{{.*}}Derived +// CHECK: CXXMethodDecl{{.*}}foo +// CHECK-NEXT: Overrides: [ {{.*}} Base::foo {{.*}} ] +void expr(struct Derived *D) { + D->foo(); +} Index: tools/clang-import-test/clang-import-test.cpp =================================================================== --- tools/clang-import-test/clang-import-test.cpp +++ 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 @@ 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 @@ } llvm::Error ParseSource(const std::string &Path, CompilerInstance &CI, - CodeGenerator &CG) { + ASTConsumer &Consumer) { SourceManager &SM = CI.getSourceManager(); const FileEntry *FE = CI.getFileManager().getFile(Path); if (!FE) { @@ -241,13 +247,14 @@ llvm::Twine("Couldn't open ", Path), std::error_code()); } SM.setMainFileID(SM.createFileID(FE, SourceLocation(), SrcMgr::C_User)); - ParseAST(CI.getPreprocessor(), &CG, CI.getASTContext()); + ParseAST(CI.getPreprocessor(), &Consumer, CI.getASTContext()); return llvm::Error::success(); } llvm::Expected> Parse(const std::string &Path, - llvm::ArrayRef> Imports) { + llvm::ArrayRef> Imports, + bool IsExpression) { 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 @@ 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 (IsExpression && DumpAST) + 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 @@ 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 @@ } } llvm::Expected> ExpressionCI = - Parse(Expression, Direct ? ImportCIs : IndirectCIs); + Parse(Expression, Direct ? ImportCIs : IndirectCIs, true); if (auto E = ExpressionCI.takeError()) { llvm::errs() << llvm::toString(std::move(E)); exit(-1);