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()); }
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; }
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()); }