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()); }
void PragmaRecorder::HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducerKind Introducer, clang::Token &FirstToken) { clang::Token &CurrentToken = FirstToken; std::string PragmaName, PragmaValue = ""; // Pragma in ACC should be a name/value pair if (GetPragmaNameFromToken(FirstToken, PragmaName)) { // start parsing the value '(' PragmaValue ')', if we have one. const clang::Token* NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::l_paren)) PP.LexUnexpandedToken(CurrentToken); else goto end_parsing_pragma_value; NextToken = &PP.LookAhead(0); if (GetPragmaValueFromToken(*NextToken, PragmaValue)) { PP.Lex(CurrentToken); } else { PP.LexUnexpandedToken(CurrentToken); PP.Diag(NextToken->getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "expected value after '#pragma %0('")) << PragmaName; return; } if (!NextToken->is(clang::tok::r_paren)) { NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::r_paren)) { PP.LexUnexpandedToken(CurrentToken); } else { PP.LexUnexpandedToken(CurrentToken); PP.Diag(NextToken->getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "missing ')' after '#pragma %0(%1'")) << PragmaName << PragmaValue; return; } } } else { PP.Diag(FirstToken.getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "no pragma name or value")); return; } end_parsing_pragma_value: // PragmaValue may be an empty string. mPragmas->push_back(make_pair(PragmaName, PragmaValue)); // Inform lex to eat the token PP.LexUnexpandedToken(CurrentToken); return; }
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()); }
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 FMacroCallback::MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD) { auto MacroName = MacroNameTok.getIdentifierInfo()->getName(); if (IsMacroDefinedInCommandLine(MacroName) || IsBuiltInMacro(MD) || IsPredefinedMacro(MacroName)) { return; } auto MacroDefinitionFile = FString(SourceManager.getFilename(MacroNameTok.getLocation()).data()); MacroDefinitionFile.ReplaceInline(TEXT("\\"), TEXT("/")); if (MacroDefinitionFile.IsEmpty()) { OutputFileContents.Logf(TEXT("Found unexpected definition of macro %s."), ANSI_TO_TCHAR(MacroName.data())); } MacroDefinitionToFile.Add(MacroName.data(), MacroDefinitionFile); }
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()); }
static clang::SourceLocation GetFromLiteral(clang::Token Tok, clang::StringLiteral *Lit, clang::Preprocessor &PP) { return Lit->getLocationOfByte(PP.getSourceManager().getFileOffset(Tok.getLocation()), PP.getSourceManager(), PP.getLangOpts(), PP.getTargetInfo()); }