[cfe-commits] r98826 - in /cfe/trunk: include/clang-c/Index.h test/Index/annotate-tokens-pp.c tools/CIndex/CIndex.cpp tools/CIndex/CXCursor.cpp tools/CIndex/CXCursor.h

Douglas Gregor dgregor at apple.com
Thu Mar 18 08:23:44 PDT 2010


Author: dgregor
Date: Thu Mar 18 10:23:44 2010
New Revision: 98826

URL: http://llvm.org/viewvc/llvm-project?rev=98826&view=rev
Log:
More token-annotation experimentation, preprocessing the annotated
token sequence to detect macro instantiations (that produce at least
token). WIP.

Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/test/Index/annotate-tokens-pp.c
    cfe/trunk/tools/CIndex/CIndex.cpp
    cfe/trunk/tools/CIndex/CXCursor.cpp
    cfe/trunk/tools/CIndex/CXCursor.h

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=98826&r1=98825&r2=98826&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Mar 18 10:23:44 2010
@@ -800,9 +800,9 @@
      
   /* Preprocessing */
   CXCursor_PreprocessingDirective        = 500,
-  
+  CXCursor_MacroInstantiation            = 501,
   CXCursor_FirstPreprocessing            = CXCursor_PreprocessingDirective,
-  CXCursor_LastPreprocessing             = CXCursor_PreprocessingDirective
+  CXCursor_LastPreprocessing             = CXCursor_MacroInstantiation
 };
 
 /**

Modified: cfe/trunk/test/Index/annotate-tokens-pp.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens-pp.c?rev=98826&r1=98825&r2=98826&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-tokens-pp.c (original)
+++ cfe/trunk/test/Index/annotate-tokens-pp.c Thu Mar 18 10:23:44 2010
@@ -1,6 +1,6 @@
 #define BAR baz
-#define WIBBLE(X, Y)
-WIBBLE(int, float)
+#define WIBBLE(X, Y) X##Y
+float WIBBLE(int, float);
 int BAR;
 #include "foo.h"
 
@@ -17,14 +17,15 @@
 // CHECK: Punctuation: "," [2:17 - 2:18] preprocessing directive=
 // CHECK: Identifier: "Y" [2:19 - 2:20] preprocessing directive=
 // CHECK: Punctuation: ")" [2:20 - 2:21] preprocessing directive=
-// CHECK: Identifier: "WIBBLE" [3:1 - 3:7]
-// CHECK: Punctuation: "(" [3:7 - 3:8]
-// CHECK: Keyword: "int" [3:8 - 3:11]
-// CHECK: Punctuation: "," [3:11 - 3:12]
-// CHECK: Keyword: "float" [3:13 - 3:18]
-// CHECK: Punctuation: ")" [3:18 - 3:19]
+// CHECK: Identifier: "WIBBLE" [3:7 - 3:13] macro instantiation=
+// CHECK: Punctuation: "(" [3:13 - 3:14]
+// CHECK: Keyword: "int" [3:14 - 3:17]
+// CHECK: Punctuation: "," [3:17 - 3:18]
+// CHECK: Keyword: "float" [3:19 - 3:24]
+// CHECK: Punctuation: ")" [3:24 - 3:25]
+// CHECK: Punctuation: ";" [3:25 - 3:26]
 // CHECK: Keyword: "int" [4:1 - 4:4]
-// CHECK: Identifier: "BAR" [4:5 - 4:8]
+// CHECK: Identifier: "BAR" [4:5 - 4:8] macro instantiation=
 // CHECK: Punctuation: ";" [4:8 - 4:9]
 // CHECK: Punctuation: "#" [5:1 - 5:2] preprocessing directive=
 // CHECK: Identifier: "include" [5:2 - 5:9] preprocessing directive=

Modified: cfe/trunk/tools/CIndex/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CIndex.cpp?rev=98826&r1=98825&r2=98826&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CIndex.cpp (original)
+++ cfe/trunk/tools/CIndex/CIndex.cpp Thu Mar 18 10:23:44 2010
@@ -1522,6 +1522,8 @@
      return createCXString("attribute(iboutlet)");
   case CXCursor_PreprocessingDirective:
     return createCXString("preprocessing directive");
+  case CXCursor_MacroInstantiation:
+    return createCXString("macro instantiation");
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
@@ -1652,6 +1654,11 @@
     SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
     return cxloc::translateSourceLocation(getCursorContext(C), L);
   }
+
+  if (C.kind == CXCursor_MacroInstantiation) {
+    SourceLocation L = cxcursor::getCursorMacroInstantiation(C).getBegin();
+    return cxloc::translateSourceLocation(getCursorContext(C), L);
+  }
   
   if (!getCursorDecl(C))
     return clang_getNullLocation();
@@ -1708,6 +1715,11 @@
     SourceRange R = cxcursor::getCursorPreprocessingDirective(C);
     return cxloc::translateSourceRange(getCursorContext(C), R);
   }
+
+  if (C.kind == CXCursor_MacroInstantiation) {
+    SourceRange R = cxcursor::getCursorMacroInstantiation(C);
+    return cxloc::translateSourceRange(getCursorContext(C), R);
+  }
   
   if (!getCursorDecl(C))
     return clang_getNullRange();
@@ -2017,6 +2029,17 @@
 // Token-based Operations.
 //===----------------------------------------------------------------------===//
 
+namespace {
+/// IgnoringDiagClient - This is a diagnostic client that just ignores all
+/// diags.
+class IgnoringDiagClient : public DiagnosticClient {
+  void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                        const DiagnosticInfo &Info) {
+    // Just ignore it.
+  }
+};
+}
+
 /* CXToken layout:
  *   int_data[0]: a CXTokenKind
  *   int_data[1]: starting token location
@@ -2281,9 +2304,8 @@
     // Lex tokens in raw mode until we hit the end of the range, to avoid 
     // entering #includes or expanding macros.
     std::vector<Token> TokenStream;
-    const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
     Preprocessor &PP = CXXUnit->getPreprocessor();
-    while (Lex.getBufferLocation() <= EffectiveBufferEnd) {
+    while (true) {
       Token Tok;
       Lex.LexFromRawLexer(Tok);
       
@@ -2311,23 +2333,21 @@
           Annotated[Locations[I].getRawEncoding()] = Cursor;
         }
         
-        if (Tok.is(tok::eof))
-          break;
-        
         if (Tok.isAtStartOfLine())
           goto reprocess;
         
         continue;
       }
       
-      // If this is a ## token, change its kind to unknown so that repreprocessing
-      // it will not produce an error.
+      // If this is a ## token, change its kind to unknown so that
+      // repreprocessing it will not produce an error.
       if (Tok.is(tok::hashhash))
         Tok.setKind(tok::unknown);
       
-      // If this raw token is an identifier, the raw lexer won't have looked up
-      // the corresponding identifier info for it.  Do this now so that it will be
-      // macro expanded when we re-preprocess it.
+      // If this raw token is an identifier, the raw lexer won't have
+      // looked up the corresponding identifier info for it.  Do this
+      // now so that it will be macro expanded when we re-preprocess
+      // it.
       if (Tok.is(tok::identifier)) {
         // Change the kind of this identifier to the appropriate token kind, e.g.
         // turning "for" into a keyword.
@@ -2336,9 +2356,67 @@
       
       TokenStream.push_back(Tok);
       
-      if (Tok.is(tok::eof)) 
+      if (Tok.is(tok::eof))
         break;
     }
+
+    // Temporarily change the diagnostics object so that we ignore any
+    // generated diagnostics from this pass.
+    IgnoringDiagClient TmpDC;
+    Diagnostic TmpDiags(&TmpDC);
+    Diagnostic *OldDiags = &PP.getDiagnostics();
+    PP.setDiagnostics(TmpDiags);
+
+    // Inform the preprocessor that we don't want comments.
+    PP.SetCommentRetentionState(false, false);
+    
+    // Enter the tokens we just lexed.  This will cause them to be macro expanded
+    // but won't enter sub-files (because we removed #'s).
+    PP.EnterTokenStream(&TokenStream[0], TokenStream.size(), false, false);
+
+    // Lex all the tokens.
+    Token Tok;
+    PP.Lex(Tok);
+    while (Tok.isNot(tok::eof)) {
+      // Ignore non-macro tokens.
+      if (!Tok.getLocation().isMacroID()) {
+        PP.Lex(Tok);
+        continue;
+      }
+
+      // Okay, we have the first token of a macro expansion. Keep
+      // track of the range of the macro expansion.
+      std::pair<SourceLocation, SourceLocation> LLoc =
+        SourceMgr.getInstantiationRange(Tok.getLocation());
+
+      // Ignore tokens whose instantiation location was not the main file.
+      if (SourceMgr.getFileID(LLoc.first) != BeginLocInfo.first) {
+        PP.Lex(Tok);
+        continue;
+      }
+
+      assert(SourceMgr.getFileID(LLoc.second) == BeginLocInfo.first &&
+             "Start and end of expansion must be in the same ultimate file!");
+
+      // Okay, eat this token, getting the next one.
+      PP.Lex(Tok);
+
+      // Skip all the rest of the tokens that are part of this macro
+      // instantiation.  It would be really nice to pop up a window with all the
+      // spelling of the tokens or something.
+      while (!Tok.is(tok::eof) &&
+             SourceMgr.getInstantiationLoc(Tok.getLocation()) == LLoc.first)
+        PP.Lex(Tok);
+
+      CXCursor Cursor
+        = cxcursor::MakeMacroInstantiationCursor(SourceRange(LLoc.first, 
+                                                             LLoc.second), 
+                                                 CXXUnit);
+      Annotated[LLoc.first.getRawEncoding()] = Cursor;
+    }
+
+    // Restore diagnostics object back to its own thing.
+    PP.setDiagnostics(*OldDiags);
   }
   
   for (unsigned I = 0; I != NumTokens; ++I) {

Modified: cfe/trunk/tools/CIndex/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CXCursor.cpp?rev=98826&r1=98825&r2=98826&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CXCursor.cpp (original)
+++ cfe/trunk/tools/CIndex/CXCursor.cpp Thu Mar 18 10:23:44 2010
@@ -314,6 +314,24 @@
                                       reinterpret_cast<uintptr_t> (C.data[1])));
 }
 
+CXCursor cxcursor::MakeMacroInstantiationCursor(SourceRange Range, 
+                                                ASTUnit *TU) {
+  CXCursor C = { CXCursor_MacroInstantiation, 
+                 { reinterpret_cast<void *>(Range.getBegin().getRawEncoding()),
+                   reinterpret_cast<void *>(Range.getEnd().getRawEncoding()),
+                   TU }
+               };
+  return C;
+}
+
+SourceRange cxcursor::getCursorMacroInstantiation(CXCursor C) {
+  assert(C.kind == CXCursor_MacroInstantiation);
+  return SourceRange(SourceLocation::getFromRawEncoding(
+                                      reinterpret_cast<uintptr_t> (C.data[0])),
+                     SourceLocation::getFromRawEncoding(
+                                      reinterpret_cast<uintptr_t> (C.data[1])));
+}
+
 Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
   return (Decl *)Cursor.data[0];
 }

Modified: cfe/trunk/tools/CIndex/CXCursor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/CIndex/CXCursor.h?rev=98826&r1=98825&r2=98826&view=diff
==============================================================================
--- cfe/trunk/tools/CIndex/CXCursor.h (original)
+++ cfe/trunk/tools/CIndex/CXCursor.h Thu Mar 18 10:23:44 2010
@@ -78,7 +78,14 @@
 
 /// \brief Unpack a given preprocessing directive to retrieve its source range.
 SourceRange getCursorPreprocessingDirective(CXCursor C);
-  
+
+/// \brief Create a macro instantiation cursor.
+CXCursor MakeMacroInstantiationCursor(SourceRange Range, ASTUnit *TU);
+
+/// \brief Unpack a given macro instantiation cursor to retrieve its
+/// source range.
+SourceRange getCursorMacroInstantiation(CXCursor C);
+
 Decl *getCursorDecl(CXCursor Cursor);
 Expr *getCursorExpr(CXCursor Cursor);
 Stmt *getCursorStmt(CXCursor Cursor);





More information about the cfe-commits mailing list