[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