[clang] c9fbabf - [ASTMatcher] Fix redundant macro expansion checks in getExpansionLocOfMacro (#117143)

via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 3 08:23:00 PST 2024


Author: mandymi
Date: 2024-12-03T11:22:56-05:00
New Revision: c9fbabfdc92f12b2b0148762e6e789157a172e4d

URL: https://github.com/llvm/llvm-project/commit/c9fbabfdc92f12b2b0148762e6e789157a172e4d
DIFF: https://github.com/llvm/llvm-project/commit/c9fbabfdc92f12b2b0148762e6e789157a172e4d.diff

LOG: [ASTMatcher] Fix redundant macro expansion checks in getExpansionLocOfMacro (#117143)

A performance issue was descibed in #114521 

**Root Cause**: The function getExpansionLocOfMacro is responsible for
finding the expansion location of macros. When dealing with macro
parameters, it recursively calls itself to check the expansion of macro
arguments. This recursive logic redundantly checks previous macro
expansions, leading to significant performance degradation when macros
are heavily nested.
Solution
**Modification**: Track already processed macros during recursion.
Implementation Details:
Introduced a data structure to record processed macros.
Before each recursive call, check if the macro has already been
processed to avoid redundant calculations.
**Testing**: 
1. refer to #114521 
Finder->addMatcher(expr(isExpandedFromMacro("NULL")).bind("E"), this);
run clang-tidy on freecad/src/Mod/Path/App/AreaPyImp.cpp 
clang-tidy src/Mod/Path/App/AreaPyImp.cpp -checks=-*,testchecker
-p=build/compile_commands.json
checker runs normally
2. check-clang-unit pass

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 395da768f7c322..922f49c453e15d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -971,6 +971,8 @@ AST Matchers
 - Ensure ``hasName`` matches template specializations across inline namespaces,
   making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.
 
+- Improved the performance of the ``getExpansionLocOfMacro`` by tracking already processed macros during recursion.
+
 - Add ``exportDecl`` matcher to match export declaration.
 
 clang-format

diff  --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index cdbdb65195409f..84a7fa4d36b480 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -21,6 +21,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
@@ -697,20 +698,27 @@ static bool isTokenAtLoc(const SourceManager &SM, const LangOptions &LangOpts,
   return !Invalid && Text == TokenText;
 }
 
-std::optional<SourceLocation>
-getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
-                       const ASTContext &Context) {
+static std::optional<SourceLocation> getExpansionLocOfMacroRecursive(
+    StringRef MacroName, SourceLocation Loc, const ASTContext &Context,
+    llvm::DenseSet<SourceLocation> &CheckedLocations) {
   auto &SM = Context.getSourceManager();
   const LangOptions &LangOpts = Context.getLangOpts();
   while (Loc.isMacroID()) {
+    if (CheckedLocations.count(Loc))
+      return std::nullopt;
+    CheckedLocations.insert(Loc);
     SrcMgr::ExpansionInfo Expansion =
         SM.getSLocEntry(SM.getFileID(Loc)).getExpansion();
-    if (Expansion.isMacroArgExpansion())
+    if (Expansion.isMacroArgExpansion()) {
       // Check macro argument for an expansion of the given macro. For example,
       // `F(G(3))`, where `MacroName` is `G`.
-      if (std::optional<SourceLocation> ArgLoc = getExpansionLocOfMacro(
-              MacroName, Expansion.getSpellingLoc(), Context))
+      if (std::optional<SourceLocation> ArgLoc =
+              getExpansionLocOfMacroRecursive(MacroName,
+                                              Expansion.getSpellingLoc(),
+                                              Context, CheckedLocations)) {
         return ArgLoc;
+      }
+    }
     Loc = Expansion.getExpansionLocStart();
     if (isTokenAtLoc(SM, LangOpts, MacroName, Loc))
       return Loc;
@@ -718,6 +726,14 @@ getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
   return std::nullopt;
 }
 
+std::optional<SourceLocation>
+getExpansionLocOfMacro(StringRef MacroName, SourceLocation Loc,
+                       const ASTContext &Context) {
+  llvm::DenseSet<SourceLocation> CheckedLocations;
+  return getExpansionLocOfMacroRecursive(MacroName, Loc, Context,
+                                         CheckedLocations);
+}
+
 std::shared_ptr<llvm::Regex> createAndVerifyRegex(StringRef Regex,
                                                   llvm::Regex::RegexFlags Flags,
                                                   StringRef MatcherID) {


        


More information about the cfe-commits mailing list