<div dir="ltr">Hi Balazs,<div><br></div><div>Your commit introduces a layering violation: ASTImporter (which is inside clangAST library) cannot depend on ASTUnit (which is inside clangFrontend library).</div><div>I'm afraid I'll have to revert the commit to unbreak our integrate.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 18, 2019 at 5:22 PM Balazs Keri via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: balazske<br>
Date: Thu Jul 18 08:23:10 2019<br>
New Revision: 366449<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=366449&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=366449&view=rev</a><br>
Log:<br>
[CrossTU] Add a function to retrieve original source location.<br>
<br>
Summary:<br>
A new function will be added to get the original SourceLocation<br>
for a SourceLocation that was imported as result of getCrossTUDefinition.<br>
The returned SourceLocation is in the context of the (original)<br>
SourceManager for the original source file. Additionally the<br>
ASTUnit object for that source file is returned. This is needed<br>
to get a SourceManager to operate on with the returned source location.<br>
<br>
The new function works if multiple different source files are loaded<br>
with the same CrossTU context.<br>
<br>
This patch can be treated as part of a bigger change that is needed to<br>
improve macro expansion handliong at plist generation.<br>
<br>
Reviewers: martong, shafik, a_sidorin, xazax.hun<br>
<br>
Reviewed By: martong<br>
<br>
Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits<br>
<br>
Tags: #clang<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D64554" rel="noreferrer" target="_blank">https://reviews.llvm.org/D64554</a><br>
<br>
Modified:<br>
    cfe/trunk/include/clang/AST/ASTImporter.h<br>
    cfe/trunk/include/clang/AST/ASTImporterSharedState.h<br>
    cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h<br>
    cfe/trunk/lib/AST/ASTImporter.cpp<br>
    cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp<br>
    cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTImporter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTImporter.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTImporter.h Thu Jul 18 08:23:10 2019<br>
@@ -34,6 +34,7 @@ namespace clang {<br>
<br>
 class ASTContext;<br>
 class ASTImporterSharedState;<br>
+class ASTUnit;<br>
 class Attr;<br>
 class CXXBaseSpecifier;<br>
 class CXXCtorInitializer;<br>
@@ -229,6 +230,11 @@ class TypeSourceInfo;<br>
     /// The file managers we're importing to and from.<br>
     FileManager &ToFileManager, &FromFileManager;<br>
<br>
+    /// The ASTUnit for the From context, if any.<br>
+    /// This is used to create a mapping of imported ('To') FileID's to the<br>
+    /// original ('From') FileID and ASTUnit.<br>
+    ASTUnit *FromUnit;<br>
+<br>
     /// Whether to perform a minimal import.<br>
     bool Minimal;<br>
<br>
@@ -277,6 +283,11 @@ class TypeSourceInfo;<br>
<br>
     void AddToLookupTable(Decl *ToD);<br>
<br>
+    ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,<br>
+                ASTContext &FromContext, FileManager &FromFileManager,<br>
+                ASTUnit *FromUnit, bool MinimalImport,<br>
+                std::shared_ptr<ASTImporterSharedState> SharedState);<br>
+<br>
   protected:<br>
     /// Can be overwritten by subclasses to implement their own import logic.<br>
     /// The overwritten method should call this method if it didn't import the<br>
@@ -287,7 +298,6 @@ class TypeSourceInfo;<br>
     virtual bool returnWithErrorInTest() { return false; };<br>
<br>
   public:<br>
-<br>
     /// \param ToContext The context we'll be importing into.<br>
     ///<br>
     /// \param ToFileManager The file manager we'll be importing into.<br>
@@ -307,6 +317,23 @@ class TypeSourceInfo;<br>
                 ASTContext &FromContext, FileManager &FromFileManager,<br>
                 bool MinimalImport,<br>
                 std::shared_ptr<ASTImporterSharedState> SharedState = nullptr);<br>
