diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTImporter.cpp | 94 | ||||
-rw-r--r-- | lib/Frontend/ASTMerge.cpp | 98 | ||||
-rw-r--r-- | lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 5 |
4 files changed, 194 insertions, 4 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 7668b7ba67..0d1a0dca75 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -30,6 +30,7 @@ namespace { explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) { } using TypeVisitor<ASTNodeImporter, QualType>::Visit; + using DeclVisitor<ASTNodeImporter, Decl *>::Visit; // Importing types QualType VisitBuiltinType(BuiltinType *T); @@ -440,6 +441,13 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { if (!DC) return 0; + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return 0; + } + // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) @@ -455,11 +463,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Try to find a variable in our own ("to") context with the same name and // in the same context as the variable we're importing. - if (!D->isFileVarDecl()) { + if (D->isFileVarDecl()) { VarDecl *MergeWithVar = 0; llvm::SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; - for (DeclContext::lookup_result Lookup = DC->lookup(D->getDeclName()); + for (DeclContext::lookup_result Lookup = DC->lookup(Name); Lookup.first != Lookup.second; ++Lookup.first) { if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) @@ -517,16 +525,22 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { TypeSourceInfo *TInfo = 0; if (TypeSourceInfo *FromTInfo = D->getTypeSourceInfo()) { TInfo = Importer.Import(FromTInfo); +#if 0 + // FIXME: Tolerate failures in translation type source + // information, at least until it is implemented. if (!TInfo) return 0; +#endif } // Create the imported variable. VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass()); + ToVar->setLexicalDeclContext(LexicalDC); Importer.getImportedDecls()[D] = ToVar; - + LexicalDC->addDecl(ToVar); + // Merge the initializer. // FIXME: Can we really import any initializer? Alternatively, we could force // ourselves to import every declaration of a variable and then only use @@ -542,7 +556,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ASTImporter::ASTImporter(ASTContext &ToContext, Diagnostic &ToDiags, ASTContext &FromContext, Diagnostic &FromDiags) : ToContext(ToContext), FromContext(FromContext), - ToDiags(ToDiags), FromDiags(FromDiags) { } + ToDiags(ToDiags), FromDiags(FromDiags) { + ImportedDecls[FromContext.getTranslationUnitDecl()] + = ToContext.getTranslationUnitDecl(); +} + +ASTImporter::~ASTImporter() { } QualType ASTImporter::Import(QualType FromT) { if (FromT.isNull()) @@ -566,6 +585,73 @@ QualType ASTImporter::Import(QualType FromT) { return ToContext.getQualifiedType(ToT, FromT.getQualifiers()); } +TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { + // FIXME: Implement! + return 0; +} + +Decl *ASTImporter::Import(Decl *FromD) { + if (!FromD) + return 0; + + // Check whether we've already imported this declaration. + llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); + if (Pos != ImportedDecls.end()) + return Pos->second; + + // Import the type + ASTNodeImporter Importer(*this); + Decl *ToD = Importer.Visit(FromD); + if (!ToD) + return 0; + + // Record the imported declaration. + ImportedDecls[FromD] = ToD; + return ToD; +} + +DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { + if (!FromDC) + return FromDC; + + return cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); +} + +Expr *ASTImporter::Import(Expr *FromE) { + if (!FromE) + return 0; + + return cast_or_null<Expr>(Import(cast<Stmt>(FromE))); +} + +Stmt *ASTImporter::Import(Stmt *FromS) { + if (!FromS) + return 0; + + // FIXME: Implement! + return 0; +} + +NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { + if (!FromNNS) + return 0; + + // FIXME: Implement! + return 0; +} + +SourceLocation ASTImporter::Import(SourceLocation FromLoc) { + if (FromLoc.isInvalid()) + return SourceLocation(); + + // FIXME: Implement! + return SourceLocation(); +} + +SourceRange ASTImporter::Import(SourceRange FromRange) { + return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd())); +} + DeclarationName ASTImporter::Import(DeclarationName FromName) { if (!FromName) return DeclarationName(); diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp new file mode 100644 index 0000000000..649af9e4b8 --- /dev/null +++ b/lib/Frontend/ASTMerge.cpp @@ -0,0 +1,98 @@ +//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTImporter.h" + +using namespace clang; + +ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) { + return AdaptedAction->CreateASTConsumer(CI, InFile); +} + +bool ASTMergeAction::BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename) { + // FIXME: This is a hack. We need a better way to communicate the + // AST file, compiler instance, and file name than member variables + // of FrontendAction. + AdaptedAction->setCurrentFile(getCurrentFile(), takeCurrentASTUnit()); + AdaptedAction->setCompilerInstance(&CI); + return AdaptedAction->BeginSourceFileAction(CI, Filename); +} + +void ASTMergeAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + + for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { + ASTUnit *Unit = ASTUnit::LoadFromPCHFile(ASTFiles[I], CI.getDiagnostics(), + false, true); + if (!Unit) + continue; + + ASTImporter Importer(CI.getASTContext(), CI.getDiagnostics(), + Unit->getASTContext(), CI.getDiagnostics()); + + TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); + for (DeclContext::decl_iterator D = TU->decls_begin(), + DEnd = TU->decls_end(); + D != DEnd; ++D) { + // FIXME: We only merge variables whose names start with x. Why + // would anyone want anything else? + if (VarDecl *VD = dyn_cast<VarDecl>(*D)) + if (VD->getIdentifier() && + *VD->getIdentifier()->getNameStart() == 'x') { + Decl *Merged = Importer.Import(VD); + if (Merged) + Merged->dump(); + } + } + + delete Unit; + } + + + return AdaptedAction->ExecuteAction(); +} + +void ASTMergeAction::EndSourceFileAction() { + return AdaptedAction->EndSourceFileAction(); +} + +ASTMergeAction::ASTMergeAction(FrontendAction *AdaptedAction, + std::string *ASTFiles, unsigned NumASTFiles) + : AdaptedAction(AdaptedAction), ASTFiles(ASTFiles, ASTFiles + NumASTFiles) { + assert(AdaptedAction && "ASTMergeAction needs an action to adapt"); +} + +ASTMergeAction::~ASTMergeAction() { + delete AdaptedAction; +} + +bool ASTMergeAction::usesPreprocessorOnly() const { + return AdaptedAction->usesPreprocessorOnly(); +} + +bool ASTMergeAction::usesCompleteTranslationUnit() { + return AdaptedAction->usesCompleteTranslationUnit(); +} + +bool ASTMergeAction::hasPCHSupport() const { + return AdaptedAction->hasPCHSupport(); +} + +bool ASTMergeAction::hasASTSupport() const { + return AdaptedAction->hasASTSupport(); +} + +bool ASTMergeAction::hasCodeCompletionSupport() const { + return AdaptedAction->hasCodeCompletionSupport(); +} diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 58aaa43aab..1d0b5c1204 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_NO_RTTI 1) add_clang_library(clangFrontend ASTConsumers.cpp + ASTMerge.cpp ASTUnit.cpp AnalysisConsumer.cpp Backend.cpp diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5b64c7e639..006f3c095c 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -367,6 +367,10 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts, Res.push_back("-load"); Res.push_back(Opts.Plugins[i]); } + for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i) { + Res.push_back("-ast-merge"); + Res.push_back(Opts.ASTMergeFiles[i]); + } } static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts, @@ -929,6 +933,7 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) { Opts.ShowTimers = Args.hasArg(OPT_ftime_report); Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ViewClassInheritance = getLastArgValue(Args, OPT_cxx_inheritance_view); + Opts.ASTMergeFiles = getAllArgValues(Args, OPT_ast_merge); FrontendOptions::InputKind DashX = FrontendOptions::IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { |