Extend the preprocessing record and libclang with support for
inclusion directives, keeping track of every #include, #import,
etc. in the translation unit. We keep track of the source location and
kind of the inclusion, how the file name was spelled, and the
underlying file to which the inclusion resolved.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 722e2cb..c944883 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -555,6 +555,13 @@
           
           continue;
         }
+        
+        if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) {
+          if (Visit(MakeInclusionDirectiveCursor(ID, CXXUnit)))
+            return true;
+          
+          continue;
+        }
       }
     }
     return false;
@@ -2565,6 +2572,9 @@
     return createCXString(getCursorMacroDefinition(C)->getName()
                                                            ->getNameStart());
 
+  if (C.kind == CXCursor_InclusionDirective)
+    return createCXString(getCursorInclusionDirective(C)->getFileName());
+      
   if (clang_isDeclaration(C.kind))
     return getDeclSpelling(getCursorDecl(C));
 
@@ -2757,6 +2767,8 @@
     return createCXString("macro definition");
   case CXCursor_MacroInstantiation:
     return createCXString("macro instantiation");
+  case CXCursor_InclusionDirective:
+    return createCXString("inclusion directive");
   case CXCursor_Namespace:
     return createCXString("Namespace");
   case CXCursor_LinkageSpec:
@@ -2977,7 +2989,13 @@
     SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
     return cxloc::translateSourceLocation(getCursorContext(C), L);
   }
-  
+
+  if (C.kind == CXCursor_InclusionDirective) {
+    SourceLocation L
+      = cxcursor::getCursorInclusionDirective(C)->getSourceRange().getBegin();
+    return cxloc::translateSourceLocation(getCursorContext(C), L);
+  }
+
   if (C.kind < CXCursor_FirstDecl || C.kind > CXCursor_LastDecl)
     return clang_getNullLocation();
 
@@ -3043,12 +3061,14 @@
 
   if (C.kind == CXCursor_MacroDefinition)
     return cxcursor::getCursorMacroDefinition(C)->getSourceRange();
-  
+
+  if (C.kind == CXCursor_InclusionDirective)
+    return cxcursor::getCursorInclusionDirective(C)->getSourceRange();
+
   if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl)
     return getCursorDecl(C)->getSourceRange();
 
-  return SourceRange();
-}
+  return SourceRange();}
 
 extern "C" {
 
@@ -4149,6 +4169,14 @@
   delete [] overridden;
 }
 
+CXFile clang_getIncludedFile(CXCursor cursor) {
+  if (cursor.kind != CXCursor_InclusionDirective)
+    return 0;
+  
+  InclusionDirective *ID = getCursorInclusionDirective(cursor);
+  return (void *)ID->getFile();
+}
+  
 } // end: extern "C"
 
 
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 52594dc..d506400 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -363,6 +363,17 @@
   return static_cast<MacroInstantiation *>(C.data[0]);
 }
 
+CXCursor cxcursor::MakeInclusionDirectiveCursor(InclusionDirective *ID, 
+                                                ASTUnit *TU) {
+  CXCursor C = { CXCursor_InclusionDirective, { ID, 0, TU } };
+  return C;
+}
+
+InclusionDirective *cxcursor::getCursorInclusionDirective(CXCursor C) {
+  assert(C.kind == CXCursor_InclusionDirective);
+  return static_cast<InclusionDirective *>(C.data[0]);  
+}
+
 CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, 
                                       ASTUnit *TU) {
   
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index 4a29dd0..a31a322 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -28,6 +28,7 @@
 class Decl;
 class Expr;
 class FieldDecl;
+class InclusionDirective;
 class LabelStmt;
 class MacroDefinition;
 class MacroInstantiation;
@@ -133,6 +134,13 @@
 /// source range.
 MacroInstantiation *getCursorMacroInstantiation(CXCursor C);
 
+/// \brief Create an inclusion directive cursor.
+CXCursor MakeInclusionDirectiveCursor(InclusionDirective *, ASTUnit *TU);
+
+/// \brief Unpack a given inclusion directive cursor to retrieve its
+/// source range.
+InclusionDirective *getCursorInclusionDirective(CXCursor C);
+
 /// \brief Create a label reference at the given location.
 CXCursor MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, ASTUnit *TU);
 
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index dbb335f..e9d40d0 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -68,6 +68,7 @@
 _clang_getFileName
 _clang_getFileTime
 _clang_getIBOutletCollectionType
+_clang_getIncludedFile
 _clang_getInclusions
 _clang_getInstantiationLocation
 _clang_getLocation
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 06e5a8b..9935a58 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -68,6 +68,7 @@
 clang_getFileName
 clang_getFileTime
 clang_getIBOutletCollectionType
+clang_getIncludedFile
 clang_getInclusions
 clang_getInstantiationLocation
 clang_getLocation