[cfe-commits] r95732 - in /cfe/trunk: include/clang/AST/ASTImporter.h lib/AST/ASTImporter.cpp lib/Frontend/ASTMerge.cpp test/ASTMerge/Inputs/var1.c test/ASTMerge/Inputs/var2.c test/ASTMerge/var.c
Douglas Gregor
dgregor at apple.com
Tue Feb 9 16:15:18 PST 2010
Author: dgregor
Date: Tue Feb 9 18:15:17 2010
New Revision: 95732
URL: http://llvm.org/viewvc/llvm-project?rev=95732&view=rev
Log:
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!).
Modified:
cfe/trunk/include/clang/AST/ASTImporter.h
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/lib/Frontend/ASTMerge.cpp
cfe/trunk/test/ASTMerge/Inputs/var1.c
cfe/trunk/test/ASTMerge/Inputs/var2.c
cfe/trunk/test/ASTMerge/var.c
Modified: cfe/trunk/include/clang/AST/ASTImporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)
+++ cfe/trunk/include/clang/AST/ASTImporter.h Tue Feb 9 18:15:17 2010
@@ -25,6 +25,7 @@
class DeclContext;
class Diagnostic;
class Expr;
+ class FileManager;
class IdentifierInfo;
class NestedNameSpecifier;
class Stmt;
@@ -36,6 +37,9 @@
/// \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 @@
/// 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 @@
/// \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 @@
/// \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 @@
/// \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; }
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Feb 9 18:15:17 2010
@@ -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 @@
// 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 @@
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 @@
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();
Modified: cfe/trunk/lib/Frontend/ASTMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTMerge.cpp?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTMerge.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTMerge.cpp Tue Feb 9 18:15:17 2010
@@ -44,8 +44,12 @@
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(),
Modified: cfe/trunk/test/ASTMerge/Inputs/var1.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/Inputs/var1.c?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/Inputs/var1.c (original)
+++ cfe/trunk/test/ASTMerge/Inputs/var1.c Tue Feb 9 18:15:17 2010
@@ -1,2 +1,3 @@
int *x0;
float **x1;
+#include "var1.h"
Modified: cfe/trunk/test/ASTMerge/Inputs/var2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/Inputs/var2.c?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/Inputs/var2.c (original)
+++ cfe/trunk/test/ASTMerge/Inputs/var2.c Tue Feb 9 18:15:17 2010
@@ -1,2 +1,3 @@
int *x0;
double *x1;
+int x2;
Modified: cfe/trunk/test/ASTMerge/var.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/var.c?rev=95732&r1=95731&r2=95732&view=diff
==============================================================================
--- cfe/trunk/test/ASTMerge/var.c (original)
+++ cfe/trunk/test/ASTMerge/var.c Tue Feb 9 18:15:17 2010
@@ -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'
More information about the cfe-commits
mailing list