Skip to content

Commit 8c2b0d4

Browse files
authored
[Clang] Fix dependency of SourceLocExpr. (llvm#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 llvm#78128
1 parent 9917d39 commit 8c2b0d4

File tree

5 files changed

+47
-2
lines changed

5 files changed

+47
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,10 @@ Bug Fixes to C++ Support
972972
(`#57410 <https://github.com/llvm/llvm-project/issues/57410>`_) and
973973
(`#76604 <https://github.com/llvm/llvm-project/issues/57410>`_)
974974

975+
- Fix a bug where clang would produce inconsistent values when
976+
``std::source_location::current()`` was used in a function template.
977+
Fixes (`#78128 <https://github.com/llvm/llvm-project/issues/78128>`_)
978+
975979
Bug Fixes to AST Handling
976980
^^^^^^^^^^^^^^^^^^^^^^^^^
977981
- Fixed an import failure of recursive friend class template.

clang/include/clang/AST/Expr.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4756,6 +4756,17 @@ class SourceLocExpr final : public Expr {
47564756
return T->getStmtClass() == SourceLocExprClass;
47574757
}
47584758

4759+
static bool MayBeDependent(SourceLocIdentKind Kind) {
4760+
switch (Kind) {
4761+
case SourceLocIdentKind::Function:
4762+
case SourceLocIdentKind::FuncSig:
4763+
case SourceLocIdentKind::SourceLocStruct:
4764+
return true;
4765+
default:
4766+
return false;
4767+
}
4768+
}
4769+
47594770
private:
47604771
friend class ASTStmtReader;
47614772
};

clang/lib/AST/Expr.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2219,7 +2219,10 @@ SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Kind,
22192219
: Expr(SourceLocExprClass, ResultTy, VK_PRValue, OK_Ordinary),
22202220
BuiltinLoc(BLoc), RParenLoc(RParenLoc), ParentContext(ParentContext) {
22212221
SourceLocExprBits.Kind = llvm::to_underlying(Kind);
2222-
setDependence(ExprDependence::None);
2222+
// In dependent contexts, function names may change.
2223+
setDependence(MayBeDependent(Kind) && ParentContext->isDependentContext()
2224+
? ExprDependence::Value
2225+
: ExprDependence::None);
22232226
}
22242227

22252228
StringRef SourceLocExpr::getBuiltinStr() const {

clang/lib/Sema/TreeTransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12148,7 +12148,7 @@ TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) {
1214812148

1214912149
template <typename Derived>
1215012150
ExprResult TreeTransform<Derived>::TransformSourceLocExpr(SourceLocExpr *E) {
12151-
bool NeedRebuildFunc = E->getIdentKind() == SourceLocIdentKind::Function &&
12151+
bool NeedRebuildFunc = SourceLocExpr::MayBeDependent(E->getIdentKind()) &&
1215212152
getSema().CurContext != E->getParentContext();
1215312153

1215412154
if (!getDerived().AlwaysRebuild() && !NeedRebuildFunc)

clang/test/SemaCXX/source_location.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,3 +805,30 @@ static_assert(S(0).j == S{0}.j);
805805
static_assert(S(0).j == S{0}.i);
806806
}
807807
#endif
808+
809+
namespace GH78128 {
810+
811+
template<int N>
812+
constexpr int f() {
813+
return N;
814+
}
815+
816+
template<typename T>
817+
void foo() {
818+
constexpr auto* F1 = std::source_location::current().function();
819+
static_assert(__builtin_strlen(F1) == f<__builtin_strlen(F1)>());
820+
821+
constexpr auto* F2 = __builtin_FUNCTION();
822+
static_assert(__builtin_strlen(F2) == f<__builtin_strlen(F2)>());
823+
824+
#ifdef MS
825+
constexpr auto* F3 = __builtin_FUNCSIG();
826+
static_assert(__builtin_strlen(F3) == f<__builtin_strlen(F3)>());
827+
#endif
828+
}
829+
830+
void test() {
831+
foo<int>();
832+
}
833+
834+
}

0 commit comments

Comments
 (0)