[cfe-commits] r171773 - in /cfe/trunk: test/Index/c-index-getCursor-pp.c tools/libclang/CIndex.cpp tools/libclang/CIndexHigh.cpp tools/libclang/CIndexer.h tools/libclang/CXCursor.cpp tools/libclang/CXCursor.h

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Jan 7 11:16:26 PST 2013


Author: akirtzidis
Date: Mon Jan  7 13:16:25 2013
New Revision: 171773

URL: http://llvm.org/viewvc/llvm-project?rev=171773&view=rev
Log:
[libclang] When getting the cursor for an identifier inside a macro definition, check if
this was ever a macro name and return a specific CXCursor_MacroExpansion cursor in such a case,
instead of the generic CXCursor_MacroDefinition.

Checking for macro name makes sure the identifier is not part of the identifier list in a
function macro.
While, in general, resolving identifiers in macro definitions to other macros may not be completely accurate,
it greatly improves functionality such as give-me-the-definition-of-this, which was not working at all
inside macro definitions.

Modified:
    cfe/trunk/test/Index/c-index-getCursor-pp.c
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CIndexHigh.cpp
    cfe/trunk/tools/libclang/CIndexer.h
    cfe/trunk/tools/libclang/CXCursor.cpp
    cfe/trunk/tools/libclang/CXCursor.h

Modified: cfe/trunk/test/Index/c-index-getCursor-pp.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/c-index-getCursor-pp.c?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/test/Index/c-index-getCursor-pp.c (original)
+++ cfe/trunk/test/Index/c-index-getCursor-pp.c Mon Jan  7 13:16:25 2013
@@ -1,6 +1,6 @@
 #define OBSCURE(X) X
 #define DECORATION
-
+#define FNM(X) OBSCURE(X)
 typedef int T;
 void OBSCURE(func)(int x) {
   OBSCURE(T) DECORATION value;
@@ -23,6 +23,8 @@
 #if defined(OBSCURE)
 #endif
 
+#define C(A) A
+
 // RUN: c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s
 // CHECK-1: macro definition=OBSCURE
 // RUN: c-index-test -cursor-at=%s:2:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-2 %s
@@ -45,8 +47,17 @@
 // CHECK-10: 20:8 macro expansion=OBSCURE
 // CHECK-10: 23:13 macro expansion=OBSCURE
 
+// RUN: c-index-test -cursor-at=%s:3:20 -cursor-at=%s:12:14 \
+// RUN:              -cursor-at=%s:26:11 -cursor-at=%s:26:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-IN-MACRODEF %s
+// CHECK-IN-MACRODEF: 3:16 macro expansion=OBSCURE
+// CHECK-IN-MACRODEF: 12:14 macro expansion=A
+// CHECK-IN-MACRODEF: 26:9 macro definition=C
+// CHECK-IN-MACRODEF: 26:9 macro definition=C
+
 // Same tests, but with "editing" optimizations
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:1:11 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-1 %s
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:2:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-2 %s
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:5:7 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-3 %s
 // RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:9:10 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-6 %s
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -cursor-at=%s:3:20 -cursor-at=%s:12:14 \
+// RUN:              -cursor-at=%s:26:11 -cursor-at=%s:26:14 -I%S/Inputs %s | FileCheck -check-prefix=CHECK-IN-MACRODEF %s

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Mon Jan  7 13:16:25 2013
@@ -520,6 +520,19 @@
                                                     A->getInterfaceLoc(), TU));
   }
 
+  // If pointing inside a macro definition, check if the token is an identifier
+  // that was ever defined as a macro. In such a case, create a "pseudo" macro
+  // expansion cursor for that token.
+  SourceLocation BeginLoc = RegionOfInterest.getBegin();
+  if (Cursor.kind == CXCursor_MacroDefinition &&
+      BeginLoc == RegionOfInterest.getEnd()) {
+    SourceLocation Loc = AU->mapLocationToPreamble(BeginLoc);
+    MacroInfo *MI = getMacroInfo(cxcursor::getCursorMacroDefinition(Cursor),TU);
+    if (MacroDefinition *MacroDef =
+          checkForMacroInMacroDefinition(MI, Loc, TU))
+      return Visit(cxcursor::MakeMacroExpansionCursor(MacroDef, BeginLoc, TU));
+  }
+
   // Nothing to visit at the moment.
   return false;
 }
