[clang] [Clang] Fix dependency of SourceLocExpr. (PR #78436)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 17 04:36:54 PST 2024


https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/78436

SourceLocExpr that may produce a function name
are marked dependent so that the non-instantiated
name of a function does not get evaluated.

In GH78128, the name('s size) is used as
template argument to a `DeclRef` that is not otherwise
dependent, and therefore cached and not transformed when the function is instantiated, leading
to 2 different values existing at the same time for the same function.

Fixes #78128

>From ec8e4ad567daa15ddef6c90380f5b6877009b354 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 17 Jan 2024 13:26:01 +0100
Subject: [PATCH] [Clang] Fix dependency of SourceLocExpr.

SourceLocExpr that may produce a function name
are marked dependent so that the non-instantiated
name of a function does not get evaluated.

In GH78128, the name('s size) is used as
template argument to a Declref that is not
dependent, and therefore not transformed and cached
when the function is instantiated, leading
to 2 different values existing at the same time
for the same function.

Fixes #78128
---
 clang/docs/ReleaseNotes.rst            |  4 ++++
 clang/include/clang/AST/Expr.h         | 11 +++++++++++
 clang/lib/AST/Expr.cpp                 |  5 ++++-
 clang/lib/Sema/TreeTransform.h         |  2 +-
 clang/test/SemaCXX/source_location.cpp | 27 ++++++++++++++++++++++++++
 5 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 174392da17551e..a18596097ecd4d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -913,6 +913,10 @@ Bug Fixes to C++ Support
   (`#57410 <https://github.com/llvm/llvm-project/issues/57410>`_) and
   (`#76604 <https://github.com/llvm/llvm-project/issues/57410>`_)
 
+- Fix a bug where clang would produce inconsistent values when
+  std::source_location::current was used in function templates.
+  Fixes  (`#78128 <https://github.com/llvm/llvm-project/issues/78128>`_)
+
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 - Fixed an import failure of recursive friend class template.
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index a41f2d66b37b69..8bce87fa7a46eb 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4806,6 +4806,17 @@ class SourceLocExpr final : public Expr {
     return T->getStmtClass() == SourceLocExprClass;
   }
 
+  static bool MayBeDependent(SourceLocIdentKind Kind) {
+    switch (Kind) {
+    case SourceLocIdentKind::Function:
+    case SourceLocIdentKind::FuncSig:
+    case SourceLocIdentKind::SourceLocStruct:
+      return true;
+    default:
+      return false;
+    }
+  }
+
 private:
   friend class ASTStmtReader;
 };
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a90f92d07f86d2..11697a07b0e322 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2282,7 +2282,10 @@ SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Kind,
     : Expr(SourceLocExprClass, ResultTy, VK_PRValue, OK_Ordinary),
       BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
   SourceLocExprBits.Kind = llvm::to_underlying(Kind);
-  setDependence(ExprDependence::None);
+  // In dependent contexts, function names may change.
+  setDependence(MayBeDependent(Kind) && ParentContext->isDependentContext()
+                    ? ExprDependence::Value
+                    : ExprDependence::None);
 }
 
 StringRef SourceLocExpr::getBuiltinStr() const {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 1a1bc87d2b3203..4463904b07211b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -12148,7 +12148,7 @@ TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
 
 template <typename Derived>
 ExprResult TreeTransform<Derived>::TransformSourceLocExpr(SourceLocExpr *E) {
-  bool NeedRebuildFunc = E->getIdentKind() == SourceLocIdentKind::Function &&
+  bool NeedRebuildFunc = SourceLocExpr::MayBeDependent(E->getIdentKind()) &&
                          getSema().CurContext != E->getParentContext();
 
   if (!getDerived().AlwaysRebuild() && !NeedRebuildFunc)
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index e92fb35b653a8f..7414fbce7828d1 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -805,3 +805,30 @@ static_assert(S(0).j == S{0}.j);
 static_assert(S(0).j == S{0}.i);
 }
 #endif
+
+namespace GH78128 {
+
+template<int N>
+constexpr int f() {
+  return N;
+}
+
+template<typename T>
+void foo() {
+  constexpr auto* F1 = std::source_location::current().function();
+  static_assert(__builtin_strlen(F1) == f<__builtin_strlen(F1)>());
+
+  constexpr auto* F2 = __builtin_FUNCTION();
+  static_assert(__builtin_strlen(F2) == f<__builtin_strlen(F2)>());
+
+#ifdef MS
+  constexpr auto* F3 = __builtin_FUNCSIG();
+  static_assert(__builtin_strlen(F3) == f<__builtin_strlen(F3)>());
+#endif
+}
+
+void test() {
+  foo<int>();
+}
+
+}



More information about the cfe-commits mailing list