clang API Documentation
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 }