[cfe-commits] r74803 - in /cfe/trunk: test/Index/_init.c test/Index/find-decls.c test/Index/find-defs.c test/Index/find-refs.c test/Index/foo.h test/Index/t1.c test/Index/t2.c test/TestRunner.sh tools/index-test/CMakeLists.txt tools/index-test/Makefile tools/index-test/index-test.cpp utils/test/TestRunner.py

Argiris Kirtzidis akyrtzi at gmail.com
Sun Jul 5 15:22:35 PDT 2009


Author: akirtzidis
Date: Sun Jul  5 17:22:35 2009
New Revision: 74803

URL: http://llvm.org/viewvc/llvm-project?rev=74803&view=rev
Log:
Make use of the Index library through the index-test tool.

'index-test' is now able to provide additional info for a Decl, through multiple AST files:
-Find declarations
-Find definitions
-Find references

Added:
    cfe/trunk/test/Index/_init.c
    cfe/trunk/test/Index/find-decls.c
    cfe/trunk/test/Index/find-defs.c
    cfe/trunk/test/Index/find-refs.c
    cfe/trunk/test/Index/foo.h
    cfe/trunk/test/Index/t1.c
    cfe/trunk/test/Index/t2.c
Modified:
    cfe/trunk/test/TestRunner.sh
    cfe/trunk/tools/index-test/CMakeLists.txt
    cfe/trunk/tools/index-test/Makefile
    cfe/trunk/tools/index-test/index-test.cpp
    cfe/trunk/utils/test/TestRunner.py

Added: cfe/trunk/test/Index/_init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/_init.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/_init.c (added)
+++ cfe/trunk/test/Index/_init.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,2 @@
+// RUN: clang-cc -emit-pch %S/t1.c -o %T/t1.ast &&
+// RUN: clang-cc -emit-pch %S/t2.c -o %T/t2.ast

Added: cfe/trunk/test/Index/find-decls.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/find-decls.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/find-decls.c (added)
+++ cfe/trunk/test/Index/find-decls.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,7 @@
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:8:7 -print-decls | count 3 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:8:7 -print-decls | grep 'foo.h:4:6,' | count 2 && 
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:8:7 -print-decls | grep 't2.c:5:6,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:47 -print-decls | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:47 -print-decls | grep 't1.c:5:12,' && 
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:6:20 -print-decls | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:6:20 -print-decls | grep 't1.c:3:19,'

Added: cfe/trunk/test/Index/find-defs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/find-defs.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/find-defs.c (added)
+++ cfe/trunk/test/Index/find-defs.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,8 @@
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-defs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-defs | grep 't2.c:3:5,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:3:9 -print-defs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:3:9 -print-defs | grep 't1.c:3:6,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:4:9 -print-defs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:4:9 -print-defs | grep 't2.c:5:6,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:8:7 -print-defs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:8:7 -print-defs | grep 't2.c:5:6,'

Added: cfe/trunk/test/Index/find-refs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/find-refs.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/find-refs.c (added)
+++ cfe/trunk/test/Index/find-refs.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,16 @@
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-refs | count 3 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-refs | grep 't1.c:4:19,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-refs | grep 't2.c:6:3,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:1:14 -print-refs | grep 't2.c:7:12,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:3:9 -print-refs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:3:9 -print-refs | grep 't2.c:7:3,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:4:9 -print-refs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/foo.h:4:9 -print-refs | grep 't1.c:8:3,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:3:22 -print-refs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:3:22 -print-refs | grep 't1.c:6:17,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:4:11 -print-refs | count 1 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:4:11 -print-refs | grep 't1.c:6:5,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:30 -print-refs | count 3 &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:30 -print-refs | grep 't1.c:5:27,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:30 -print-refs | grep 't1.c:5:44,' &&
+// RUN: index-test %T/t1.ast %T/t2.ast -point-at %S/t1.c:5:30 -print-refs | grep 't1.c:6:26,'

Added: cfe/trunk/test/Index/foo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/foo.h?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/foo.h (added)
+++ cfe/trunk/test/Index/foo.h Sun Jul  5 17:22:35 2009
@@ -0,0 +1,4 @@
+extern int global_var;
+
+void foo_func(int param1);
+void bar_func(void);

Added: cfe/trunk/test/Index/t1.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/t1.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/t1.c (added)
+++ cfe/trunk/test/Index/t1.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,9 @@
+#include "foo.h"
+
+void foo_func(int param1) {
+  int local_var = global_var;
+  for (int for_var = 100; for_var < 500; ++for_var) {
+    local_var = param1 + for_var;
+  }
+  bar_func();
+}

Added: cfe/trunk/test/Index/t2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/t2.c?rev=74803&view=auto

