clang API Documentation

MacroInfo.cpp
Go to the documentation of this file.
00001 //===--- MacroInfo.cpp - Information about #defined identifiers -----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the MacroInfo interface.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Lex/MacroInfo.h"
00015 #include "clang/Lex/Preprocessor.h"
00016 using namespace clang;
00017 
00018 MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) {
00019   IsFunctionLike = false;
00020   IsC99Varargs = false;
00021   IsGNUVarargs = false;
00022   IsBuiltinMacro = false;
00023   IsFromAST = false;
00024   ChangedAfterLoad = false;
00025   IsDisabled = false;
00026   IsUsed = false;
00027   IsAllowRedefinitionsWithoutWarning = false;
00028   IsWarnIfUnused = false;
00029   IsDefinitionLengthCached = false;
00030   IsPublic = true;
00031   
00032   ArgumentList = 0;
00033   NumArguments = 0;
00034 }
00035 
00036 MacroInfo::MacroInfo(const MacroInfo &MI, llvm::BumpPtrAllocator &PPAllocator) {
00037   Location = MI.Location;
00038   EndLocation = MI.EndLocation;
00039   ReplacementTokens = MI.ReplacementTokens;
00040   IsFunctionLike = MI.IsFunctionLike;
00041   IsC99Varargs = MI.IsC99Varargs;
00042   IsGNUVarargs = MI.IsGNUVarargs;
00043   IsBuiltinMacro = MI.IsBuiltinMacro;
00044   IsFromAST = MI.IsFromAST;
00045   ChangedAfterLoad = MI.ChangedAfterLoad;
00046   IsDisabled = MI.IsDisabled;
00047   IsUsed = MI.IsUsed;
00048   IsAllowRedefinitionsWithoutWarning = MI.IsAllowRedefinitionsWithoutWarning;
00049   IsWarnIfUnused = MI.IsWarnIfUnused;
00050   IsDefinitionLengthCached = MI.IsDefinitionLengthCached;
00051   DefinitionLength = MI.DefinitionLength;
00052   IsPublic = MI.IsPublic;
00053   
00054   ArgumentList = 0;
00055   NumArguments = 0;
00056   setArgumentList(MI.ArgumentList, MI.NumArguments, PPAllocator);
00057 }
00058 
00059 unsigned MacroInfo::getDefinitionLengthSlow(SourceManager &SM) const {
00060   assert(!IsDefinitionLengthCached);
00061   IsDefinitionLengthCached = true;
00062 
00063   if (ReplacementTokens.empty())
00064     return (DefinitionLength = 0);
00065 
00066   const Token &firstToken = ReplacementTokens.front();
00067   const Token &lastToken = ReplacementTokens.back();
00068   SourceLocation macroStart = firstToken.getLocation();
00069   SourceLocation macroEnd = lastToken.getLocation();
00070   assert(macroStart.isValid() && macroEnd.isValid());
00071   assert((macroStart.isFileID() || firstToken.is(tok::comment)) &&
00072          "Macro defined in macro?");
00073   assert((macroEnd.isFileID() || lastToken.is(tok::comment)) &&
00074          "Macro defined in macro?");
00075   std::pair<FileID, unsigned>
00076       startInfo = SM.getDecomposedExpansionLoc(macroStart);
00077   std::pair<FileID, unsigned>
00078       endInfo = SM.getDecomposedExpansionLoc(macroEnd);
00079   assert(startInfo.first == endInfo.first &&
00080          "Macro definition spanning multiple FileIDs ?");
00081   assert(startInfo.second <= endInfo.second);
00082   DefinitionLength = endInfo.second - startInfo.second;
00083   DefinitionLength += lastToken.getLength();
00084 
00085   return DefinitionLength;
00086 }
00087 
00088 /// isIdenticalTo - Return true if the specified macro definition is equal to
00089 /// this macro in spelling, arguments, and whitespace.  This is used to emit
00090 /// duplicate definition warnings.  This implements the rules in C99 6.10.3.
00091 ///
00092 bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
00093   // Check # tokens in replacement, number of args, and various flags all match.
00094   if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
00095       getNumArgs() != Other.getNumArgs() ||
00096       isFunctionLike() != Other.isFunctionLike() ||
00097       isC99Varargs() != Other.isC99Varargs() ||
00098       isGNUVarargs() != Other.isGNUVarargs())
00099     return false;
00100 
00101   // Check arguments.
00102   for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
00103        I != E; ++I, ++OI)
00104     if (*I != *OI) return false;
00105 
00106   // Check all the tokens.
00107   for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
00108     const Token &A = ReplacementTokens[i];
00109     const Token &B = Other.ReplacementTokens[i];
00110     if (A.getKind() != B.getKind())
00111       return false;
00112 
00113     // If this isn't the first first token, check that the whitespace and
00114     // start-of-line characteristics match.
00115     if (i != 0 &&
00116         (A.isAtStartOfLine() != B.isAtStartOfLine() ||
00117          A.hasLeadingSpace() != B.hasLeadingSpace()))
00118       return false;
00119 
00120     // If this is an identifier, it is easy.
00121     if (A.getIdentifierInfo() || B.getIdentifierInfo()) {
00122       if (A.getIdentifierInfo() != B.getIdentifierInfo())
00123         return false;
00124       continue;
00125     }
00126 
00127     // Otherwise, check the spelling.
00128     if (PP.getSpelling(A) != PP.getSpelling(B))
00129       return false;
00130   }
00131 
00132   return true;
00133 }