static Optional<std::pair<llvm::APSInt, Type>> getIntegerConstantForMacroToken(ClangImporter::Implementation &impl, DeclContext *DC, const clang::Token &token) { // Integer literal. if (token.is(clang::tok::numeric_constant)) { if (auto literal = parseNumericLiteral<clang::IntegerLiteral>(impl,token)) { auto value = llvm::APSInt { literal->getValue(), literal->getType()->isUnsignedIntegerType() }; auto type = impl.importType(literal->getType(), ImportTypeKind::Value, isInSystemModule(DC), Bridgeability::None); return {{ value, type }}; } // Macro identifier. } else if (token.is(clang::tok::identifier) && token.getIdentifierInfo()->hasMacroDefinition()) { auto rawID = token.getIdentifierInfo(); auto definition = impl.getClangPreprocessor().getMacroDefinition(rawID); if (!definition) return None; ClangNode macroNode; const clang::MacroInfo *macroInfo; if (definition.getModuleMacros().empty()) { macroInfo = definition.getMacroInfo(); macroNode = macroInfo; } else { // Follow MacroDefinition::getMacroInfo in preferring the last ModuleMacro // rather than the first. const clang::ModuleMacro *moduleMacro = definition.getModuleMacros().back(); macroInfo = moduleMacro->getMacroInfo(); macroNode = moduleMacro; } auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo); (void)impl.importMacro(importedID, macroNode); auto searcher = impl.ImportedMacroConstants.find(macroInfo); if (searcher == impl.ImportedMacroConstants.end()) { return None; } auto importedConstant = searcher->second; if (!importedConstant.first.isInt()) { return None; } return {{ importedConstant.first.getInt(), importedConstant.second }}; } return None; }
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; }
void PreprocessingRecord::InclusionDirective(SourceLocation HashLoc, const clang::Token &IncludeTok, llvm::StringRef FileName, bool IsAngled, const FileEntry *File, clang::SourceLocation EndLoc) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: Kind = InclusionDirective::Include; break; case tok::pp_import: Kind = InclusionDirective::Import; break; case tok::pp_include_next: Kind = InclusionDirective::IncludeNext; break; case tok::pp___include_macros: Kind = InclusionDirective::IncludeMacros; break; default: llvm_unreachable("Unknown include directive kind"); return; } clang::InclusionDirective *ID = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, File, SourceRange(HashLoc, EndLoc)); PreprocessedEntities.push_back(ID); }
void FMacroCallback::MacroExpands(const clang::Token &MacroNameTok, const clang::MacroDirective *MD, clang::SourceRange Range, const clang::MacroArgs *Args) { auto MacroName = MacroNameTok.getIdentifierInfo()->getName(); if (IsBuiltInMacro(MD) || IsMacroDefinedInCommandLine(MacroName) || IsPredefinedMacro(MacroName)) { return; } if (MacroDefinitionToFile.Contains(FString(MacroName.data()))) { auto MacroDefinitionFilename = FString(*MacroDefinitionToFile[MacroName.data()]); MacroDefinitionFilename.ReplaceInline(TEXT("\\"), TEXT("/")); auto MacroDefinitionFilenameHash = FIncludeSetMapKeyFuncs::GetKeyHash(MacroDefinitionFilename); auto MacroExpansionFilename = FString(SourceManager.getFilename(Range.getBegin()).data()); MacroExpansionFilename.ReplaceInline(TEXT("\\"), TEXT("/")); auto MacroExpansionFilenameHash = FIncludeSetMapKeyFuncs::GetKeyHash(MacroExpansionFilename); if (!Includes.Contains(MacroExpansionFilenameHash)) { Includes.FindOrAdd(MacroExpansionFilenameHash).Add(MacroDefinitionFilenameHash); } GHashToFilename.Add(MacroDefinitionFilenameHash, MacroDefinitionFilename); GHashToFilename.Add(MacroExpansionFilenameHash, MacroExpansionFilename); return; } OutputFileContents.Logf(TEXT("Internal error. Found usage of unknown macro %s."), ANSI_TO_TCHAR(MacroName.data())); }
static best_guess tok_type(clang::Preprocessor &pp, const char *macro_name, const clang::Token &t, StringSet *seen) { using namespace clang; tok::TokenKind k = t.getKind(); if(k == tok::identifier) { IdentifierInfo *ii = t.getIdentifierInfo(); if(ii && !seen->count(ii->getNameStart())) return macro_type(pp, ii->getNameStart(), pp.getMacroInfo(ii), seen); return tok_ok; } if (k == tok::l_paren || k == tok::r_paren || k == tok::amp || k == tok::plus || k == tok::star || k == tok::minus || k == tok::tilde || k == tok::slash || k == tok::percent || k == tok::lessless || k == tok::greatergreater || k == tok::caret || k == tok::pipe || k == tok::exclaim || k == tok::kw_int || k == tok::kw_float || k == tok::kw_double || k == tok::kw_long || k == tok::kw_signed || k == tok::kw_unsigned) return tok_ok; return tok_invalid; }
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()); }
static Optional<std::pair<llvm::APSInt, Type>> getIntegerConstantForMacroToken(ClangImporter::Implementation &impl, DeclContext *DC, const clang::Token &token) { // Integer literal. if (token.is(clang::tok::numeric_constant)) { if (auto literal = parseNumericLiteral<clang::IntegerLiteral>(impl,token)) { auto value = llvm::APSInt { literal->getValue(), literal->getType()->isUnsignedIntegerType() }; auto type = impl.importType(literal->getType(), ImportTypeKind::Value, isInSystemModule(DC), /*isFullyBridgeable*/false); return {{ value, type }}; } // Macro identifier. } else if (token.is(clang::tok::identifier) && token.getIdentifierInfo()->hasMacroDefinition()) { auto rawID = token.getIdentifierInfo(); auto macroInfo = impl.getClangPreprocessor().getMacroInfo(rawID); auto importedID = impl.getNameImporter().importMacroName(rawID, macroInfo); impl.importMacro(importedID, macroInfo); auto searcher = impl.ImportedMacroConstants.find(macroInfo); if (searcher == impl.ImportedMacroConstants.end()) { return None; } auto importedConstant = searcher->second; if (!importedConstant.first.isInt()) { return None; } return {{ importedConstant.first.getInt(), importedConstant.second }}; } return None; }
void PreprocessingRecord::InclusionDirective( SourceLocation HashLoc, const clang::Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, const Module *Imported) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: Kind = InclusionDirective::Include; break; case tok::pp_import: Kind = InclusionDirective::Import; break; case tok::pp_using: Kind = InclusionDirective::Using; break; case tok::pp_include_next: Kind = InclusionDirective::IncludeNext; break; case tok::pp___include_macros: Kind = InclusionDirective::IncludeMacros; break; default: llvm_unreachable("Unknown include directive kind"); } SourceLocation EndLoc; if (!IsAngled) { EndLoc = FilenameRange.getBegin(); } else { EndLoc = FilenameRange.getEnd(); if (FilenameRange.isCharRange()) EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects // a token range. } clang::InclusionDirective *ID = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, File, SourceRange(HashLoc, EndLoc)); addPreprocessedEntity(ID); }
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::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()); }
void DeclCollector::MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective *MD) { Transaction::MacroDirectiveInfo MDE(MacroNameTok.getIdentifierInfo(), MD); m_CurTransaction->append(MDE); }
void PreprocessorCallback::MacroExpands(const clang::Token& MacroNameTok, MyMacroDefinition MD, clang::SourceRange Range, const clang::MacroArgs *) { if (disabled) return; #if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR >= 7 auto *MI = MD.getMacroInfo(); #else auto *MI = MD->getMacroInfo(); #endif 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(), &PP.getDiagnostics().getDiagnosticOptions(), new clang::IgnoringDiagConsumer); disabled = true; clang::DiagnosticsEngine *OldDiags = &PP.getDiagnostics(); PP.setDiagnostics(TmpDiags); // We don't want pragmas either. Although we filtered out #pragma, removing // _Pragma and __pragma is much harder. bool pragmasPreviouslyEnabled = PP.getPragmasEnabled(); PP.setPragmasEnabled(false); 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); PP.setPragmasEnabled(pragmasPreviouslyEnabled); disabled = false; std::string ref = llvm::Twine("_M/", MacroNameTok.getIdentifierInfo()->getName()).str(); clang::SourceLocation defLoc = MI->getDefinitionLoc(); clang::FileID defFID = sm.getFileID(defLoc); llvm::SmallString<128> expansionBuffer; std::string link; std::string dataProj; if (defFID != FID) { link = annotator.pathTo(FID, defFID, &dataProj); if (link.empty()) { std::string tag = "class=\"macro\" title=\"" % Generator::escapeAttr(expansion, expansionBuffer) % "\" 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_Call); } std::string tag = "class=\"macro\" href=\"" % link % "#" % llvm::Twine(sm.getExpansionLineNumber(defLoc)).str() % "\" title=\"" % Generator::escapeAttr(expansion, expansionBuffer) % "\" data-ref=\"" % ref % "\"" % dataProj; annotator.generator(FID).addTag("a", tag, sm.getFileOffset(loc), MacroNameTok.getLength()); }