+    /// \param ToContext The context we'll be importing into.<br>
+    ///<br>
+    /// \param ToFileManager The file manager we'll be importing into.<br>
+    ///<br>
+    /// \param FromUnit Pointer to an ASTUnit that contains the context and<br>
+    /// file manager to import from.<br>
+    ///<br>
+    /// \param MinimalImport If true, the importer will attempt to import<br>
+    /// as little as it can, e.g., by importing declarations as forward<br>
+    /// declarations that can be completed at a later point.<br>
+    ///<br>
+    /// \param SharedState The importer specific lookup table which may be<br>
+    /// shared amongst several ASTImporter objects.<br>
+    /// If not set then the original C/C++ lookup is used.<br>
+    ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,<br>
+                ASTUnit &FromUnit, bool MinimalImport,<br>
+                std::shared_ptr<ASTImporterSharedState> SharedState = nullptr);<br>
<br>
     virtual ~ASTImporter();<br>
<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTImporterSharedState.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporterSharedState.h?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporterSharedState.h?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTImporterSharedState.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTImporterSharedState.h Thu Jul 18 08:23:10 2019<br>
@@ -17,18 +17,24 @@<br>
<br>
 #include "clang/AST/ASTImporterLookupTable.h"<br>
 #include "clang/AST/Decl.h"<br>
+#include "clang/Basic/SourceLocation.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
 // FIXME We need this because of ImportError.<br>
 #include "clang/AST/ASTImporter.h"<br>
<br>
 namespace clang {<br>
<br>
+class ASTUnit;<br>
 class TranslationUnitDecl;<br>
<br>
 /// Importer specific state, which may be shared amongst several ASTImporter<br>
 /// objects.<br>
 class ASTImporterSharedState {<br>
+public:<br>
+  using ImportedFileIDMap =<br>
+      llvm::DenseMap<FileID, std::pair<FileID, ASTUnit *>>;<br>
<br>
+private:<br>
   /// Pointer to the import specific lookup table.<br>
   std::unique_ptr<ASTImporterLookupTable> LookupTable;<br>
<br>
@@ -43,6 +49,16 @@ class ASTImporterSharedState {<br>
   // FIXME put ImportedFromDecls here!<br>
   // And from that point we can better encapsulate the lookup table.<br>
<br>
+  /// Map of imported FileID's (in "To" context) to FileID in "From" context<br>
+  /// and the ASTUnit that contains the preprocessor and source manager for the<br>
+  /// "From" FileID. This map is used to lookup a FileID and its SourceManager<br>
+  /// when knowing only the FileID in the 'To' context. The FileID could be<br>
+  /// imported by any of multiple ASTImporter objects. The map is used because<br>
+  /// we do not want to loop over all ASTImporter's to find the one that<br>
+  /// imported the FileID. (The ASTUnit is usable to get the SourceManager and<br>
+  /// additional data.)<br>
+  ImportedFileIDMap ImportedFileIDs;<br>
+<br>
 public:<br>
   ASTImporterSharedState() = default;<br>
<br>
@@ -75,6 +91,12 @@ public:<br>
   void setImportDeclError(Decl *To, ImportError Error) {<br>
     ImportErrors[To] = Error;<br>
   }<br>
+<br>
+  ImportedFileIDMap &getImportedFileIDs() { return ImportedFileIDs; }<br>
+<br>
+  const ImportedFileIDMap &getImportedFileIDs() const {<br>
+    return ImportedFileIDs;<br>
+  }<br>
 };<br>
<br>
 } // namespace clang<br>
<br>
Modified: cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h (original)<br>
+++ cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h Thu Jul 18 08:23:10 2019<br>
@@ -153,8 +153,10 @@ public:<br>
   ///        was passed to the constructor.<br>
   ///<br>
   /// \return Returns the resulting definition or an error.<br>
-  llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);<br>
-  llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD);<br>
+  llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD,<br>
+                                                        ASTUnit *Unit);<br>
+  llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD,<br>
+                                                   ASTUnit *Unit);<br>
<br>
   /// Get a name to identify a named decl.<br>
   static std::string getLookupName(const NamedDecl *ND);<br>
@@ -162,9 +164,19 @@ public:<br>
   /// Emit diagnostics for the user for potential configuration errors.<br>
   void emitCrossTUDiagnostics(const IndexError &IE);<br>
