kythe.io@v0.0.68-0.20240422202219-7225dbc01741/third_party/llvm/src/cxx_extractor_preprocessor_utils.cc (about) 1 // cxx_extractor_preprocessor_utils.cc - Preprocessor utilities -*- C++ -*--==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===--------------------------------------------------------------------===// 9 /// \file 10 /// This file contains code from PreprocessorTracker.cpp from the modularize 11 /// project in clang-tools-extra; more details on its provenance and license 12 /// are available in //third_party/llvm. 13 //===--------------------------------------------------------------------===// 14 // This file uses the Clang style conventions. 15 #include "cxx_extractor_preprocessor_utils.h" 16 17 #include <set> 18 19 #include "clang/Lex/Preprocessor.h" 20 21 namespace kythe { 22 namespace { 23 24 // Changed vs. modularize: added Visited set. 25 std::string getMacroExpandedStringInternal( 26 clang::Preprocessor &PP, llvm::StringRef MacroName, 27 const clang::MacroInfo *MI, const clang::MacroArgs *Args, 28 std::set<const clang::MacroInfo *> &Visited) { 29 if (!Visited.insert(MI).second) { 30 return MacroName.str(); 31 } 32 std::string Expanded; 33 // Walk over the macro Tokens. 34 for (const auto &Tok : MI->tokens()) { 35 clang::IdentifierInfo *II = Tok.getIdentifierInfo(); 36 int ArgNo = (II && Args ? MI->getParameterNum(II) : -1); 37 if (ArgNo == -1) { 38 // This isn't an argument, just add it. 39 if (II == nullptr) 40 Expanded += PP.getSpelling(Tok); // Not an identifier. 41 else { 42 // Token is for an identifier. 43 std::string Name = II->getName().str(); 44 // Check for nexted macro references. 45 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 46 if (MacroInfo) 47 Expanded += getMacroExpandedStringInternal(PP, Name, MacroInfo, 48 nullptr, Visited); 49 else 50 Expanded += Name; 51 } 52 continue; 53 } 54 // We get here if it's a function-style macro with arguments. 55 const clang::Token *ResultArgToks; 56 const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); 57 if (Args->ArgNeedsPreexpansion(ArgTok, PP)) 58 ResultArgToks = &(const_cast<clang::MacroArgs *>(Args)) 59 ->getPreExpArgument(ArgNo, PP)[0]; 60 else 61 ResultArgToks = ArgTok; // Use non-preexpanded Tokens. 62 // If the arg token didn't expand into anything, ignore it. 63 if (ResultArgToks->is(clang::tok::eof)) continue; 64 unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); 65 // Append the resulting argument expansions. 66 for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { 67 const clang::Token &AT = ResultArgToks[ArgumentIndex]; 68 clang::IdentifierInfo *II = AT.getIdentifierInfo(); 69 if (II == nullptr) 70 Expanded += PP.getSpelling(AT); // Not an identifier. 71 else { 72 // It's an identifier. Check for further expansion. 73 std::string Name = II->getName().str(); 74 clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); 75 if (MacroInfo) 76 Expanded += getMacroExpandedStringInternal(PP, Name, MacroInfo, 77 nullptr, Visited); 78 else 79 Expanded += Name; 80 } 81 } 82 } 83 return Expanded; 84 } 85 } // namespace 86 87 std::string getMacroUnexpandedString(clang::SourceRange Range, 88 clang::Preprocessor &PP, 89 llvm::StringRef MacroName, 90 const clang::MacroInfo *MI) { 91 clang::SourceLocation BeginLoc(Range.getBegin()); 92 const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); 93 size_t Length; 94 std::string Unexpanded; 95 if (MI->isFunctionLike()) { 96 clang::SourceLocation EndLoc(Range.getEnd()); 97 const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1; 98 Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width. 99 } else 100 Length = MacroName.size(); 101 return llvm::StringRef(BeginPtr, Length).trim().str(); 102 } 103 104 std::string getMacroExpandedString(clang::Preprocessor &PP, 105 llvm::StringRef MacroName, 106 const clang::MacroInfo *MI, 107 const clang::MacroArgs *Args) { 108 std::set<const clang::MacroInfo *> Visited; 109 return getMacroExpandedStringInternal(PP, MacroName, MI, Args, Visited); 110 } 111 112 std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range) { 113 return std::string( 114 clang::Lexer::getSourceText(clang::CharSourceRange(Range, false), 115 PP.getSourceManager(), PP.getLangOpts()) 116 .trim()); 117 } 118 } // namespace kythe