================
@@ -424,6 +424,74 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
   }
 
 private:
+  struct LifetimeBoundMacroCache {
+    bool IsBuilt = false;
+    SmallVector<const IdentifierInfo *> Candidates;
+  };
+
+  void buildLifetimeBoundMacroCache(LifetimeBoundMacroCache &Cache,
+                                    ArrayRef<TokenValue> Tokens) {
+    if (Cache.IsBuilt)
+      return;
+
+    const Preprocessor &PP = S.getPreprocessor();
+    // Collect macro names that were ever defined as a lifetimebound attribute.
+    for (const auto &M : PP.macros()) {
+      const IdentifierInfo *II = M.first;
+      const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
+      if (!MD)
+        continue;
+
+      // Include earlier matching definitions to handle redefinitions.
+      for (MacroDirective::DefInfo Def = MD->getDefinition(); Def;
+           Def = Def.getPreviousDefinition()) {
+        const MacroInfo *MI = Def.getMacroInfo();
+        if (MI->isObjectLike() && Tokens.size() == MI->getNumTokens() &&
+            std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin())) {
+          Cache.Candidates.push_back(II);
+          break;
+        }
+      }
+    }
+    Cache.IsBuilt = true;
+  }
+
+  StringRef getLastCachedMacroWithSpelling(SourceLocation Loc,
+                                           llvm::ArrayRef<TokenValue> Tokens,
+                                           LifetimeBoundMacroCache &Cache) {
+    if (Loc.isInvalid())
+      return {};
+
+    buildLifetimeBoundMacroCache(Cache, Tokens);
+
+    const Preprocessor &PP = S.getPreprocessor();
+    const SourceManager &SM = S.getSourceManager();
+    SourceLocation BestLocation;
+    StringRef BestSpelling;
+    for (const IdentifierInfo *II : Cache.Candidates) {
+      const MacroDirective *MD = PP.getLocalMacroDirectiveHistory(II);
+      const MacroDirective::DefInfo Def = MD->findDirectiveAtLoc(Loc, SM);
+      if (!Def || !Def.getMacroInfo())
+        continue;
+
+      // Ensure the macro definition active at Loc still has this spelling.
+      const MacroInfo *MI = Def.getMacroInfo();
+      if (!MI->isObjectLike() || Tokens.size() != MI->getNumTokens() ||
+          !std::equal(Tokens.begin(), Tokens.end(), MI->tokens_begin()))
+        continue;
+
+      // Choose the matching macro defined latest before Loc.
----------------
zeyi2 wrote:

`findDirectiveAtLoc(Loc, SM)` should guarantee this. Its implementation only 
returns a definition whose location is invalid, otherwise it keeps walking the 
definition chain. The implementation here basically mirrors what 
`Preprocessor::getLastMacroWithSpelling` does today. Please see:

https://github.com/llvm/llvm-project/blob/1e3018523042d1b610b6676cf8d056315f6e3bd7/clang/lib/Lex/Preprocessor.cpp#L393-L417

> Should we have an assertion about this?

Added now, thanks for reviewing.

https://github.com/llvm/llvm-project/pull/205250
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to