https://github.com/achaljhawar updated 
https://github.com/llvm/llvm-project/pull/205719

>From e2c41b02955dbc34871ae34f71a72e8f2a6e282b Mon Sep 17 00:00:00 2001
From: achaljhawar <[email protected]>
Date: Thu, 25 Jun 2026 12:44:18 +1000
Subject: [PATCH] [clang][Tooling] Recognize standard user-defined literal
 operators

---
 .../Inclusions/Stdlib/StandardLibrary.cpp     | 10 ++++-
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 14 ++++++
 .../unittests/Tooling/StandardLibraryTest.cpp | 44 +++++++++++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 807a8d8a34ad7..e4de3b3850507 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -298,6 +298,7 @@ std::optional<Symbol> Recognizer::operator()(const Decl *D) 
{
   if (!Symbols)
     return std::nullopt;
 
+  std::string NameStorage;
   llvm::StringRef Name = [&]() -> llvm::StringRef {
     for (const auto *SymDC : llvm::reverse(IntermediateDecl)) {
       DeclarationName N = cast<NamedDecl>(SymDC)->getDeclName();
@@ -306,9 +307,16 @@ std::optional<Symbol> Recognizer::operator()(const Decl 
*D) {
       if (!N.isEmpty())
         return ""; // e.g. operator<: give up
     }
-    if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
+    if (const auto *ND = llvm::dyn_cast<NamedDecl>(D)) {
       if (const auto *II = ND->getIdentifier())
         return II->getName();
+      DeclarationName DN = ND->getDeclName();
+      if (DN.getNameKind() == DeclarationName::CXXLiteralOperatorName) {
+        NameStorage =
+            "operator\"\"" + DN.getCXXLiteralIdentifier()->getName().str();
+        return NameStorage;
+      }
+    }
     return "";
   }();
   if (Name.empty())
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index c5b022e87ec33..d84f230232d8a 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -851,3 +851,17 @@ SYMBOL(UINT64_C, None, <cstdint>)
 SYMBOL(UINT64_C, None, <stdint.h>)
 SYMBOL(UINTMAX_C, None, <cstdint>)
 SYMBOL(UINTMAX_C, None, <stdint.h>)
+
+SYMBOL(operator""h, std::, <chrono>)
+SYMBOL(operator""min, std::, <chrono>)
+SYMBOL(operator""s, std::, <chrono>)
+SYMBOL(operator""s, std::, <string>)
+SYMBOL(operator""ms, std::, <chrono>)
+SYMBOL(operator""us, std::, <chrono>)
+SYMBOL(operator""ns, std::, <chrono>)
+SYMBOL(operator""d, std::, <chrono>)
+SYMBOL(operator""y, std::, <chrono>)
+SYMBOL(operator""sv, std::, <string_view>)
+SYMBOL(operator""i, std::, <complex>)
+SYMBOL(operator""if, std::, <complex>)
+SYMBOL(operator""il, std::, <complex>)
diff --git a/clang/unittests/Tooling/StandardLibraryTest.cpp 
b/clang/unittests/Tooling/StandardLibraryTest.cpp
index e4c109f3d580d..78fb7d10fe24e 100644
--- a/clang/unittests/Tooling/StandardLibraryTest.cpp
+++ b/clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -10,6 +10,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclarationName.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/Testing/TestAST.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
@@ -174,6 +175,49 @@ TEST(StdlibTest, Recognizer) {
   EXPECT_EQ(Recognizer(Sec), std::nullopt);
 }
 
+TEST(StdlibTest, LiteralOperatorMappings) {
+  auto Chrono = stdlib::Header::named("<chrono>");
+  auto Str = stdlib::Header::named("<string>");
+  ASSERT_TRUE(Chrono);
+  ASSERT_TRUE(Str);
+
+  auto Ms = stdlib::Symbol::named("std::", "operator\"\"ms");
+  ASSERT_TRUE(Ms);
+  EXPECT_EQ(Ms->qualifiedName(), "std::operator\"\"ms");
+  EXPECT_EQ(Ms->header(), *Chrono);
+
+  auto S = stdlib::Symbol::named("std::", "operator\"\"s");
+  ASSERT_TRUE(S);
+  EXPECT_THAT(S->headers(), ElementsAre(*Chrono, *Str));
+
+  EXPECT_EQ(stdlib::Symbol::named("std::", "operator\"\"sv")->header(),
+            stdlib::Header::named("<string_view>"));
+}
+
+TEST(StdlibTest, RecognizerLiteralOperator) {
+  TestAST AST(R"cpp(
+    namespace std {
+    inline namespace literals {
+    inline namespace chrono_literals {
+      struct dur {};
+      dur operator"" ms(unsigned long long);
+    } // chrono_literals
+    } // literals
+    } // std
+
+    using namespace std::chrono_literals;
+    auto x = 5ms;
+  )cpp");
+
+  const VarDecl &X = cast<VarDecl>(lookup(AST, "x"));
+  const auto *UDL = cast<UserDefinedLiteral>(X.getInit()->IgnoreImplicit());
+  const FunctionDecl *Op = UDL->getDirectCallee();
+  ASSERT_TRUE(Op);
+
+  stdlib::Recognizer Recognizer;
+  EXPECT_EQ(Recognizer(Op), stdlib::Symbol::named("std::", "operator\"\"ms"));
+}
+
 TEST(StdlibTest, RecognizerForC99) {
   TestInputs Input("typedef char uint8_t;");
   Input.Language = TestLanguage::Lang_C99;

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

Reply via email to