[cfe-commits] r145369 - in /cfe/trunk: test/Index/file-macro-refs.c tools/libclang/CIndex.cpp tools/libclang/CIndexHigh.cpp tools/libclang/CursorVisitor.h

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Nov 28 19:14:11 PST 2011


Author: akirtzidis
Date: Mon Nov 28 21:14:11 2011
New Revision: 145369

URL: http://llvm.org/viewvc/llvm-project?rev=145369&view=rev
Log:
[libclang] Make clang_findReferencesInFile also work on macros (find all expansions/definition
of a macro in a file).

As a bonus, also make searching for declarations more efficient by ignoring
preprocessing entities when we know that we are looking for a declaration.

Fixes rdar://10427411.

Added:
    cfe/trunk/test/Index/file-macro-refs.c
Modified:
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CIndexHigh.cpp
    cfe/trunk/tools/libclang/CursorVisitor.h

Added: cfe/trunk/test/Index/file-macro-refs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/file-macro-refs.c?rev=145369&view=auto
==============================================================================
--- cfe/trunk/test/Index/file-macro-refs.c (added)
+++ cfe/trunk/test/Index/file-macro-refs.c Mon Nov 28 21:14:11 2011
@@ -0,0 +1,12 @@
+#define FOO
+
+FOO
+FOO
+
+// RUN: c-index-test -file-refs-at=%s:3:2 %s | FileCheck %s
+// RUN: CINDEXTEST_EDITING=1 c-index-test -file-refs-at=%s:3:2 %s | FileCheck %s
+
+// CHECK:      macro expansion=FOO:1:9
+// CHECK-NEXT: macro definition=FOO =[1:9 - 1:12]
+// CHECK-NEXT: macro expansion=FOO:1:9 =[3:1 - 3:4]
+// CHECK-NEXT: macro expansion=FOO:1:9 =[4:1 - 4:4]

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=145369&r1=145368&r2=145369&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Nov 28 21:14:11 2011
@@ -226,14 +226,13 @@
   unsigned Offset = Begin.second;
   unsigned Length = End.second - Begin.second;
 
-  if (!VisitPreprocessorLast &&
-      Unit->getPreprocessor().getPreprocessingRecord())
-    visitPreprocessedEntitiesInRegion();
+  if (!VisitDeclsOnly && !VisitPreprocessorLast)
+    if (visitPreprocessedEntitiesInRegion())
+      return; // visitation break.
 
   visitDeclsFromFileRegion(File, Offset, Length);
 
-  if (VisitPreprocessorLast &&
-      Unit->getPreprocessor().getPreprocessingRecord())
+  if (!VisitDeclsOnly && VisitPreprocessorLast)
     visitPreprocessedEntitiesInRegion();
 }
 
@@ -354,6 +353,9 @@
 }
 
 bool CursorVisitor::visitPreprocessedEntitiesInRegion() {
+  if (!AU->getPreprocessor().getPreprocessingRecord())
+    return false;
+
   PreprocessingRecord &PPRec
     = *AU->getPreprocessor().getPreprocessingRecord();
   SourceManager &SM = AU->getSourceManager();

Modified: cfe/trunk/tools/libclang/CIndexHigh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexHigh.cpp?rev=145369&r1=145368&r2=145369&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexHigh.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexHigh.cpp Mon Nov 28 21:14:11 2011
@@ -168,7 +168,8 @@
     if (SelIdLoc.isValid())
       Loc = SelIdLoc;
 
-    SourceManager &SM = data->getASTContext().getSourceManager();
+    ASTContext &Ctx = data->getASTContext();
+    SourceManager &SM = Ctx.getSourceManager();
     bool isInMacroDef = false;
     if (Loc.isMacroID()) {
       bool isMacroArg;
@@ -184,11 +185,11 @@
     if (isInMacroDef) {
       // FIXME: For a macro definition make sure that all expansions
       // of it expand to the same reference before allowing to point to it.
-      Loc = SourceLocation();
+      return CXChildVisit_Recurse;
     }
 
     data->visitor.visit(data->visitor.context, cursor,
-                        cxloc::translateSourceRange(D->getASTContext(), Loc));
+                        cxloc::translateSourceRange(Ctx, Loc));
   }
   return CXChildVisit_Recurse;
 }
@@ -217,10 +218,104 @@
                                   findFileIdRefVisit, &data,
                                   /*VisitPreprocessorLast=*/true,
                                   /*VisitIncludedEntities=*/false,
-                                  Range);
+                                  Range,
+                                  /*VisitDeclsOnly=*/true);
   FindIdRefsVisitor.visitFileRegion();
 }
 
