void PreprocessorCallback::Defined(const clang::Token& MacroNameTok, MyMacroDefinition MD,
                                   clang::SourceRange Range)
{
    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;

    clang::SourceManager &sm = annotator.getSourceMgr();

    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str();
    std::string link;
    std::string dataProj;
    clang::SourceLocation defLoc;
    clang::FileID defFID;

    if (MD) {
#if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR >= 7
        auto *MI = MD.getMacroInfo();
#else
        auto *MI = MD->getMacroInfo();
#endif
        if (MI) {
            defLoc = MI->getDefinitionLoc();
            defFID = sm.getFileID(defLoc);
        }
    }

    if (defFID.isInvalid() || defFID != FID) {
        if (!defFID.isInvalid()) {
            link = annotator.pathTo(FID, defFID, &dataProj);
        }
        if (link.empty()) {
            std::string tag = "class=\"macro\" data-ref=\"" % ref % "\"";
            annotator.generator(FID).addTag("span", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
            return;
        }

        if (!dataProj.empty()) {
            dataProj = " data-proj=\"" % dataProj % "\"";
        }
    }

    if (sm.getMainFileID() != defFID) {
        annotator.registerMacro(ref, MacroNameTok.getLocation(), Annotator::Use_Address);
    }

    std::string tag = "class=\"macro\" href=\"" % link % "#" % llvm::Twine(sm.getExpansionLineNumber(defLoc)).str()
        % "\" data-ref=\"" % ref % "\"" % dataProj;
    annotator.generator(FID).addTag("a", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
}
Пример #2
0
bool PragmaRecorder::GetPragmaNameFromToken(const clang::Token &Token,
        std::string &PragmaName) {
    if (Token.isLiteral())
        PragmaName.assign(Token.getLiteralData(), Token.getLength());
    else if (Token.is(clang::tok::identifier))
        PragmaName.assign(Token.getIdentifierInfo()->getNameStart(),
                          Token.getIdentifierInfo()->getLength());
    else
        return false;
    return true;
}
Пример #3
0
static best_guess num_type(clang::Preprocessor &pp,
                           const clang::Token &t) {
    llvm::StringRef sr(t.getLiteralData(), t.getLength());
    clang::NumericLiteralParser parser(sr, t.getLocation(), pp);

    if(parser.isIntegerLiteral())
        return tok_int;
    if(parser.isFloatingLiteral())
        return tok_float;

    return tok_invalid;
}
void PreprocessorCallback::MacroExpands(const clang::Token& MacroNameTok,
                                        const clang::MacroInfo* MI,
                                        clang::SourceRange Range)
{
    if (disabled)
        return;

    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;
    clang::SourceManager &sm = annotator.getSourceMgr();
    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    const char *begin = sm.getCharacterData(Range.getBegin());
    int len = sm.getCharacterData(Range.getEnd()) - begin;
    len += clang::Lexer::MeasureTokenLength(Range.getEnd(), sm, PP.getLangOpts());

    std::string copy(begin, len);
    begin = copy.c_str();
    clang::Lexer lex(loc, PP.getLangOpts(), begin, begin, begin + len);
    std::vector<clang::Token> tokens;
    std::string expansion;

    //Lousely based on code from clang::html::HighlightMacros

    // Lex all the tokens in raw mode, to avoid entering #includes or expanding
    // macros.
    clang::Token tok;
    do {
        lex.LexFromRawLexer(tok);

        // If this is a # at the start of a line, discard it from the token stream.
        // We don't want the re-preprocess step to see #defines, #includes or other
        // preprocessor directives.
        if (tok.is(clang::tok::hash) && tok.isAtStartOfLine())
            continue;

        // If this is a ## token, change its kind to unknown so that repreprocessing
        // it will not produce an error.
        if (tok.is(clang::tok::hashhash))
            tok.setKind(clang::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 (tok.is(clang::tok::raw_identifier))
            PP.LookUpIdentifierInfo(tok);

        tokens.push_back(tok);

    } while(!tok.is(clang::tok::eof));

    // Temporarily change the diagnostics object so that we ignore any generated
    // diagnostics from this pass.
    clang::DiagnosticsEngine TmpDiags(PP.getDiagnostics().getDiagnosticIDs(),
#if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>=2
                                      &PP.getDiagnostics().getDiagnosticOptions(),
#endif
                                      new clang::IgnoringDiagConsumer);

    disabled = true;
    clang::DiagnosticsEngine *OldDiags = &PP.getDiagnostics();
    PP.setDiagnostics(TmpDiags);

    PP.EnterTokenStream(tokens.data(), tokens.size(), false, false);

    PP.Lex(tok);
    while(tok.isNot(clang::tok::eof)) {
        // If the tokens were already space separated, or if they must be to avoid
        // them being implicitly pasted, add a space between them.
        if (tok.hasLeadingSpace())
            expansion += ' ';
           // ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok)) //FIXME
        // Escape any special characters in the token text.
        expansion += PP.getSpelling(tok);
        PP.Lex(tok);
    }

    PP.setDiagnostics(*OldDiags);
    disabled = false;

    expansion = Generator::escapeAttr(expansion);

    clang::SourceLocation defLoc = MI->getDefinitionLoc();
    clang::FileID defFID = sm.getFileID(defLoc);
    std::string link;
    if (defFID != FID)
        link = annotator.pathTo(FID, defFID);
    std::string tag = "class=\"macro\" href=\"" % link % "#" % llvm::Twine(sm.getExpansionLineNumber(defLoc)).str()
                    % "\" title=\"" % expansion % "\"";
    annotator.generator(FID).addTag("a", tag, sm.getFileOffset(loc), MacroNameTok.getLength());
}
void PreprocessorCallback::MacroDefined(const clang::Token& MacroNameTok, const clang::MacroDirective *MD)
{
    clang::SourceLocation loc = MacroNameTok.getLocation();
    if (!loc.isValid() || !loc.isFileID())
        return;

    clang::SourceManager &sm = annotator.getSourceMgr();
    clang::FileID FID = sm.getFileID(loc);
    if (!annotator.shouldProcess(FID))
        return;

    std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str();

    if (sm.getMainFileID() != FID) {
        annotator.registerMacro(ref, MacroNameTok.getLocation(), Annotator::Declaration);
    }

    annotator.generator(FID).addTag("dfn", "class=\"macro\" id=\""% ref %"\" data-ref=\"" % ref % "\"", sm.getFileOffset(loc), MacroNameTok.getLength());
}