<br>
+  /// Determine the original source location in the original TU for an<br>
+  /// imported source location.<br>
+  /// \p ToLoc Source location in the imported-to AST.<br>
+  /// \return Source location in the imported-from AST and the corresponding<br>
+  /// ASTUnit.<br>
+  /// If any error happens (ToLoc is a non-imported source location) empty is<br>
+  /// returned.<br>
+  llvm::Optional<std::pair<SourceLocation /*FromLoc*/, ASTUnit *>><br>
+  getImportedFromSourceLocation(const clang::SourceLocation &ToLoc) const;<br>
+<br>
 private:<br>
   void lazyInitImporterSharedSt(TranslationUnitDecl *ToTU);<br>
-  ASTImporter &getOrCreateASTImporter(ASTContext &From);<br>
+  ASTImporter &getOrCreateASTImporter(ASTUnit *Unit);<br>
   template <typename T><br>
   llvm::Expected<const T *> getCrossTUDefinitionImpl(const T *D,<br>
                                                      StringRef CrossTUDir,<br>
@@ -174,7 +186,7 @@ private:<br>
   const T *findDefInDeclContext(const DeclContext *DC,<br>
                                 StringRef LookupName);<br>
   template <typename T><br>
-  llvm::Expected<const T *> importDefinitionImpl(const T *D);<br>
+  llvm::Expected<const T *> importDefinitionImpl(const T *D, ASTUnit *Unit);<br>
<br>
   llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;<br>
   llvm::StringMap<clang::ASTUnit *> NameASTUnitMap;<br>
<br>
Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Jul 18 08:23:10 2019<br>
@@ -12,9 +12,9 @@<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 #include "clang/AST/ASTImporter.h"<br>
-#include "clang/AST/ASTImporterSharedState.h"<br>
 #include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/ASTDiagnostic.h"<br>
+#include "clang/AST/ASTImporterSharedState.h"<br>
 #include "clang/AST/ASTStructuralEquivalence.h"<br>
 #include "clang/AST/Attr.h"<br>
 #include "clang/AST/Decl.h"<br>
@@ -52,13 +52,14 @@<br>
 #include "clang/Basic/SourceLocation.h"<br>
 #include "clang/Basic/SourceManager.h"<br>
 #include "clang/Basic/Specifiers.h"<br>
+#include "clang/Frontend/ASTUnit.h"<br>
 #include "llvm/ADT/APSInt.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
 #include "llvm/ADT/None.h"<br>
 #include "llvm/ADT/Optional.h"<br>
-#include "llvm/ADT/ScopeExit.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/ADT/ScopeExit.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/Support/Casting.h"<br>
 #include "llvm/Support/ErrorHandling.h"<br>
@@ -7716,9 +7717,22 @@ ASTImporter::ASTImporter(ASTContext &ToC<br>
                          ASTContext &FromContext, FileManager &FromFileManager,<br>
                          bool MinimalImport,<br>
                          std::shared_ptr<ASTImporterSharedState> SharedState)<br>
+    : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,<br>
+                  nullptr, MinimalImport, SharedState){}<br>
+ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,<br>
+                         ASTUnit &FromUnit, bool MinimalImport,<br>
+                         std::shared_ptr<ASTImporterSharedState> SharedState)<br>
+    : ASTImporter(ToContext, ToFileManager, FromUnit.getASTContext(),<br>
+                  FromUnit.getFileManager(), &FromUnit, MinimalImport,<br>
+                  SharedState){}<br>
+<br>
+ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,<br>
+                         ASTContext &FromContext, FileManager &FromFileManager,<br>
+                         ASTUnit *FromUnit, bool MinimalImport,<br>
+                         std::shared_ptr<ASTImporterSharedState> SharedState)<br>
     : SharedState(SharedState), ToContext(ToContext), FromContext(FromContext),<br>
       ToFileManager(ToFileManager), FromFileManager(FromFileManager),<br>