@@ -3185,7 +3198,7 @@
   }
   
   if (C.kind == CXCursor_MacroExpansion)
-    return createCXString(getCursorMacroExpansion(C)->getName()
+    return createCXString(getCursorMacroExpansion(C).getName()
                                                            ->getNameStart());
 
   if (C.kind == CXCursor_MacroDefinition)
@@ -3999,7 +4012,7 @@
 
   if (C.kind == CXCursor_MacroExpansion) {
     SourceLocation L
-      = cxcursor::getCursorMacroExpansion(C)->getSourceRange().getBegin();
+      = cxcursor::getCursorMacroExpansion(C).getSourceRange().getBegin();
     return cxloc::translateSourceLocation(getCursorContext(C), L);
   }
 
@@ -4125,7 +4138,7 @@
 
   if (C.kind == CXCursor_MacroExpansion) {
     ASTUnit *TU = getCursorASTUnit(C);
-    SourceRange Range = cxcursor::getCursorMacroExpansion(C)->getSourceRange();
+    SourceRange Range = cxcursor::getCursorMacroExpansion(C).getSourceRange();
     return TU->mapRangeFromPreamble(Range);
   }
 
@@ -4265,7 +4278,7 @@
   }
   
   if (C.kind == CXCursor_MacroExpansion) {
-    if (MacroDefinition *Def = getCursorMacroExpansion(C)->getDefinition())
+    if (MacroDefinition *Def = getCursorMacroExpansion(C).getDefinition())
       return MakeMacroDefinitionCursor(Def, tu);
   }
 
@@ -5265,7 +5278,7 @@
     if (cursor.kind != CXCursor_MacroExpansion)
       return CXChildVisit_Continue;
 
-    SourceRange macroRange = getCursorMacroExpansion(cursor)->getSourceRange();
+    SourceRange macroRange = getCursorMacroExpansion(cursor).getSourceRange();
     if (macroRange.getBegin() == macroRange.getEnd())
       return CXChildVisit_Continue; // it's not a function macro.
 
@@ -6169,6 +6182,100 @@
 #endif
 }
 
