Home | History | Annotate | Download | only in Lex
      1 //===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
      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 //
     10 // This file implements the MacroInfo interface.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/Lex/MacroInfo.h"
     15 #include "clang/Lex/Preprocessor.h"
     16 using namespace clang;
     17 
     18 MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
     19   IsFunctionLike = false;
     20   IsC99Varargs = false;
     21   IsGNUVarargs = false;
     22   IsBuiltinMacro = false;
     23   IsFromAST = false;
     24   ChangedAfterLoad = false;
     25   IsDisabled = false;
     26   IsUsed = false;
     27   IsAllowRedefinitionsWithoutWarning = false;
     28   IsWarnIfUnused = false;
     29   IsDefinitionLengthCached = false;
     30   IsPublic = true;
     31 
     32   ArgumentList = 0;
     33   NumArguments = 0;
     34 }
     35 
     36 MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
     37   Location = MI.Location;
     38   EndLocation = MI.EndLocation;
     39   ReplacementTokens = MI.ReplacementTokens;
     40   IsFunctionLike = MI.IsFunctionLike;
     41   IsC99Varargs = MI.IsC99Varargs;
     42   IsGNUVarargs = MI.IsGNUVarargs;
     43   IsBuiltinMacro = MI.IsBuiltinMacro;
     44   IsFromAST = MI.IsFromAST;
     45   ChangedAfterLoad = MI.ChangedAfterLoad;
     46   IsDisabled = MI.IsDisabled;
     47   IsUsed = MI.IsUsed;
     48   IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
     49   IsWarnIfUnused = MI.IsWarnIfUnused;
     50   IsDefinitionLengthCached = MI.IsDefinitionLengthCached;
     51   DefinitionLength = MI.DefinitionLength;
     52   IsPublic = MI.IsPublic;
     53 
     54   ArgumentList = 0;
     55   NumArguments = 0;
     56   setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
     57 }
     58 
     59 unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
     60   assert(!IsDefinitionLengthCached);
     61   IsDefinitionLengthCached = true;
     62 
     63   if (ReplacementTokens.empty())
     64     return (DefinitionLength = 0);
     65 
     66   const Token &firstToken = ReplacementTokens.front();
     67   const Token &lastToken = ReplacementTokens.back();
     68   SourceLocation macroStart = firstToken.getLocation();
     69   SourceLocation macroEnd = lastToken.getLocation();
     70   assert(macroStart.isValid() && macroEnd.isValid());
     71   assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
     72          "Macro defined in macro?");
     73   assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
     74          "Macro defined in macro?");
     75   std::pair<FileID, unsigned>
     76       startInfo = SM.getDecomposedExpansionLoc(macroStart);
     77   std::pair<FileID, unsigned>
     78       endInfo = SM.getDecomposedExpansionLoc(macroEnd);
     79   assert(startInfo.first == endInfo.first &&
     80          "Macro definition spanning multiple FileIDs ?");
     81   assert(startInfo.second <= endInfo.second);
     82   DefinitionLength = endInfo.second - startInfo.second;
     83   DefinitionLength += lastToken.getLength();
     84 
     85   return DefinitionLength;
     86 }
     87 
     88 /// isIdenticalTo - Return true if the specified macro definition is equal to
     89 /// this macro in spelling, arguments, and whitespace.  This is used to emit
     90 /// duplicate definition warnings.  This implements the rules in C99 6.10.3.
     91 ///
     92 bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
     93   // Check # tokens in replacement, number of args, and various flags all match.
     94   if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
     95       getNumArgs() != Other.getNumArgs() ||
     96       isFunctionLike() != Other.isFunctionLike() ||
     97       isC99Varargs() != Other.isC99Varargs() ||
     98       isGNUVarargs() != Other.isGNUVarargs())
     99     return false;
    100 
    101   // Check arguments.
    102   for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
    103        I != E; ++I, ++OI)
    104     if (*I != *OI) return false;
    105 
    106   // Check all the tokens.
    107   for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
    108     const Token &A = ReplacementTokens[i];
    109     const Token &B = Other.ReplacementTokens[i];
    110     if (A.getKind() != B.getKind())
    111       return false;
    112 
    113     // If this isn't the first first token, check that the whitespace and
    114     // start-of-line characteristics match.
    115     if (i != 0 &&
    116         (A.isAtStartOfLine() != B.isAtStartOfLine() ||
    117          A.hasLeadingSpace() != B.hasLeadingSpace()))
    118       return false;
    119 
    120     // If this is an identifier, it is easy.
    121     if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
    122       if (A.getIdentifierInfo() != B.getIdentifierInfo())
    123         return false;
    124       continue;
    125     }
    126 
    127     // Otherwise, check the spelling.
    128     if (PP.getSpelling(A) != PP.getSpelling(B))
    129       return false;
    130   }
    131 
    132   return true;
    133 }
    134