==============================================================================
--- cfe/trunk/test/Index/t2.c (added)
+++ cfe/trunk/test/Index/t2.c Sun Jul  5 17:22:35 2009
@@ -0,0 +1,8 @@
+#include "foo.h"
+
+int global_var = 10;
+
+void bar_func(void) {
+  global_var += 100;
+  foo_func(global_var);
+}

Modified: cfe/trunk/test/TestRunner.sh
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/TestRunner.sh?rev=74803&r1=74802&r2=74803&view=diff

==============================================================================
--- cfe/trunk/test/TestRunner.sh (original)
+++ cfe/trunk/test/TestRunner.sh Sun Jul  5 17:22:35 2009
@@ -11,6 +11,7 @@
 #     %S - Replaced with the directory where the input file resides
 #     %prcontext - prcontext.tcl script
 #     %t - temporary file name (derived from testcase name)
+#     %T - directory of temporary file name
 #
 
 FILENAME=$1
@@ -19,6 +20,7 @@
 FILEDIR=`dirname $TESTNAME`
 
 OUTPUT=Output/$1.out
+OUTPUTDIR=`dirname $OUTPUT`
 
 # create the output directory if it does not already exist
 mkdir -p `dirname $OUTPUT` > /dev/null 2>&1
@@ -86,6 +88,7 @@
       -e "s|%s|$SUBST|g" \
       -e "s|%S|$FILEDIR|g" \
       -e "s|%prcontext|prcontext.tcl|g" \
+      -e "s|%T|$OUTPUTDIR|g" \
       -e "s|%t|$TEMPOUTPUT|g" > $SCRIPT
 
 IS_XFAIL=0

Modified: cfe/trunk/tools/index-test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/index-test/CMakeLists.txt?rev=74803&r1=74802&r2=74803&view=diff

