File indexing completed on 2026-05-10 08:36:57
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_LEX_MACROINFO_H
0015 #define LLVM_CLANG_LEX_MACROINFO_H
0016
0017 #include "clang/Lex/Token.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "clang/Basic/SourceLocation.h"
0020 #include "llvm/ADT/ArrayRef.h"
0021 #include "llvm/ADT/FoldingSet.h"
0022 #include "llvm/ADT/PointerIntPair.h"
0023 #include "llvm/ADT/SmallVector.h"
0024 #include "llvm/Support/Allocator.h"
0025 #include <algorithm>
0026 #include <cassert>
0027
0028 namespace clang {
0029
0030 class DefMacroDirective;
0031 class IdentifierInfo;
0032 class Module;
0033 class Preprocessor;
0034 class SourceManager;
0035
0036
0037
0038
0039 class MacroInfo {
0040
0041
0042
0043
0044 SourceLocation Location;
0045
0046
0047 SourceLocation EndLocation;
0048
0049
0050
0051
0052
0053
0054
0055 IdentifierInfo **ParameterList = nullptr;
0056
0057
0058 const Token *ReplacementTokens = nullptr;
0059
0060
0061 unsigned NumParameters = 0;
0062
0063
0064 unsigned NumReplacementTokens = 0;
0065
0066
0067 mutable unsigned DefinitionLength;
0068 mutable bool IsDefinitionLengthCached : 1;
0069
0070
0071 bool IsFunctionLike : 1;
0072
0073
0074
0075
0076
0077
0078 bool IsC99Varargs : 1;
0079
0080
0081
0082
0083
0084 bool IsGNUVarargs : 1;
0085
0086
0087
0088
0089
0090
0091 bool IsBuiltinMacro : 1;
0092
0093
0094 bool HasCommaPasting : 1;
0095
0096
0097
0098
0099
0100
0101
0102
0103 bool IsDisabled : 1;
0104
0105
0106
0107
0108
0109 bool IsUsed : 1;
0110
0111
0112 bool IsAllowRedefinitionsWithoutWarning : 1;
0113
0114
0115 bool IsWarnIfUnused : 1;
0116
0117
0118 bool UsedForHeaderGuard : 1;
0119
0120
0121 MacroInfo(SourceLocation DefLoc);
0122
0123 public:
0124
0125 SourceLocation getDefinitionLoc() const { return Location; }
0126
0127
0128 void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }
0129
0130
0131 SourceLocation getDefinitionEndLoc() const { return EndLocation; }
0132
0133
0134 unsigned getDefinitionLength(const SourceManager &SM) const {
0135 if (IsDefinitionLengthCached)
0136 return DefinitionLength;
0137 return getDefinitionLengthSlow(SM);
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147 bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
0148 bool Syntactically) const;
0149
0150
0151 void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
0152
0153
0154 void setIsUsed(bool Val) { IsUsed = Val; }
0155
0156
0157 void setIsAllowRedefinitionsWithoutWarning(bool Val) {
0158 IsAllowRedefinitionsWithoutWarning = Val;
0159 }
0160
0161
0162 void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }
0163
0164
0165
0166 void setParameterList(ArrayRef<IdentifierInfo *> List,
0167 llvm::BumpPtrAllocator &PPAllocator) {
0168 assert(ParameterList == nullptr && NumParameters == 0 &&
0169 "Parameter list already set!");
0170 if (List.empty())
0171 return;
0172
0173 NumParameters = List.size();
0174 ParameterList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
0175 std::copy(List.begin(), List.end(), ParameterList);
0176 }
0177
0178
0179
0180 using param_iterator = IdentifierInfo *const *;
0181 bool param_empty() const { return NumParameters == 0; }
0182 param_iterator param_begin() const { return ParameterList; }
0183 param_iterator param_end() const { return ParameterList + NumParameters; }
0184 unsigned getNumParams() const { return NumParameters; }
0185 ArrayRef<const IdentifierInfo *> params() const {
0186 return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters);
0187 }
0188
0189
0190
0191 int getParameterNum(const IdentifierInfo *Arg) const {
0192 for (param_iterator I = param_begin(), E = param_end(); I != E; ++I)
0193 if (*I == Arg)
0194 return I - param_begin();
0195 return -1;
0196 }
0197
0198
0199
0200 void setIsFunctionLike() { IsFunctionLike = true; }
0201 bool isFunctionLike() const { return IsFunctionLike; }
0202 bool isObjectLike() const { return !IsFunctionLike; }
0203
0204
0205 void setIsC99Varargs() { IsC99Varargs = true; }
0206 void setIsGNUVarargs() { IsGNUVarargs = true; }
0207 bool isC99Varargs() const { return IsC99Varargs; }
0208 bool isGNUVarargs() const { return IsGNUVarargs; }
0209 bool isVariadic() const { return IsC99Varargs || IsGNUVarargs; }
0210
0211
0212
0213
0214
0215
0216
0217 bool isBuiltinMacro() const { return IsBuiltinMacro; }
0218
0219 bool hasCommaPasting() const { return HasCommaPasting; }
0220 void setHasCommaPasting() { HasCommaPasting = true; }
0221
0222
0223
0224 bool isUsed() const { return IsUsed; }
0225
0226
0227 bool isAllowRedefinitionsWithoutWarning() const {
0228 return IsAllowRedefinitionsWithoutWarning;
0229 }
0230
0231
0232 bool isWarnIfUnused() const { return IsWarnIfUnused; }
0233
0234
0235 unsigned getNumTokens() const { return NumReplacementTokens; }
0236
0237 const Token &getReplacementToken(unsigned Tok) const {
0238 assert(Tok < NumReplacementTokens && "Invalid token #");
0239 return ReplacementTokens[Tok];
0240 }
0241
0242 using const_tokens_iterator = const Token *;
0243
0244 const_tokens_iterator tokens_begin() const { return ReplacementTokens; }
0245 const_tokens_iterator tokens_end() const {
0246 return ReplacementTokens + NumReplacementTokens;
0247 }
0248 bool tokens_empty() const { return NumReplacementTokens == 0; }
0249 ArrayRef<Token> tokens() const {
0250 return llvm::ArrayRef(ReplacementTokens, NumReplacementTokens);
0251 }
0252
0253 llvm::MutableArrayRef<Token>
0254 allocateTokens(unsigned NumTokens, llvm::BumpPtrAllocator &PPAllocator) {
0255 assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
0256 "Token list already allocated!");
0257 NumReplacementTokens = NumTokens;
0258 Token *NewReplacementTokens = PPAllocator.Allocate<Token>(NumTokens);
0259 ReplacementTokens = NewReplacementTokens;
0260 return llvm::MutableArrayRef(NewReplacementTokens, NumTokens);
0261 }
0262
0263 void setTokens(ArrayRef<Token> Tokens, llvm::BumpPtrAllocator &PPAllocator) {
0264 assert(
0265 !IsDefinitionLengthCached &&
0266 "Changing replacement tokens after definition length got calculated");
0267 assert(ReplacementTokens == nullptr && NumReplacementTokens == 0 &&
0268 "Token list already set!");
0269 if (Tokens.empty())
0270 return;
0271
0272 NumReplacementTokens = Tokens.size();
0273 Token *NewReplacementTokens = PPAllocator.Allocate<Token>(Tokens.size());
0274 std::copy(Tokens.begin(), Tokens.end(), NewReplacementTokens);
0275 ReplacementTokens = NewReplacementTokens;
0276 }
0277
0278
0279
0280
0281 bool isEnabled() const { return !IsDisabled; }
0282
0283 void EnableMacro() {
0284 assert(IsDisabled && "Cannot enable an already-enabled macro!");
0285 IsDisabled = false;
0286 }
0287
0288 void DisableMacro() {
0289 assert(!IsDisabled && "Cannot disable an already-disabled macro!");
0290 IsDisabled = true;
0291 }
0292
0293
0294 bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }
0295
0296 void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }
0297
0298 void dump() const;
0299
0300 private:
0301 friend class Preprocessor;
0302
0303 unsigned getDefinitionLengthSlow(const SourceManager &SM) const;
0304 };
0305
0306
0307
0308
0309
0310
0311
0312
0313 class MacroDirective {
0314 public:
0315 enum Kind {
0316 MD_Define,
0317 MD_Undefine,
0318 MD_Visibility
0319 };
0320
0321 protected:
0322
0323 MacroDirective *Previous = nullptr;
0324
0325 SourceLocation Loc;
0326
0327
0328 LLVM_PREFERRED_TYPE(Kind)
0329 unsigned MDKind : 2;
0330
0331
0332 LLVM_PREFERRED_TYPE(bool)
0333 unsigned IsFromPCH : 1;
0334
0335
0336
0337
0338
0339 LLVM_PREFERRED_TYPE(bool)
0340 unsigned IsPublic : 1;
0341
0342 MacroDirective(Kind K, SourceLocation Loc)
0343 : Loc(Loc), MDKind(K), IsFromPCH(false), IsPublic(true) {}
0344
0345 public:
0346 Kind getKind() const { return Kind(MDKind); }
0347
0348 SourceLocation getLocation() const { return Loc; }
0349
0350
0351 void setPrevious(MacroDirective *Prev) { Previous = Prev; }
0352
0353
0354 const MacroDirective *getPrevious() const { return Previous; }
0355
0356
0357 MacroDirective *getPrevious() { return Previous; }
0358
0359
0360 bool isFromPCH() const { return IsFromPCH; }
0361
0362 void setIsFromPCH() { IsFromPCH = true; }
0363
0364 class DefInfo {
0365 DefMacroDirective *DefDirective = nullptr;
0366 SourceLocation UndefLoc;
0367 bool IsPublic = true;
0368
0369 public:
0370 DefInfo() = default;
0371 DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
0372 bool isPublic)
0373 : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
0374
0375 const DefMacroDirective *getDirective() const { return DefDirective; }
0376 DefMacroDirective *getDirective() { return DefDirective; }
0377
0378 inline SourceLocation getLocation() const;
0379 inline MacroInfo *getMacroInfo();
0380
0381 const MacroInfo *getMacroInfo() const {
0382 return const_cast<DefInfo *>(this)->getMacroInfo();
0383 }
0384
0385 SourceLocation getUndefLocation() const { return UndefLoc; }
0386 bool isUndefined() const { return UndefLoc.isValid(); }
0387
0388 bool isPublic() const { return IsPublic; }
0389
0390 bool isValid() const { return DefDirective != nullptr; }
0391 bool isInvalid() const { return !isValid(); }
0392
0393 explicit operator bool() const { return isValid(); }
0394
0395 inline DefInfo getPreviousDefinition();
0396
0397 const DefInfo getPreviousDefinition() const {
0398 return const_cast<DefInfo *>(this)->getPreviousDefinition();
0399 }
0400 };
0401
0402
0403
0404
0405 DefInfo getDefinition();
0406 const DefInfo getDefinition() const {
0407 return const_cast<MacroDirective *>(this)->getDefinition();
0408 }
0409
0410 bool isDefined() const {
0411 if (const DefInfo Def = getDefinition())
0412 return !Def.isUndefined();
0413 return false;
0414 }
0415
0416 const MacroInfo *getMacroInfo() const {
0417 return getDefinition().getMacroInfo();
0418 }
0419 MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
0420
0421
0422
0423 const DefInfo findDirectiveAtLoc(SourceLocation L,
0424 const SourceManager &SM) const;
0425
0426 void dump() const;
0427
0428 static bool classof(const MacroDirective *) { return true; }
0429 };
0430
0431
0432 class DefMacroDirective : public MacroDirective {
0433 MacroInfo *Info;
0434
0435 public:
0436 DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
0437 : MacroDirective(MD_Define, Loc), Info(MI) {
0438 assert(MI && "MacroInfo is null");
0439 }
0440 explicit DefMacroDirective(MacroInfo *MI)
0441 : DefMacroDirective(MI, MI->getDefinitionLoc()) {}
0442
0443
0444 const MacroInfo *getInfo() const { return Info; }
0445 MacroInfo *getInfo() { return Info; }
0446
0447 static bool classof(const MacroDirective *MD) {
0448 return MD->getKind() == MD_Define;
0449 }
0450
0451 static bool classof(const DefMacroDirective *) { return true; }
0452 };
0453
0454
0455 class UndefMacroDirective : public MacroDirective {
0456 public:
0457 explicit UndefMacroDirective(SourceLocation UndefLoc)
0458 : MacroDirective(MD_Undefine, UndefLoc) {
0459 assert(UndefLoc.isValid() && "Invalid UndefLoc!");
0460 }
0461
0462 static bool classof(const MacroDirective *MD) {
0463 return MD->getKind() == MD_Undefine;
0464 }
0465
0466 static bool classof(const UndefMacroDirective *) { return true; }
0467 };
0468
0469
0470 class VisibilityMacroDirective : public MacroDirective {
0471 public:
0472 explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
0473 : MacroDirective(MD_Visibility, Loc) {
0474 IsPublic = Public;
0475 }
0476
0477
0478
0479 bool isPublic() const { return IsPublic; }
0480
0481 static bool classof(const MacroDirective *MD) {
0482 return MD->getKind() == MD_Visibility;
0483 }
0484
0485 static bool classof(const VisibilityMacroDirective *) { return true; }
0486 };
0487
0488 inline SourceLocation MacroDirective::DefInfo::getLocation() const {
0489 if (isInvalid())
0490 return {};
0491 return DefDirective->getLocation();
0492 }
0493
0494 inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
0495 if (isInvalid())
0496 return nullptr;
0497 return DefDirective->getInfo();
0498 }
0499
0500 inline MacroDirective::DefInfo
0501 MacroDirective::DefInfo::getPreviousDefinition() {
0502 if (isInvalid() || DefDirective->getPrevious() == nullptr)
0503 return {};
0504 return DefDirective->getPrevious()->getDefinition();
0505 }
0506
0507
0508
0509
0510
0511
0512
0513
0514 class ModuleMacro : public llvm::FoldingSetNode {
0515 friend class Preprocessor;
0516
0517
0518 const IdentifierInfo *II;
0519
0520
0521 MacroInfo *Macro;
0522
0523
0524 Module *OwningModule;
0525
0526
0527 unsigned NumOverriddenBy = 0;
0528
0529
0530 unsigned NumOverrides;
0531
0532 ModuleMacro(Module *OwningModule, const IdentifierInfo *II, MacroInfo *Macro,
0533 ArrayRef<ModuleMacro *> Overrides)
0534 : II(II), Macro(Macro), OwningModule(OwningModule),
0535 NumOverrides(Overrides.size()) {
0536 std::copy(Overrides.begin(), Overrides.end(),
0537 reinterpret_cast<ModuleMacro **>(this + 1));
0538 }
0539
0540 public:
0541 static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
0542 const IdentifierInfo *II, MacroInfo *Macro,
0543 ArrayRef<ModuleMacro *> Overrides);
0544
0545 void Profile(llvm::FoldingSetNodeID &ID) const {
0546 return Profile(ID, OwningModule, II);
0547 }
0548
0549 static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
0550 const IdentifierInfo *II) {
0551 ID.AddPointer(OwningModule);
0552 ID.AddPointer(II);
0553 }
0554
0555
0556 const IdentifierInfo *getName() const { return II; }
0557
0558
0559 Module *getOwningModule() const { return OwningModule; }
0560
0561
0562
0563 MacroInfo *getMacroInfo() const { return Macro; }
0564
0565
0566
0567 using overrides_iterator = ModuleMacro *const *;
0568
0569 overrides_iterator overrides_begin() const {
0570 return reinterpret_cast<overrides_iterator>(this + 1);
0571 }
0572
0573 overrides_iterator overrides_end() const {
0574 return overrides_begin() + NumOverrides;
0575 }
0576
0577 ArrayRef<ModuleMacro *> overrides() const {
0578 return llvm::ArrayRef(overrides_begin(), overrides_end());
0579 }
0580
0581
0582
0583 unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
0584 };
0585
0586
0587
0588
0589
0590 class MacroDefinition {
0591 llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
0592 ArrayRef<ModuleMacro *> ModuleMacros;
0593
0594 public:
0595 MacroDefinition() = default;
0596 MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
0597 bool IsAmbiguous)
0598 : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
0599
0600
0601 explicit operator bool() const {
0602 return getLocalDirective() || !ModuleMacros.empty();
0603 }
0604
0605
0606 MacroInfo *getMacroInfo() const {
0607 if (!ModuleMacros.empty())
0608 return ModuleMacros.back()->getMacroInfo();
0609 if (auto *MD = getLocalDirective())
0610 return MD->getMacroInfo();
0611 return nullptr;
0612 }
0613
0614
0615 bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
0616
0617
0618
0619 DefMacroDirective *getLocalDirective() const {
0620 return LatestLocalAndAmbiguous.getPointer();
0621 }
0622
0623
0624 ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
0625
0626 template <typename Fn> void forAllDefinitions(Fn F) const {
0627 if (auto *MD = getLocalDirective())
0628 F(MD->getMacroInfo());
0629 for (auto *MM : getModuleMacros())
0630 F(MM->getMacroInfo());
0631 }
0632 };
0633
0634 }
0635
0636 #endif