Skip to content

Commit

Permalink
Preserve CXX method overrides in ASTImporter
Browse files Browse the repository at this point in the history
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
  • Loading branch information
lhames committed Jun 20, 2017
1 parent 30cf2e8 commit 19e07e1
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
22 changes: 22 additions & 0 deletions clang/lib/AST/ASTDumper.cpp
Expand Up @@ -1184,6 +1184,28 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
I != E; ++I)
dumpCXXCtorInitializer(*I);

if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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());
}
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/AST/ASTImporter.cpp
Expand Up @@ -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);
};
}

Expand Down Expand Up @@ -2025,6 +2028,9 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
// Add this function to the lexical context.
LexicalDC->addDeclInternal(ToFunction);

if (auto *FromCXXMethod = dyn_cast<CXXMethodDecl>(D))
ImportOverrides(cast<CXXMethodDecl>(ToFunction), FromCXXMethod);

return ToFunction;
}

Expand Down Expand Up @@ -5499,6 +5505,14 @@ Expr *ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
Replacement);
}

void ASTNodeImporter::ImportOverrides(CXXMethodDecl *ToMethod,
CXXMethodDecl *FromMethod) {
for (auto *FromOverriddenMethod : FromMethod->overridden_methods())
ToMethod->addOverriddenMethod(
cast<CXXMethodDecl>(Importer.Import(const_cast<CXXMethodDecl*>(
FromOverriddenMethod))));
}

ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
ASTContext &FromContext, FileManager &FromFileManager,
bool MinimalImport)
Expand Down
32 changes: 23 additions & 9 deletions clang/tools/clang-import-test/clang-import-test.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -51,6 +53,10 @@ static llvm::cl::list<std::string>
llvm::cl::desc("Argument to pass to the CompilerInvocation"),
llvm::cl::CommaSeparated);

static llvm::cl::opt<bool>
DumpAST("dump-ast", llvm::cl::init(false),
llvm::cl::desc("Dump combined AST"));

namespace init_convenience {
class TestDiagnosticConsumer : public DiagnosticConsumer {
private:
Expand Down Expand Up @@ -233,21 +239,22 @@ std::unique_ptr<CompilerInstance> BuildIndirect(std::unique_ptr<CompilerInstance
}

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) {
return llvm::make_error<llvm::StringError>(
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<std::unique_ptr<CompilerInstance>>
Parse(const std::string &Path,
llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports) {
llvm::ArrayRef<std::unique_ptr<CompilerInstance>> Imports,
bool ShouldDumpAST) {
std::vector<const char *> ClangArgv(ClangArgs.size());
std::transform(ClangArgs.begin(), ClangArgs.end(), ClangArgv.begin(),
[](const std::string &s) -> const char * { return s.data(); });
Expand All @@ -261,14 +268,20 @@ Parse(const std::string &Path,
if (Imports.size())
AddExternalSource(*CI, Imports);

std::vector<std::unique_ptr<ASTConsumer>> ASTConsumers;

auto LLVMCtx = llvm::make_unique<llvm::LLVMContext>();
std::unique_ptr<CodeGenerator> 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();
Expand All @@ -288,7 +301,8 @@ int main(int argc, const char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv);
std::vector<std::unique_ptr<CompilerInstance>> ImportCIs;
for (auto I : Imports) {
llvm::Expected<std::unique_ptr<CompilerInstance>> ImportCI = Parse(I, {});
llvm::Expected<std::unique_ptr<CompilerInstance>> ImportCI =
Parse(I, {}, false);
if (auto E = ImportCI.takeError()) {
llvm::errs() << llvm::toString(std::move(E));
exit(-1);
Expand All @@ -310,7 +324,7 @@ int main(int argc, const char **argv) {
}
}
llvm::Expected<std::unique_ptr<CompilerInstance>> 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);
Expand Down

0 comments on commit 19e07e1

Please sign in to comment.