==============================================================================
--- cfe/trunk/tools/index-test/CMakeLists.txt (original)
+++ cfe/trunk/tools/index-test/CMakeLists.txt Sun Jul  5 17:22:35 2009
@@ -1,6 +1,7 @@
 set(LLVM_NO_RTTI 1)
 
 set( LLVM_USED_LIBS
+  clangIndex
   clangFrontend
   clangSema
   clangAST

Modified: cfe/trunk/tools/index-test/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/index-test/Makefile?rev=74803&r1=74802&r2=74803&view=diff

==============================================================================
--- cfe/trunk/tools/index-test/Makefile (original)
+++ cfe/trunk/tools/index-test/Makefile Sun Jul  5 17:22:35 2009
@@ -18,6 +18,6 @@
 include $(LEVEL)/Makefile.config
 
 LINK_COMPONENTS := bitreader
-USEDLIBS = clangFrontend.a clangSema.a clangAST.a clangLex.a clangBasic.a 
+USEDLIBS = clangIndex.a clangFrontend.a clangSema.a clangAST.a clangLex.a clangBasic.a 
 
 include $(LLVM_SRC_ROOT)/Makefile.rules

Modified: cfe/trunk/tools/index-test/index-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/index-test/index-test.cpp?rev=74803&r1=74802&r2=74803&view=diff

==============================================================================
--- cfe/trunk/tools/index-test/index-test.cpp (original)
+++ cfe/trunk/tools/index-test/index-test.cpp Sun Jul  5 17:22:35 2009
@@ -21,35 +21,162 @@
 //       Point at a declaration/statement/expression. If no other operation is
 //       specified, prints some info about it.
 //
+//   -print-refs
+//       Print ASTNodes that reference the -point-at node
+//
+//   -print-defs
+//       Print ASTNodes that define the -point-at node
+//
+//   -print-decls
+//       Print ASTNodes that declare the -point-at node
+//
 //===----------------------------------------------------------------------===//
 
+#include "clang/Index/Program.h"
+#include "clang/Index/IndexProvider.h"
+#include "clang/Index/Entity.h"
+#include "clang/Index/TranslationUnit.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Frontend/CommandLineSourceLoc.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/Stmt.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/ASTNode.h"
+#include "clang/AST/DeclReferenceMap.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/System/Signals.h"
 using namespace clang;
+using namespace idx;
 
+class TUnit : public TranslationUnit {
+public:
+  TUnit(ASTUnit *ast, const std::string &filename)
+    : AST(ast), Filename(filename) { }
+  
+  virtual ASTContext &getASTContext() { return AST->getASTContext(); }
+  
+  llvm::OwningPtr<ASTUnit> AST;
+  std::string Filename;
+};
 
 static llvm::cl::list<ParsedSourceLocation>
 PointAtLocation("point-at", llvm::cl::Optional,
                  llvm::cl::value_desc("source-location"),
    llvm::cl::desc("Point at the given source location of the first AST file"));
 
+enum ProgActions {
+  PrintPoint,     // Just print the point-at node
+  PrintRefs,      // Print references of the point-at node
+  PrintDefs,      // Print definitions of the point-at node
+  PrintDecls      // Print declarations of the point-at node
+};
+
+static llvm::cl::opt<ProgActions> 
+ProgAction(
+        llvm::cl::desc("Choose action to perform on the pointed-at AST node:"),
+        llvm::cl::ZeroOrMore,
+           llvm::cl::init(PrintPoint),
+           llvm::cl::values(
+             clEnumValN(PrintRefs, "print-refs",
+                        "Print references"),
+             clEnumValN(PrintDefs, "print-defs",
+                        "Print definitions"),
+             clEnumValN(PrintDecls, "print-decls",
+                        "Print declarations"),
+             clEnumValEnd));
+
 static llvm::cl::opt<bool>
 DisableFree("disable-free",
            llvm::cl::desc("Disable freeing of memory on exit"),
            llvm::cl::init(false));
 
+static void ProcessDecl(Decl *D) {
+  assert(D);
+  llvm::raw_ostream &OS = llvm::outs();
+  
+  switch (ProgAction) {
+  default: assert(0);
+  case PrintRefs: {
+    NamedDecl *ND = dyn_cast<NamedDecl>(D);
+    if (!ND)
+      return;
+
+    DeclReferenceMap RefMap(ND->getASTContext());
+    for (DeclReferenceMap::astnode_iterator
+           I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
+      I->print(OS);
+    break;
+  }
+  
+  case PrintDefs: {
+    const Decl *DefD = 0;
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      const FunctionDecl *DFD = 0;
+      FD->getBody(DFD);
+      DefD = DFD;
+    } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+      const VarDecl *DVD = 0;
+      VD->getDefinition(DVD);
+      DefD = DVD;
+    } 
+
+    if (DefD)
+      ASTNode(DefD).print(OS);
+    break;    
+  }
+  
+  case PrintDecls :
+    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      while (FD) {
+        ASTNode(FD).print(OS);
+        FD = FD->getPreviousDeclaration();
+      }
+    } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+      while (VD) {
+        ASTNode(VD).print(OS);
+        VD = VD->getPreviousDeclaration();
+      }
+    } else
+      ASTNode(D).print(OS);
+    break;
+    
+  }
+}
+
+static void ProcessNode(ASTNode Node, IndexProvider &IdxProvider) {
+  assert(Node.isValid());
+
+  Decl *D = 0;
+  if (Node.hasStmt()) {
+    if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(Node.getStmt()))
+      D = RefExpr->getDecl();
+  } else {
+    D = Node.getDecl();
+  }
+  assert(D);
+
+  Entity *Ent = Entity::get(D, IdxProvider.getProgram());
+  // If there is no Entity associated with this Decl, it means that it's not
+  // visible to other translation units.
+  if (!Ent)
+    return ProcessDecl(D);
+
+  // Find the "same" Decl in other translation units and print information.
+  for (IndexProvider::translation_unit_iterator
+         I = IdxProvider.translation_units_begin(Ent),
+         E = IdxProvider.translation_units_end(Ent); I != E; ++I) {
+    TUnit *TU = static_cast<TUnit*>(*I);
+    Decl *OtherD = Ent->getDecl(TU->getASTContext());
+    assert(OtherD && "Couldn't resolve Entity");
+    ProcessDecl(OtherD);
+  }
+}
+
 static llvm::cl::list<std::string>
 InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>"));
 
@@ -60,25 +187,36 @@
                      "LLVM 'Clang' Indexing Test Bed: http://clang.llvm.org\n");
   
   FileManager FileMgr;
+
+  Program Prog;
+  IndexProvider IdxProvider(Prog);
+  llvm::SmallVector<TUnit*, 4> TUnits;
   
   // If no input was specified, read from stdin.
   if (InputFilenames.empty())
     InputFilenames.push_back("-");
 
-  // FIXME: Only the first AST file is used for now.
+  for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
+    const std::string &InFile = InputFilenames[i];
+    
+    std::string ErrMsg;
+    llvm::OwningPtr<ASTUnit> AST;
 
-  const std::string &InFile = InputFilenames[0];
-  
-  std::string ErrMsg;
-  llvm::OwningPtr<ASTUnit> AST;
+    AST.reset(ASTUnit::LoadFromPCHFile(InFile, FileMgr, &ErrMsg));
+    if (!AST) {
+      llvm::errs() << "[" << InFile << "] Error: " << ErrMsg << '\n';
+      return 1;
+    }
 
-  AST.reset(ASTUnit::LoadFromPCHFile(InFile, FileMgr, &ErrMsg));
-  if (!AST) {
-    llvm::errs() << "[" << InFile << "] Error: " << ErrMsg << '\n';
-    return 1;
+    TUnit *TU = new TUnit(AST.take(), InFile);
+    TUnits.push_back(TU);
+    
+    IdxProvider.IndexAST(TU);
   }
 
   ASTNode Node;
