forked from OSchip/llvm-project
Implement basic support for importing source locations from one AST
into another AST, including their include history. Here's an example error that involves a conflict merging a variable with different types in two translation units (diagnosed in the third AST context into which everything is merged). /Volumes/Data/dgregor/Projects/llvm/tools/clang/test/ASTMerge/Inputs/var2.c:3:5: error: external variable 'x2' declared with incompatible types in different translation units ('int' vs. 'double') int x2; ^ In file included from /Volumes/Data/dgregor/Projects/llvm/tools/clang/test/ASTMerge/Inputs/var1.c:3: /Volumes/Data/dgregor/Projects/llvm/tools/clang/test/ASTMerge/Inputs/var1.h:1:8: note: declared here with type 'double' double x2; ^ Although we maintain include history, we do not maintain macro instantiation history across a merge. Instead, we map down to the spelling location (for now!). llvm-svn: 95732
This commit is contained in:
parent
08f618cd03
commit
811663eb11
|
@ -25,6 +25,7 @@ namespace clang {
|
|||
class DeclContext;
|
||||
class Diagnostic;
|
||||
class Expr;
|
||||
class FileManager;
|
||||
class IdentifierInfo;
|
||||
class NestedNameSpecifier;
|
||||
class Stmt;
|
||||
|
@ -36,6 +37,9 @@ namespace clang {
|
|||
/// \brief The contexts we're importing to and from.
|
||||
ASTContext &ToContext, &FromContext;
|
||||
|
||||
/// \brief The file managers we're importing to and from.
|
||||
FileManager &ToFileManager, &FromFileManager;
|
||||
|
||||
/// \brief The diagnostics object that we should use to emit diagnostics
|
||||
/// within the context we're importing to and from.
|
||||
Diagnostic &ToDiags, &FromDiags;
|
||||
|
@ -48,9 +52,15 @@ namespace clang {
|
|||
/// context to the corresponding declarations in the "to" context.
|
||||
llvm::DenseMap<Decl *, Decl *> ImportedDecls;
|
||||
|
||||
/// \brief Mapping from the already-imported FileIDs in the "from" source
|
||||
/// manager to the corresponding FileIDs in the "to" source manager.
|
||||
llvm::DenseMap<unsigned, FileID> ImportedFileIDs;
|
||||
|
||||
public:
|
||||
ASTImporter(ASTContext &ToContext, Diagnostic &ToDiags,
|
||||
ASTContext &FromContext, Diagnostic &FromDiags);
|
||||
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
|
||||
Diagnostic &ToDiags,
|
||||
ASTContext &FromContext, FileManager &FromFileManager,
|
||||
Diagnostic &FromDiags);
|
||||
|
||||
virtual ~ASTImporter();
|
||||
|
||||
|
@ -102,7 +112,7 @@ namespace clang {
|
|||
/// \returns the equivalent nested-name-specifier in the "to"
|
||||
/// context, or NULL if an error occurred.
|
||||
NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS);
|
||||
|
||||
|
||||
/// \brief Import the given source location from the "from" context into
|
||||
/// the "to" context.
|
||||
///
|
||||
|
@ -130,6 +140,13 @@ namespace clang {
|
|||
/// \returns the equivalent identifier in the "to" context.
|
||||
IdentifierInfo *Import(IdentifierInfo *FromId);
|
||||
|
||||
/// \brief Import the given file ID from the "from" context into the
|
||||
/// "to" context.
|
||||
///
|
||||
/// \returns the equivalent file ID in the source manager of the "to"
|
||||
/// context.
|
||||
FileID Import(FileID);
|
||||
|
||||
/// \brief Cope with a name conflict when importing a declaration into the
|
||||
/// given context.
|
||||
///
|
||||
|
@ -168,6 +185,12 @@ namespace clang {
|
|||
/// \brief Retrieve the context that AST nodes are being imported from.
|
||||
ASTContext &getFromContext() const { return FromContext; }
|
||||
|
||||
/// \brief Retrieve the file manager that AST nodes are being imported into.
|
||||
FileManager &getToFileManager() const { return ToFileManager; }
|
||||
|
||||
/// \brief Retrieve the file manager that AST nodes are being imported from.
|
||||
FileManager &getFromFileManager() const { return FromFileManager; }
|
||||
|
||||
/// \brief Retrieve the diagnostics object to use to report errors within
|
||||
/// the context we're importing into.
|
||||
Diagnostic &getToDiags() const { return ToDiags; }
|
||||
|
|
|
@ -14,10 +14,13 @@
|
|||
#include "clang/AST/ASTImporter.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTDiagnostic.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/TypeVisitor.h"
|
||||
#include "clang/AST/ASTDiagnostic.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
|
@ -444,7 +447,7 @@ QualType ASTNodeImporter::VisitObjCObjectPointerType(ObjCObjectPointerType *T) {
|
|||
// Import Declarations
|
||||
//----------------------------------------------------------------------------
|
||||
Decl *ASTNodeImporter::VisitDecl(Decl *D) {
|
||||
Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
|
||||
Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node)
|
||||
<< D->getDeclKindName();
|
||||
return 0;
|
||||
}
|
||||
|
@ -567,9 +570,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {
|
|||
return ToVar;
|
||||
}
|
||||
|
||||
ASTImporter::ASTImporter(ASTContext &ToContext, Diagnostic &ToDiags,
|
||||
ASTContext &FromContext, Diagnostic &FromDiags)
|
||||
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
|
||||
Diagnostic &ToDiags,
|
||||
ASTContext &FromContext, FileManager &FromFileManager,
|
||||
Diagnostic &FromDiags)
|
||||
: ToContext(ToContext), FromContext(FromContext),
|
||||
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
|
||||
ToDiags(ToDiags), FromDiags(FromDiags) {
|
||||
ImportedDecls[FromContext.getTranslationUnitDecl()]
|
||||
= ToContext.getTranslationUnitDecl();
|
||||
|
@ -658,14 +664,62 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
|
|||
if (FromLoc.isInvalid())
|
||||
return SourceLocation();
|
||||
|
||||
// FIXME: Implement!
|
||||
return SourceLocation();
|
||||
SourceManager &FromSM = FromContext.getSourceManager();
|
||||
|
||||
// For now, map everything down to its spelling location, so that we
|
||||
// don't have to import macro instantiations.
|
||||
// FIXME: Import macro instantiations!
|
||||
FromLoc = FromSM.getSpellingLoc(FromLoc);
|
||||
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
|
||||
SourceManager &ToSM = ToContext.getSourceManager();
|
||||
return ToSM.getLocForStartOfFile(Import(Decomposed.first))
|
||||
.getFileLocWithOffset(Decomposed.second);
|
||||
}
|
||||
|
||||
SourceRange ASTImporter::Import(SourceRange FromRange) {
|
||||
return SourceRange(Import(FromRange.getBegin()), Import(FromRange.getEnd()));
|
||||
}
|
||||
|
||||
FileID ASTImporter::Import(FileID FromID) {
|
||||
llvm::DenseMap<unsigned, FileID>::iterator Pos
|
||||
= ImportedFileIDs.find(FromID.getHashValue());
|
||||
if (Pos != ImportedFileIDs.end())
|
||||
return Pos->second;
|
||||
|
||||
SourceManager &FromSM = FromContext.getSourceManager();
|
||||
SourceManager &ToSM = ToContext.getSourceManager();
|
||||
const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);
|
||||
assert(FromSLoc.isFile() && "Cannot handle macro instantiations yet");
|
||||
|
||||
// Include location of this file.
|
||||
SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
|
||||
|
||||
// Map the FileID for to the "to" source manager.
|
||||
FileID ToID;
|
||||
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
|
||||
if (Cache->Entry) {
|
||||
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
|
||||
// disk again
|
||||
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
|
||||
// than mmap the files several times.
|
||||
const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName());
|
||||
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
|
||||
FromSLoc.getFile().getFileCharacteristic());
|
||||
} else {
|
||||
// FIXME: We want to re-use the existing MemoryBuffer!
|
||||
const llvm::MemoryBuffer *FromBuf = Cache->getBuffer();
|
||||
llvm::MemoryBuffer *ToBuf
|
||||
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBufferStart(),
|
||||
FromBuf->getBufferEnd(),
|
||||
FromBuf->getBufferIdentifier());
|
||||
ToID = ToSM.createFileIDForMemBuffer(ToBuf);
|
||||
}
|
||||
|
||||
|
||||
ImportedFileIDs[FromID.getHashValue()] = ToID;
|
||||
return ToID;
|
||||
}
|
||||
|
||||
DeclarationName ASTImporter::Import(DeclarationName FromName) {
|
||||
if (!FromName)
|
||||
return DeclarationName();
|
||||
|
|
|
@ -44,8 +44,12 @@ void ASTMergeAction::ExecuteAction() {
|
|||
|
||||
ASTDiags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
|
||||
&Unit->getASTContext());
|
||||
ASTImporter Importer(CI.getASTContext(), CI.getDiagnostics(),
|
||||
Unit->getASTContext(), ASTDiags);
|
||||
ASTImporter Importer(CI.getASTContext(),
|
||||
CI.getFileManager(),
|
||||
CI.getDiagnostics(),
|
||||
Unit->getASTContext(),
|
||||
Unit->getFileManager(),
|
||||
ASTDiags);
|
||||
|
||||
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
|
||||
for (DeclContext::decl_iterator D = TU->decls_begin(),
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
int *x0;
|
||||
float **x1;
|
||||
#include "var1.h"
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
int *x0;
|
||||
double *x1;
|
||||
int x2;
|
||||
|
|
|
@ -2,4 +2,8 @@
|
|||
// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/var2.c
|
||||
// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK: error: external variable 'x1' declared with incompatible types in different translation units ('double *' vs. 'float **')
|
||||
// CHECK: var2.c:2:9: error: external variable 'x1' declared with incompatible types in different translation units ('double *' vs. 'float **')
|
||||
// CHECK: var1.c:2:9: note: declared here with type 'float **'
|
||||
// CHECK: var2.c:3:5: error: external variable 'x2' declared with incompatible types in different translation units ('int' vs. 'double')
|
||||
// CHECK: In file included from{{.*}}var1.c:3:
|
||||
// CHECK: var1.h:1:8: note: declared here with type 'double'
|
||||
|
|
Loading…
Reference in New Issue