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