+  const std::string &FirstFile = TUnits[0]->Filename;
+  ASTUnit *FirstAST = TUnits[0]->AST.get();
 
   if (!PointAtLocation.empty()) {
     const std::string &Filename = PointAtLocation[0].FileName;
@@ -87,9 +225,9 @@
     // Safety check. Using an out-of-date AST file will only lead to crashes
     // or incorrect results.
     // FIXME: Check all the source files that make up the AST file.
-    const FileEntry *ASTFile = FileMgr.getFile(InFile);
+    const FileEntry *ASTFile = FileMgr.getFile(FirstFile);
     if (File->getModificationTime() > ASTFile->getModificationTime()) {
-      llvm::errs() << "[" << InFile << "] Error: " <<
+      llvm::errs() << "[" << FirstFile << "] Error: " <<
         "Pointing at a source file which was modified after creating "
         "the AST file\n";
       return 1;
@@ -102,44 +240,38 @@
     unsigned Line = PointAtLocation[0].Line;
     unsigned Col = PointAtLocation[0].Column;
 
-    SourceLocation Loc = AST->getSourceManager().getLocation(File, Line, Col);
+    SourceLocation Loc =
+      FirstAST->getSourceManager().getLocation(File, Line, Col);
     if (Loc.isInvalid()) {
-      llvm::errs() << "[" << InFile << "] Error: " <<
+      llvm::errs() << "[" << FirstFile << "] Error: " <<
         "Couldn't resolve source location (invalid location)\n";
       return 1;
     }
     
-    Node = ResolveLocationInAST(AST->getASTContext(), Loc);
+    Node = ResolveLocationInAST(FirstAST->getASTContext(), Loc);
     if (Node.isInvalid()) {
-      llvm::errs() << "[" << InFile << "] Error: " <<
+      llvm::errs() << "[" << FirstFile << "] Error: " <<
         "Couldn't resolve source location (no declaration found)\n";
       return 1;
     }
   }
   
   if (Node.isValid()) {
-    llvm::raw_ostream &OS = llvm::outs();
-    OS << "Declaration node at point: " << Node.getDecl()->getDeclKindName()
-       << " ";
-    if (NamedDecl *ND = dyn_cast<NamedDecl>(Node.getDecl()))
-      OS << ND->getNameAsString();
-    OS << "\n";
-    
-    if (const char *Comment =
-          AST->getASTContext().getCommentForDecl(Node.getDecl()))
-      OS << "Comment associated with this declaration:\n" << Comment << "\n";
-        
-    if (Node.getStmt()) {
-      OS << "Statement node at point: " << Node.getStmt()->getStmtClassName()
-         << " ";
-      Node.getStmt()->printPretty(OS, AST->getASTContext(), 0,
-                         PrintingPolicy(AST->getASTContext().getLangOptions()));
-      OS << "\n";
+    if (ProgAction == PrintPoint) {
+      llvm::raw_ostream &OS = llvm::outs();
+      Node.print(OS);
+      if (const char *Comment =
+            FirstAST->getASTContext().getCommentForDecl(Node.getDecl()))
+        OS << "Comment associated with this declaration:\n" << Comment << "\n";
+    } else {
+      ProcessNode(Node, IdxProvider);
     }
   }
 
-  if (DisableFree)
-    AST.take();
+  if (!DisableFree) {
+    for (int i=0, e=TUnits.size(); i != e; ++i)
+      delete TUnits[i];
+  }
 
   // Managed static deconstruction. Useful for making things like
   // -time-passes usable.

Modified: cfe/trunk/utils/test/TestRunner.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/test/TestRunner.py?rev=74803&r1=74802&r2=74803&view=diff

==============================================================================
--- cfe/trunk/utils/test/TestRunner.py (original)
+++ cfe/trunk/utils/test/TestRunner.py Sun Jul  5 17:22:35 2009
@@ -13,6 +13,7 @@
 #     %llvmgxx - llvm-g++ command
 #     %prcontext - prcontext.tcl script
 #     %t - temporary file name (derived from testcase name)
+#     %T - directory of temporary file name
 #
 
 import errno
@@ -116,6 +117,7 @@
                      ('%llvmgxx','llvm-g++ -emit-llvm -w'),
                      ('%prcontext','prcontext.tcl'),
                      ('%t',TEMPOUTPUT),
+                     ('%T',os.path.dirname(TEMPOUTPUT)),
                      (' clang ', ' ' + CLANG + ' '),
                      (' clang-cc ', ' ' + CLANGCC + ' ')]
     scriptLines = []





More information about the cfe-commits mailing list