Files
Sourcetrail/src/lib_cxx/data/parser/cxx/PreprocessorCallbacks.cpp
T
malte_langkabel 9e4a02a33a src: added optional indexer AST logging
* removed old AstVisitor
* added new implementation called CxxAstVisitor
* added CxxVerboseAstVisitor that may wrap the CxxAstVisitor to log the AST while visiting
* added the same structure for the Java visitors
* removed all the logs that were fired when recording stuff
* Added UI setting for verbose indexer logging.
* implemented AST name obfuscation for Java and Cxx
* unified test visitors for Java and Cxx
* implemented recording using directive decl
* removed most of the old onXxxParsed methods
2016-11-01 10:37:30 +01:00

194 lines
5.8 KiB
C++

#include "data/parser/cxx/PreprocessorCallbacks.h"
#include "clang/Driver/Util.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Lex/MacroArgs.h"
#include "utility/file/FileRegister.h"
#include "data/parser/ParserClient.h"
#include "data/parser/ParseLocation.h"
PreprocessorCallbacks::PreprocessorCallbacks(
clang::SourceManager& sourceManager, ParserClient* client, FileRegister* fileRegister
)
: m_sourceManager(sourceManager)
, m_client(client)
, m_fileRegister(fileRegister)
{
}
void PreprocessorCallbacks::FileChanged(
clang::SourceLocation location, FileChangeReason reason, clang::SrcMgr::CharacteristicKind, clang::FileID prevID)
{
FilePath filePath;
const clang::FileEntry *fileEntry = m_sourceManager.getFileEntryForID(m_sourceManager.getFileID(location));
if (fileEntry)
{
filePath = FilePath(fileEntry->getName()).canonical();
}
if (!filePath.empty() && m_fileRegister->hasFilePath(filePath) && !m_fileRegister->fileIsParsed(filePath))
{
m_currentPath = filePath;
if (reason == EnterFile && !m_fileRegister->includeFileIsParsed(filePath))
{
m_client->onFileParsed(m_fileRegister->getFileInfo(filePath));
m_fileRegister->markIncludeFileParsing(filePath);
}
}
else
{
m_currentPath = FilePath();
}
}
void PreprocessorCallbacks::InclusionDirective(
clang::SourceLocation hashLocation, const clang::Token& includeToken, llvm::StringRef fileName, bool isAngled,
clang::CharSourceRange fileNameRange, const clang::FileEntry* fileEntry, llvm::StringRef searchPath,
llvm::StringRef relativePath, const clang::Module* imported
){
if (!m_currentPath.empty() && fileEntry)
{
FilePath includedFilePath = FilePath(fileEntry->getName()).canonical();
if (m_fileRegister->hasFilePath(includedFilePath))
{
NameHierarchy referencedNameHierarchy;
referencedNameHierarchy.push(std::make_shared<NameElement>(includedFilePath.fileName()));
NameHierarchy contextNameHierarchy;
contextNameHierarchy.push(std::make_shared<NameElement>(m_currentPath.fileName()));
m_client->recordReference(
REFERENCE_INCLUDE,
referencedNameHierarchy,
contextNameHierarchy,
getParseLocation(fileNameRange.getAsRange())
);
}
}
}
void PreprocessorCallbacks::MacroDefined(const clang::Token& macroNameToken, const clang::MacroDirective* macroDirective)
{
if (!m_currentPath.empty())
{
// ignore builtin macros
if (m_sourceManager.getSpellingLoc(macroNameToken.getLocation()).printToString(m_sourceManager)[0] == '<')
{
return;
}
NameHierarchy nameHierarchy;
nameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
m_client->recordSymbol(
nameHierarchy,
SYMBOL_MACRO,
getParseLocation(macroNameToken),
getParseLocation(macroDirective->getMacroInfo())
);
}
}
void PreprocessorCallbacks::MacroUndefined(
const clang::Token& macroNameToken, const clang::MacroDefinition& macroDefinition)
{
onMacroUsage(macroNameToken);
}
void PreprocessorCallbacks::Defined(
const clang::Token& macroNameToken, const clang::MacroDefinition& macroDefinition, clang::SourceRange range)
{
onMacroUsage(macroNameToken);
}
void PreprocessorCallbacks::Ifdef(clang::SourceLocation location, const clang::Token& macroNameToken,
const clang::MacroDefinition& macroDefinition)
{
onMacroUsage(macroNameToken);
}
void PreprocessorCallbacks::Ifndef(clang::SourceLocation location, const clang::Token& macroNameToken,
const clang::MacroDefinition& macroDefinition)
{
onMacroUsage(macroNameToken);
}
void PreprocessorCallbacks::MacroExpands(
const clang::Token& macroNameToken, const clang::MacroDefinition& macroDirective,
clang::SourceRange range, const clang::MacroArgs* args
){
onMacroUsage(macroNameToken);
}
void PreprocessorCallbacks::onMacroUsage(const clang::Token& macroNameToken)
{
if (!m_currentPath.empty())
{
const ParseLocation loc = getParseLocation(macroNameToken);
NameHierarchy referencedNameHierarchy;
referencedNameHierarchy.push(std::make_shared<NameElement>(macroNameToken.getIdentifierInfo()->getName().str()));
NameHierarchy contextNameHierarchy;
contextNameHierarchy.push(std::make_shared<NameElement>(loc.filePath.fileName()));
m_client->recordReference(
REFERENCE_MACRO_USAGE,
referencedNameHierarchy,
contextNameHierarchy,
loc
);
}
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::Token& macroNameTok) const
{
const clang::SourceLocation& location = m_sourceManager.getSpellingLoc(macroNameTok.getLocation());
const clang::SourceLocation& endLocation = m_sourceManager.getSpellingLoc(macroNameTok.getEndLoc());
return ParseLocation(
m_sourceManager.getFilename(location),
m_sourceManager.getSpellingLineNumber(location),
m_sourceManager.getSpellingColumnNumber(location),
m_sourceManager.getSpellingLineNumber(endLocation),
m_sourceManager.getSpellingColumnNumber(endLocation) - 1
);
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::MacroInfo* macroInfo) const
{
clang::SourceLocation location = macroInfo->getDefinitionLoc();
clang::SourceLocation endLocation = macroInfo->getDefinitionEndLoc();
return ParseLocation(
m_sourceManager.getFilename(location),
m_sourceManager.getSpellingLineNumber(location),
m_sourceManager.getSpellingColumnNumber(location),
m_sourceManager.getSpellingLineNumber(endLocation),
m_sourceManager.getSpellingColumnNumber(endLocation) - 1
);
}
ParseLocation PreprocessorCallbacks::getParseLocation(const clang::SourceRange& sourceRange) const
{
if (sourceRange.isInvalid())
{
return ParseLocation();
}
const clang::PresumedLoc& presumedBegin = m_sourceManager.getPresumedLoc(sourceRange.getBegin(), false);
const clang::PresumedLoc& presumedEnd = m_sourceManager.getPresumedLoc(sourceRange.getEnd(), false);
return ParseLocation(
presumedBegin.getFilename(),
presumedBegin.getLine(),
presumedBegin.getColumn(),
presumedEnd.getLine(),
presumedEnd.getColumn() - 1
);
}