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-exception 6 // 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 26 using namespace clang; 27 28 namespace { 29 30 // MacroInfo is expected to take 40 bytes on platforms with an 8 byte pointer 31 // and 4 byte SourceLocation. 32 template <int> class MacroInfoSizeChecker { 33 public: 34 [[maybe_unused]] constexpr static bool AsExpected = true; 35 }; 36 template <> class MacroInfoSizeChecker<8> { 37 public: 38 [[maybe_unused]] constexpr static bool AsExpected = 39 sizeof(MacroInfo) == (32 + sizeof(SourceLocation) * 2); 40 }; 41 42 static_assert(MacroInfoSizeChecker<sizeof(void *)>::AsExpected, 43 "Unexpected size of MacroInfo"); 44 45 } // end namespace 46 47 MacroInfo::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 54 unsigned 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 to 83 /// this macro in spelling, arguments, and whitespace. 84 /// 85 /// \param Syntactically if true, the macro definitions can be identical even 86 /// if they use different identifiers for the function macro parameters. 87 /// Otherwise the comparison is lexical and this implements the rules in 88 /// C99 6.10.3. 89 bool 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 and 117 // 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 long 130 // 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 147 LLVM_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 else 189 Out << Tok.getName(); 190 } 191 } 192 193 MacroDirective::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 214 const MacroDirective::DefInfo 215 MacroDirective::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 228 LLVM_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 254 ModuleMacro *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