+MacroInfo *cxindex::getMacroInfo(const IdentifierInfo &II,
+                                 SourceLocation MacroDefLoc,
+                                 CXTranslationUnit TU){
+  if (MacroDefLoc.isInvalid() || !TU)
+    return 0;
+
+  ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+  Preprocessor &PP = Unit->getPreprocessor();
+  if (!II.hadMacroDefinition())
+    return 0;
+
+  MacroInfo *MI = PP.getMacroInfoHistory(const_cast<IdentifierInfo*>(&II));
+  while (MI) {
+    if (MacroDefLoc == MI->getDefinitionLoc())
+      return MI;
+    MI = MI->getPreviousDefinition();
+  }
+
+  return 0;
+}
+
+MacroInfo *cxindex::getMacroInfo(MacroDefinition *MacroDef,
+                                 CXTranslationUnit TU) {
+  if (!MacroDef || !TU)
+    return 0;
+  const IdentifierInfo *II = MacroDef->getName();
+  if (!II)
+    return 0;
+
+  return getMacroInfo(*II, MacroDef->getLocation(), TU);
+}
+
+MacroDefinition *cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI,
+                                                         const Token &Tok,
+                                                         CXTranslationUnit TU) {
+  if (!MI || !TU)
+    return 0;
+  if (Tok.isNot(tok::raw_identifier))
+    return 0;
+
+  if (MI->getNumTokens() == 0)
+    return 0;
+  SourceRange DefRange(MI->getReplacementToken(0).getLocation(),
+                       MI->getDefinitionEndLoc());
+  ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+
+  // Check that the token is inside the definition and not its argument list.
+  SourceManager &SM = Unit->getSourceManager();
+  if (SM.isBeforeInTranslationUnit(Tok.getLocation(), DefRange.getBegin()))
+    return 0;
+  if (SM.isBeforeInTranslationUnit(DefRange.getEnd(), Tok.getLocation()))
+    return 0;
+
+  Preprocessor &PP = Unit->getPreprocessor();
+  PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
+  if (!PPRec)
+    return 0;
+
+  StringRef Name(Tok.getRawIdentifierData(), Tok.getLength());
+  IdentifierInfo &II = PP.getIdentifierTable().get(Name);
+  if (!II.hadMacroDefinition())
+    return 0;
+
+  // Check that the identifier is not one of the macro arguments.
+  if (std::find(MI->arg_begin(), MI->arg_end(), &II) != MI->arg_end())
+    return 0;
+
+  MacroInfo *InnerMI = PP.getMacroInfoHistory(&II);
+  if (!InnerMI)
+    return 0;
+
+  return PPRec->findMacroDefinition(InnerMI);
+}
+
+MacroDefinition *cxindex::checkForMacroInMacroDefinition(const MacroInfo *MI,
+                                                         SourceLocation Loc,
+                                                         CXTranslationUnit TU) {
+  if (Loc.isInvalid() || !MI || !TU)
+    return 0;
+
+  if (MI->getNumTokens() == 0)
+    return 0;
+  ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+  Preprocessor &PP = Unit->getPreprocessor();
+  if (!PP.getPreprocessingRecord())
+    return 0;
+  Loc = Unit->getSourceManager().getSpellingLoc(Loc);
+  Token Tok;
+  if (PP.getRawToken(Loc, Tok))
+    return 0;
+
+  return checkForMacroInMacroDefinition(MI, Tok, TU);
+}
+
 extern "C" {
 
 CXString clang_getClangVersion() {

Modified: cfe/trunk/tools/libclang/CIndexHigh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexHigh.cpp?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexHigh.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexHigh.cpp Mon Jan  7 13:16:25 2013
@@ -266,7 +266,7 @@
   if (cursor.kind == CXCursor_MacroDefinition)
     Macro = getCursorMacroDefinition(cursor)->getName();
   else if (cursor.kind == CXCursor_MacroExpansion)
-    Macro = getCursorMacroExpansion(cursor)->getName();
+    Macro = getCursorMacroExpansion(cursor).getName();
   if (!Macro)
     return CXChildVisit_Continue;
 
@@ -317,7 +317,7 @@
   if (Cursor.kind == CXCursor_MacroDefinition)
     Macro = getCursorMacroDefinition(Cursor)->getName();
   else
-    Macro = getCursorMacroExpansion(Cursor)->getName();
+    Macro = getCursorMacroExpansion(Cursor).getName();
   if (!Macro)
     return;
 

Modified: cfe/trunk/tools/libclang/CIndexer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexer.h?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexer.h (original)
+++ cfe/trunk/tools/libclang/CIndexer.h Mon Jan  7 13:16:25 2013
@@ -26,6 +26,11 @@
 
 namespace clang {
   class ASTUnit;
+  class MacroInfo;
+  class MacroDefinition;
+  class SourceLocation;
+  class Token;
+  class IdentifierInfo;
 
 class CIndexer {
   bool OnlyLocalDecls;
@@ -94,6 +99,29 @@
 
   namespace cxindex {
     void printDiagsToStderr(ASTUnit *Unit);
+
+    /// \brief If \c MacroDefLoc points at a macro definition with \c II as
+    /// its name, this retrieves its MacroInfo.
+    MacroInfo *getMacroInfo(const IdentifierInfo &II,
+                            SourceLocation MacroDefLoc,
+                            CXTranslationUnit TU);
+
+    /// \brief Retrieves the corresponding MacroInfo of a MacroDefinition.
+    MacroInfo *getMacroInfo(MacroDefinition *MacroDef, CXTranslationUnit TU);
+
+    /// \brief If \c Loc resides inside the definition of \c MI and it points at
+    /// an identifier that has ever been a macro name, this returns the latest
+    /// MacroDefinition for that name, otherwise it returns NULL.
+    MacroDefinition *checkForMacroInMacroDefinition(const MacroInfo *MI,
+                                                    SourceLocation Loc,
+                                                    CXTranslationUnit TU);
+
+    /// \brief If \c Tok resides inside the definition of \c MI and it points at
+    /// an identifier that has ever been a macro name, this returns the latest
+    /// MacroDefinition for that name, otherwise it returns NULL.
+    MacroDefinition *checkForMacroInMacroDefinition(const MacroInfo *MI,
+                                                    const Token &Tok,
+                                                    CXTranslationUnit TU);
   }
 }
 

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Mon Jan  7 13:16:25 2013
@@ -677,9 +677,28 @@
   return C;
 }
 
-MacroExpansion *cxcursor::getCursorMacroExpansion(CXCursor C) {
-  assert(C.kind == CXCursor_MacroExpansion);
-  return static_cast<MacroExpansion *>(C.data[0]);
+CXCursor cxcursor::MakeMacroExpansionCursor(MacroDefinition *MI,
+                                            SourceLocation Loc,
+                                            CXTranslationUnit TU) {
+  assert(Loc.isValid());
+  CXCursor C = { CXCursor_MacroExpansion, 0, { MI, Loc.getPtrEncoding(), TU } };
+  return C;
+}
+
+const IdentifierInfo *cxcursor::MacroExpansionCursor::getName() const {
+  if (isPseudo())
+    return getAsMacroDefinition()->getName();
+  return getAsMacroExpansion()->getName();
+}
+MacroDefinition *cxcursor::MacroExpansionCursor::getDefinition() const {
+  if (isPseudo())
+    return getAsMacroDefinition();
+  return getAsMacroExpansion()->getDefinition();
+}
+SourceRange cxcursor::MacroExpansionCursor::getSourceRange() const {
+  if (isPseudo())
+    return getPseudoLoc();
+  return getAsMacroExpansion()->getSourceRange();
 }
 
 CXCursor cxcursor::MakeInclusionDirectiveCursor(InclusionDirective *ID, 

Modified: cfe/trunk/tools/libclang/CXCursor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.h?rev=171773&r1=171772&r2=171773&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.h (original)
+++ cfe/trunk/tools/libclang/CXCursor.h Mon Jan  7 13:16:25 2013
@@ -42,6 +42,7 @@
 class TemplateName;
 class TypeDecl;
 class VarDecl;
+class IdentifierInfo;
   
 namespace cxcursor {
 
@@ -153,9 +154,51 @@
 CXCursor MakeMacroExpansionCursor(MacroExpansion *,
                                   CXTranslationUnit TU);
 
-/// \brief Unpack a given macro expansion cursor to retrieve its
-/// source range.
-MacroExpansion *getCursorMacroExpansion(CXCursor C);
+/// \brief Create a "pseudo" macro expansion cursor, using a macro definition
+/// and a source location.
+CXCursor MakeMacroExpansionCursor(MacroDefinition *, SourceLocation Loc,
+                                  CXTranslationUnit TU);
+
+/// \brief Wraps a macro expansion cursor and provides a common interface
+/// for a normal macro expansion cursor or a "pseudo" one.
+///
+/// "Pseudo" macro expansion cursors (essentially a macro definition along with
+/// a source location) are created in special cases, for example they can be
+/// created for identifiers inside macro definitions, if these identifiers are
+/// macro names.
+class MacroExpansionCursor {
+  CXCursor C;
+
+  bool isPseudo() const {
+    return C.data[1] != 0;
+  }
+  MacroDefinition *getAsMacroDefinition() const {
+    assert(isPseudo());
+    return static_cast<MacroDefinition *>(C.data[0]);
+  }
+  MacroExpansion *getAsMacroExpansion() const {
+    assert(!isPseudo());
+    return static_cast<MacroExpansion *>(C.data[0]);
+  }
+  SourceLocation getPseudoLoc() const {
+    assert(isPseudo());
+    return SourceLocation::getFromPtrEncoding(C.data[1]);
+  }
+
+public:
+  MacroExpansionCursor(CXCursor C) : C(C) {
+    assert(C.kind == CXCursor_MacroExpansion);
+  }
+
+  const IdentifierInfo *getName() const;
+  MacroDefinition *getDefinition() const;
+  SourceRange getSourceRange() const;
+};
+
+/// \brief Unpack a given macro expansion cursor to retrieve its info.
+static inline MacroExpansionCursor getCursorMacroExpansion(CXCursor C) {
+  return C;
+}
 
 /// \brief Create an inclusion directive cursor.
 CXCursor MakeInclusionDirectiveCursor(InclusionDirective *,





More information about the cfe-commits mailing list