+namespace {
+
+struct FindFileMacroRefVisitData {
+  ASTUnit &Unit;
+  const FileEntry *File;
+  const IdentifierInfo *Macro;
+  CXCursorAndRangeVisitor visitor;
+
+  FindFileMacroRefVisitData(ASTUnit &Unit, const FileEntry *File,
+                            const IdentifierInfo *Macro,
+                            CXCursorAndRangeVisitor visitor)
+    : Unit(Unit), File(File), Macro(Macro), visitor(visitor) { }
+
+  ASTContext &getASTContext() const {
+    return Unit.getASTContext();
+  }
+};
+
+} // anonymous namespace
+
+static enum CXChildVisitResult findFileMacroRefVisit(CXCursor cursor,
+                                                     CXCursor parent,
+                                                     CXClientData client_data) {
+  const IdentifierInfo *Macro = 0;
+  if (cursor.kind == CXCursor_MacroDefinition)
+    Macro = getCursorMacroDefinition(cursor)->getName();
+  else if (cursor.kind == CXCursor_MacroExpansion)
+    Macro = getCursorMacroExpansion(cursor)->getName();
+  if (!Macro)
+    return CXChildVisit_Continue;
+
+  FindFileMacroRefVisitData *data = (FindFileMacroRefVisitData *)client_data;
+  if (data->Macro != Macro)
+    return CXChildVisit_Continue;
+
+  SourceLocation
+    Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+
+  ASTContext &Ctx = data->getASTContext();
+  SourceManager &SM = Ctx.getSourceManager();
+  bool isInMacroDef = false;
+  if (Loc.isMacroID()) {
+    bool isMacroArg;
+    Loc = getFileSpellingLoc(SM, Loc, isMacroArg);
+    isInMacroDef = !isMacroArg;
+  }
+
+  // We are looking for identifiers in a specific file.
+  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+  if (SM.getFileEntryForID(LocInfo.first) != data->File)
+    return CXChildVisit_Continue;
+
+  if (isInMacroDef) {
+    // FIXME: For a macro definition make sure that all expansions
+    // of it expand to the same reference before allowing to point to it.
+    return CXChildVisit_Continue;
+  }
+
+  data->visitor.visit(data->visitor.context, cursor,
+                      cxloc::translateSourceRange(Ctx, Loc));
+  return CXChildVisit_Continue;
+}
+
+static void findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor,
+                                const FileEntry *File,
+                                CXCursorAndRangeVisitor Visitor) {
+  if (Cursor.kind != CXCursor_MacroDefinition &&
+      Cursor.kind != CXCursor_MacroExpansion)
+    return;
+
+  ASTUnit *Unit = static_cast<ASTUnit*>(TU->TUData);
+  SourceManager &SM = Unit->getSourceManager();
+
+  FileID FID = SM.translateFile(File);
+  const IdentifierInfo *Macro = 0;
+  if (Cursor.kind == CXCursor_MacroDefinition)
+    Macro = getCursorMacroDefinition(Cursor)->getName();
+  else
+    Macro = getCursorMacroExpansion(Cursor)->getName();
+  if (!Macro)
+    return;
+
+  FindFileMacroRefVisitData data(*Unit, File, Macro, Visitor);
+
+  SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
+  CursorVisitor FindMacroRefsVisitor(TU,
+                                  findFileMacroRefVisit, &data,
+                                  /*VisitPreprocessorLast=*/false,
+                                  /*VisitIncludedEntities=*/false,
+                                  Range);
+  FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion();
+}
+
 
 //===----------------------------------------------------------------------===//
 // libclang public APIs.
@@ -248,6 +343,15 @@
     return;
   }
 
+  if (cursor.kind == CXCursor_MacroDefinition ||
+      cursor.kind == CXCursor_MacroExpansion) {
+    findMacroRefsInFile(cxcursor::getCursorTU(cursor),
+                        cursor,
+                        static_cast<const FileEntry *>(file),
+                        visitor);
+    return;
+  }
+
   // We are interested in semantics of identifiers so for C++ constructor exprs
   // prefer type references, e.g.:
   //

Modified: cfe/trunk/tools/libclang/CursorVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CursorVisitor.h?rev=145369&r1=145368&r2=145369&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CursorVisitor.h (original)
+++ cfe/trunk/tools/libclang/CursorVisitor.h Mon Nov 28 21:14:11 2011
@@ -83,6 +83,10 @@
   /// its search.
   SourceRange RegionOfInterest;
 
+  /// \brief Whether we should only visit declarations and not preprocessing
+  /// record entries.
+  bool VisitDeclsOnly;
+
   // FIXME: Eventually remove.  This part of a hack to support proper
   // iteration over all Decls contained lexically within an ObjC container.
   DeclContext::decl_iterator *DI_current;
@@ -131,12 +135,15 @@
                 CXClientData ClientData,
                 bool VisitPreprocessorLast,
                 bool VisitIncludedPreprocessingEntries = false,
-                SourceRange RegionOfInterest = SourceRange())
+                SourceRange RegionOfInterest = SourceRange(),
+                bool VisitDeclsOnly = false)
     : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)),
       Visitor(Visitor), ClientData(ClientData),
       VisitPreprocessorLast(VisitPreprocessorLast),
       VisitIncludedEntities(VisitIncludedPreprocessingEntries),
-      RegionOfInterest(RegionOfInterest), DI_current(0), FileDI_current(0)
+      RegionOfInterest(RegionOfInterest),
+      VisitDeclsOnly(VisitDeclsOnly),
+      DI_current(0), FileDI_current(0)
   {
     Parent.kind = CXCursor_NoDeclFound;
     Parent.data[0] = 0;





More information about the cfe-commits mailing list