diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-29 03:14:11 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-29 03:14:11 +0000 |
commit | b49e728a4d1a84b72f3aebf60ff494684f9cb004 (patch) | |
tree | 95adfffe4770e34404e95d2aa0371722a8b5b349 /tools/libclang/CIndexHigh.cpp | |
parent | 375f7c48428ef64920dab4017a056ee1d6989ed1 (diff) | |
download | clang-b49e728a4d1a84b72f3aebf60ff494684f9cb004.tar.gz clang-b49e728a4d1a84b72f3aebf60ff494684f9cb004.tar.bz2 clang-b49e728a4d1a84b72f3aebf60ff494684f9cb004.tar.xz |
[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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145369 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/libclang/CIndexHigh.cpp')
-rw-r--r-- | tools/libclang/CIndexHigh.cpp | 112 |
1 files changed, 108 insertions, 4 deletions
diff --git a/tools/libclang/CIndexHigh.cpp b/tools/libclang/CIndexHigh.cpp index 0b36af3c95..a2a585454e 100644 --- a/tools/libclang/CIndexHigh.cpp +++ b/tools/libclang/CIndexHigh.cpp @@ -168,7 +168,8 @@ static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor, 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 @@ static enum CXChildVisitResult findFileIdRefVisit(CXCursor cursor, 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 @@ static void findIdRefsInFile(CXTranslationUnit TU, CXCursor declCursor, 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 @@ void clang_findReferencesInFile(CXCursor cursor, CXFile file, 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.: // |