-      Minimal(MinimalImport) {<br>
+      FromUnit(FromUnit), Minimal(MinimalImport) {<br>
<br>
   // Create a default state without the lookup table: LLDB case.<br>
   if (!SharedState) {<br>
@@ -8421,6 +8435,13 @@ Expected<FileID> ASTImporter::Import(Fil<br>
   assert(ToID.isValid() && "Unexpected invalid fileID was created.");<br>
<br>
   ImportedFileIDs[FromID] = ToID;<br>
+  if (FromUnit) {<br>
+    assert(SharedState->getImportedFileIDs().find(ToID) ==<br>
+               SharedState->getImportedFileIDs().end() &&<br>
+           "FileID already imported!");<br>
+    SharedState->getImportedFileIDs()[ToID] = std::make_pair(FromID, FromUnit);<br>
+  }<br>
+<br>
   return ToID;<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp (original)<br>
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp Thu Jul 18 08:23:10 2019<br>
@@ -295,7 +295,7 @@ llvm::Expected<const T *> CrossTranslati<br>
<br>
   TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();<br>
   if (const T *ResultDecl = findDefInDeclContext<T>(TU, LookupName))<br>
-    return importDefinition(ResultDecl);<br>
+    return importDefinition(ResultDecl, Unit);<br>
   return llvm::make_error<IndexError>(index_error_code::failed_import);<br>
 }<br>
<br>
@@ -411,10 +411,13 @@ llvm::Expected<ASTUnit *> CrossTranslati<br>
<br>
 template <typename T><br>
 llvm::Expected<const T *><br>
-CrossTranslationUnitContext::importDefinitionImpl(const T *D) {<br>
+CrossTranslationUnitContext::importDefinitionImpl(const T *D, ASTUnit *Unit) {<br>
   assert(hasBodyOrInit(D) && "Decls to be imported should have body or init.");<br>
<br>
-  ASTImporter &Importer = getOrCreateASTImporter(D->getASTContext());<br>
+  assert(&D->getASTContext() == &Unit->getASTContext() &&<br>
+         "ASTContext of Decl and the unit should match.");<br>
+  ASTImporter &Importer = getOrCreateASTImporter(Unit);<br>
+<br>
   auto ToDeclOrError = Importer.Import(D);<br>
   if (!ToDeclOrError) {<br>
     handleAllErrors(ToDeclOrError.takeError(),<br>
@@ -441,13 +444,15 @@ CrossTranslationUnitContext::importDefin<br>
 }<br>
<br>
 llvm::Expected<const FunctionDecl *><br>
-CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {<br>
-  return importDefinitionImpl(FD);<br>
+CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD,<br>
+                                              ASTUnit *Unit) {<br>
+  return importDefinitionImpl(FD, Unit);<br>
 }<br>
<br>
 llvm::Expected<const VarDecl *><br>
-CrossTranslationUnitContext::importDefinition(const VarDecl *VD) {<br>
-  return importDefinitionImpl(VD);<br>
+CrossTranslationUnitContext::importDefinition(const VarDecl *VD,<br>
+                                              ASTUnit *Unit) {<br>
+  return importDefinitionImpl(VD, Unit);<br>
 }<br>
<br>
 void CrossTranslationUnitContext::lazyInitImporterSharedSt(<br>
@@ -457,17 +462,40 @@ void CrossTranslationUnitContext::lazyIn<br>
 }<br>
<br>
 ASTImporter &<br>
-CrossTranslationUnitContext::getOrCreateASTImporter(ASTContext &From) {<br>
+CrossTranslationUnitContext::getOrCreateASTImporter(ASTUnit *Unit) {<br>
+  ASTContext &From = Unit->getASTContext();<br>
+<br>
   auto I = ASTUnitImporterMap.find(From.getTranslationUnitDecl());<br>
   if (I != ASTUnitImporterMap.end())<br>
     return *I->second;<br>
   lazyInitImporterSharedSt(Context.getTranslationUnitDecl());<br>
-  ASTImporter *NewImporter = new ASTImporter(<br>
-      Context, Context.getSourceManager().getFileManager(), From,<br>
-      From.getSourceManager().getFileManager(), false, ImporterSharedSt);<br>
+  ASTImporter *NewImporter =<br>
+      new ASTImporter(Context, Context.getSourceManager().getFileManager(),<br>
+                      *Unit, false, ImporterSharedSt);<br>
   ASTUnitImporterMap[From.getTranslationUnitDecl()].reset(NewImporter);<br>
   return *NewImporter;<br>
 }<br>
<br>
+llvm::Optional<std::pair<SourceLocation, ASTUnit *>><br>
+CrossTranslationUnitContext::getImportedFromSourceLocation(<br>
+    const clang::SourceLocation &ToLoc) const {<br>
+  if (!ImporterSharedSt)<br>
+    return {};<br>
+<br>
+  const SourceManager &SM = Context.getSourceManager();<br>
+  auto DecToLoc = SM.getDecomposedLoc(ToLoc);<br>
+<br>
+  auto I = ImporterSharedSt->getImportedFileIDs().find(DecToLoc.first);<br>
+  if (I == ImporterSharedSt->getImportedFileIDs().end())<br>
+    return {};<br>
+<br>
+  FileID FromID = I->second.first;<br>
+  clang::ASTUnit *Unit = I->second.second;<br>
+  SourceLocation FromLoc =<br>
+      Unit->getSourceManager().getComposedLoc(FromID, DecToLoc.second);<br>
+<br>
+  return std::make_pair(FromLoc, Unit);<br>
+}<br>
+<br>
 } // namespace cross_tu<br>
 } // namespace clang<br>
<br>
Modified: cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp?rev=366449&r1=366448&r2=366449&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp?rev=366449&r1=366448&r2=366449&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp (original)<br>
+++ cfe/trunk/unittests/CrossTU/CrossTranslationUnitTest.cpp Thu Jul 18 08:23:10 2019<br>
@@ -28,13 +28,18 @@ public:<br>
       : CTU(CI), Success(Success) {}<br>
<br>
   void HandleTranslationUnit(ASTContext &Ctx) {<br>
+    auto FindFInTU = [](const TranslationUnitDecl *TU) {<br>
+      const FunctionDecl *FD = nullptr;<br>
+      for (const Decl *D : TU->decls()) {<br>
+        FD = dyn_cast<FunctionDecl>(D);<br>
+        if (FD && FD->getName() == "f")<br>
+          break;<br>
+      }<br>
+      return FD;<br>
+    };<br>
+<br>
     const TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();<br>
-    const FunctionDecl *FD = nullptr;<br>
-    for (const Decl *D : TU->decls()) {<br>
-      FD = dyn_cast<FunctionDecl>(D);<br>
-      if (FD && FD->getName() == "f")<br>
-        break;<br>
-    }<br>
+    const FunctionDecl *FD = FindFInTU(TU);<br>
     assert(FD && FD->getName() == "f");<br>
     bool OrigFDHasBody = FD->hasBody();<br>
<br>
@@ -78,6 +83,28 @@ public:<br>
     if (NewFDorError) {<br>
       const FunctionDecl *NewFD = *NewFDorError;<br>
       *Success = NewFD && NewFD->hasBody() && !OrigFDHasBody;<br>
+<br>
+      if (NewFD) {<br>
+        // Check GetImportedFromSourceLocation.<br>
+        llvm::Optional<std::pair<SourceLocation, ASTUnit *>> SLocResult =<br>
+            CTU.getImportedFromSourceLocation(NewFD->getLocation());<br>
+        EXPECT_TRUE(SLocResult);<br>
+        if (SLocResult) {<br>
+          SourceLocation OrigSLoc = (*SLocResult).first;<br>
+          ASTUnit *OrigUnit = (*SLocResult).second;<br>
+          // OrigUnit is created internally by CTU (is not the<br>
+          // ASTWithDefinition).<br>
+          TranslationUnitDecl *OrigTU =<br>
+              OrigUnit->getASTContext().getTranslationUnitDecl();<br>
+          const FunctionDecl *FDWithDefinition = FindFInTU(OrigTU);<br>
+          EXPECT_TRUE(FDWithDefinition);<br>
+          if (FDWithDefinition) {<br>
+            EXPECT_EQ(FDWithDefinition->getName(), "f");<br>
+            EXPECT_TRUE(FDWithDefinition->isThisDeclarationADefinition());<br>
+            EXPECT_EQ(OrigSLoc, FDWithDefinition->getLocation());<br>
+          }<br>
+        }<br>
+      }<br>
     }<br>
   }<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Regards,</div><div>Ilya Biryukov</div></div></div></div></div>