brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.8 KiB · 8b296d5 Raw
262 lines · cpp
1//===- MacroInfo.cpp - Information about #defined identifiers -------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the MacroInfo interface.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Lex/MacroInfo.h"14#include "clang/Basic/IdentifierTable.h"15#include "clang/Basic/LLVM.h"16#include "clang/Basic/SourceLocation.h"17#include "clang/Basic/SourceManager.h"18#include "clang/Basic/TokenKinds.h"19#include "clang/Lex/Preprocessor.h"20#include "clang/Lex/Token.h"21#include "llvm/Support/Compiler.h"22#include "llvm/Support/raw_ostream.h"23#include <cassert>24#include <optional>25 26using namespace clang;27 28namespace {29 30// MacroInfo is expected to take 40 bytes on platforms with an 8 byte pointer31// and 4 byte SourceLocation.32template <int> class MacroInfoSizeChecker {33public:34  [[maybe_unused]] constexpr static bool AsExpected = true;35};36template <> class MacroInfoSizeChecker<8> {37public:38  [[maybe_unused]] constexpr static bool AsExpected =39      sizeof(MacroInfo) == (32 + sizeof(SourceLocation) * 2);40};41 42static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected,43              "Unexpected size of MacroInfo");44 45} // end namespace46 47MacroInfo::MacroInfo(SourceLocation DefLoc)48    : Location(DefLoc), IsDefinitionLengthCached(false), IsFunctionLike(false),49      IsC99Varargs(false), IsGNUVarargs(false), IsBuiltinMacro(false),50      HasCommaPasting(false), IsDisabled(false), IsUsed(false),51      IsAllowRedefinitionsWithoutWarning(false), IsWarnIfUnused(false),52      UsedForHeaderGuard(false) {}53 54unsigned MacroInfo::getDefinitionLengthSlow(const SourceManager &SM) const {55  assert(!IsDefinitionLengthCached);56  IsDefinitionLengthCached = true;57 58  ArrayRef<Token> ReplacementTokens = tokens();59  if (ReplacementTokens.empty())60    return (DefinitionLength = 0);61 62  const Token &firstToken = ReplacementTokens.front();63  const Token &lastToken = ReplacementTokens.back();64  SourceLocation macroStart = firstToken.getLocation();65  SourceLocation macroEnd = lastToken.getLocation();66  assert(macroStart.isValid() && macroEnd.isValid());67  assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&68         "Macro defined in macro?");69  assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&70         "Macro defined in macro?");71  FileIDAndOffset startInfo = SM.getDecomposedExpansionLoc(macroStart);72  FileIDAndOffset endInfo = SM.getDecomposedExpansionLoc(macroEnd);73  assert(startInfo.first == endInfo.first &&74         "Macro definition spanning multiple FileIDs ?");75  assert(startInfo.second <= endInfo.second);76  DefinitionLength = endInfo.second - startInfo.second;77  DefinitionLength += lastToken.getLength();78 79  return DefinitionLength;80}81 82/// Return true if the specified macro definition is equal to83/// this macro in spelling, arguments, and whitespace.84///85/// \param Syntactically if true, the macro definitions can be identical even86/// if they use different identifiers for the function macro parameters.87/// Otherwise the comparison is lexical and this implements the rules in88/// C99 6.10.3.89bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,90                              bool Syntactically) const {91  bool Lexically = !Syntactically;92 93  // Check # tokens in replacement, number of args, and various flags all match.94  if (getNumTokens() != Other.getNumTokens() ||95      getNumParams() != Other.getNumParams() ||96      isFunctionLike() != Other.isFunctionLike() ||97      isC99Varargs() != Other.isC99Varargs() ||98      isGNUVarargs() != Other.isGNUVarargs())99    return false;100 101  if (Lexically) {102    // Check arguments.103    for (param_iterator I = param_begin(), OI = Other.param_begin(),104                        E = param_end();105         I != E; ++I, ++OI)106      if (*I != *OI) return false;107  }108 109  // Check all the tokens.110  for (unsigned i = 0; i != NumReplacementTokens; ++i) {111    const Token &A = ReplacementTokens[i];112    const Token &B = Other.ReplacementTokens[i];113    if (A.getKind() != B.getKind())114      return false;115 116    // If this isn't the first token, check that the whitespace and117    // start-of-line characteristics match.118    if (i != 0 &&119        (A.isAtStartOfLine() != B.isAtStartOfLine() ||120         A.hasLeadingSpace() != B.hasLeadingSpace()))121      return false;122 123    // If this is an identifier, it is easy.124    if (A.getIdentifierInfo() || B.getIdentifierInfo()) {125      if (A.getIdentifierInfo() == B.getIdentifierInfo())126        continue;127      if (Lexically)128        return false;129      // With syntactic equivalence the parameter names can be different as long130      // as they are used in the same place.131      int AArgNum = getParameterNum(A.getIdentifierInfo());132      if (AArgNum == -1)133        return false;134      if (AArgNum != Other.getParameterNum(B.getIdentifierInfo()))135        return false;136      continue;137    }138 139    // Otherwise, check the spelling.140    if (PP.getSpelling(A) != PP.getSpelling(B))141      return false;142  }143 144  return true;145}146 147LLVM_DUMP_METHOD void MacroInfo::dump() const {148  llvm::raw_ostream &Out = llvm::errs();149 150  // FIXME: Dump locations.151  Out << "MacroInfo " << this;152  if (IsBuiltinMacro) Out << " builtin";153  if (IsDisabled) Out << " disabled";154  if (IsUsed) Out << " used";155  if (IsAllowRedefinitionsWithoutWarning)156    Out << " allow_redefinitions_without_warning";157  if (IsWarnIfUnused) Out << " warn_if_unused";158  if (UsedForHeaderGuard) Out << " header_guard";159 160  Out << "\n    #define <macro>";161  if (IsFunctionLike) {162    Out << "(";163    for (unsigned I = 0; I != NumParameters; ++I) {164      if (I) Out << ", ";165      Out << ParameterList[I]->getName();166    }167    if (IsC99Varargs || IsGNUVarargs) {168      if (NumParameters && IsC99Varargs) Out << ", ";169      Out << "...";170    }171    Out << ")";172  }173 174  bool First = true;175  for (const Token &Tok : tokens()) {176    // Leading space is semantically meaningful in a macro definition,177    // so preserve it in the dump output.178    if (First || Tok.hasLeadingSpace())179      Out << " ";180    First = false;181 182    if (const char *Punc = tok::getPunctuatorSpelling(Tok.getKind()))183      Out << Punc;184    else if (Tok.isLiteral() && Tok.getLiteralData())185      Out << StringRef(Tok.getLiteralData(), Tok.getLength());186    else if (auto *II = Tok.getIdentifierInfo())187      Out << II->getName();188    else189      Out << Tok.getName();190  }191}192 193MacroDirective::DefInfo MacroDirective::getDefinition() {194  MacroDirective *MD = this;195  SourceLocation UndefLoc;196  std::optional<bool> isPublic;197  for (; MD; MD = MD->getPrevious()) {198    if (DefMacroDirective *DefMD = dyn_cast<DefMacroDirective>(MD))199      return DefInfo(DefMD, UndefLoc, !isPublic || *isPublic);200 201    if (UndefMacroDirective *UndefMD = dyn_cast<UndefMacroDirective>(MD)) {202      UndefLoc = UndefMD->getLocation();203      continue;204    }205 206    VisibilityMacroDirective *VisMD = cast<VisibilityMacroDirective>(MD);207    if (!isPublic)208      isPublic = VisMD->isPublic();209  }210 211  return DefInfo(nullptr, UndefLoc, !isPublic || *isPublic);212}213 214const MacroDirective::DefInfo215MacroDirective::findDirectiveAtLoc(SourceLocation L,216                                   const SourceManager &SM) const {217  assert(L.isValid() && "SourceLocation is invalid.");218  for (DefInfo Def = getDefinition(); Def; Def = Def.getPreviousDefinition()) {219    if (Def.getLocation().isInvalid() ||  // For macros defined on the command line.220        SM.isBeforeInTranslationUnit(Def.getLocation(), L))221      return (!Def.isUndefined() ||222              SM.isBeforeInTranslationUnit(L, Def.getUndefLocation()))223                  ? Def : DefInfo();224  }225  return DefInfo();226}227 228LLVM_DUMP_METHOD void MacroDirective::dump() const {229  llvm::raw_ostream &Out = llvm::errs();230 231  switch (getKind()) {232  case MD_Define: Out << "DefMacroDirective"; break;233  case MD_Undefine: Out << "UndefMacroDirective"; break;234  case MD_Visibility: Out << "VisibilityMacroDirective"; break;235  }236  Out << " " << this;237  // FIXME: Dump SourceLocation.238  if (auto *Prev = getPrevious())239    Out << " prev " << Prev;240  if (IsFromPCH) Out << " from_pch";241 242  if (isa<VisibilityMacroDirective>(this))243    Out << (IsPublic ? " public" : " private");244 245  if (auto *DMD = dyn_cast<DefMacroDirective>(this)) {246    if (auto *Info = DMD->getInfo()) {247      Out << "\n  ";248      Info->dump();249    }250  }251  Out << "\n";252}253 254ModuleMacro *ModuleMacro::create(Preprocessor &PP, Module *OwningModule,255                                 const IdentifierInfo *II, MacroInfo *Macro,256                                 ArrayRef<ModuleMacro *> Overrides) {257  void *Mem = PP.getPreprocessorAllocator().Allocate(258      sizeof(ModuleMacro) + sizeof(ModuleMacro *) * Overrides.size(),259      alignof(ModuleMacro));260  return new (Mem) ModuleMacro(OwningModule, II, Macro, Overrides);261}262