-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] SourceLocIdentKind::Function should not be dependent #94942
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Qizhi Hu (jcsxky) ChangesConsider the testcase, return type of DecltypeType 0x55555570d8c0 'decltype(new struct BasicPersistent(declval<struct __alloc_traits>()))' sugar dependent
|-CXXNewExpr 0x55555570d880 'struct BasicPersistent *' Function 0x55555570ace0 'operator new' 'void *(unsigned long)'
| `-CXXConstructExpr 0x55555570d848 'struct BasicPersistent' 'void (BasicPersistent &&, SourceLocation)'
| |-CallExpr 0x55555570aae8 'BasicPersistent':'struct BasicPersistent' xvalue
| | `-ImplicitCastExpr 0x55555570aad0 'auto (*)(void) -> decltype(__declval<struct __alloc_traits>(0))' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x55555570aa18 'auto (void) -> decltype(__declval<struct __alloc_traits>(0))' lvalue Function 0x55555570a908 'declval' 'auto (void) -> decltype(__declval<struct __alloc_traits>(0))' (FunctionTemplate 0x5555556d0548 'declval') non_odr_use_unevaluated
| `-CXXDefaultArgExpr 0x55555570d820 'SourceLocation':'struct SourceLocation' has rewritten init
| `-CallExpr 0x55555570d7b0 'SourceLocation':'struct SourceLocation'
| |-ImplicitCastExpr 0x55555570d798 'SourceLocation (*)(const char *)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x5555556fe5c8 'SourceLocation (const char *)' lvalue CXXMethod 0x5555556fdb28 'Current' 'SourceLocation (const char *)'
| | `-NestedNameSpecifier TypeSpec 'struct SourceLocation'
| `-CXXDefaultArgExpr 0x55555570d7f8 'const char *' has rewritten init
| `-SourceLocExpr 0x55555570d7d8 'const char *'
`-PointerType 0x555555704800 'struct BasicPersistent *'
`-SubstTemplateTypeParmType 0x5555557047d0 'struct BasicPersistent' sugar typename depth 0 index 0 _Tp
|-FunctionTemplate 0x5555556ee048 'construct_at'
`-RecordType 0x5555556cfd10 'struct BasicPersistent'
`-CXXRecord 0x5555556fdc98 'BasicPersistent' when in the process of instantiation. This type is dependent due to the dependency of Full diff: https://github.com/llvm/llvm-project/pull/94942.diff 3 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cf1ba02cbc4b2..efe78139de6fa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -846,6 +846,7 @@ Bug Fixes to C++ Support
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474)
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307),
(#GH88081), (#GH89496), (#GH90669) and (#GH91633).
+- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index f2bf667636dc9..92bd7940bdba9 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4786,7 +4786,6 @@ class SourceLocExpr final : public Expr {
static bool MayBeDependent(SourceLocIdentKind Kind) {
switch (Kind) {
- case SourceLocIdentKind::Function:
case SourceLocIdentKind::FuncSig:
case SourceLocIdentKind::SourceLocStruct:
return true;
diff --git a/clang/test/CodeGenCXX/PR80210.cpp b/clang/test/CodeGenCXX/PR80210.cpp
new file mode 100644
index 0000000000000..fdd3beb99209e
--- /dev/null
+++ b/clang/test/CodeGenCXX/PR80210.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %itanium_abi_triple
+// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o /dev/null -verify -triple %ms_abi_triple
+
+// expected-no-diagnostics
+
+struct BasicPersistent;
+template <typename> BasicPersistent &&__declval(int);
+template <typename _Tp> auto declval() -> decltype(__declval<_Tp>(0));
+template <typename _Tp> _Tp forward;
+template <typename _Tp, typename... _Args>
+auto construct_at(_Tp *, _Args...) -> decltype(new _Tp(declval<_Args>()...)) {return 0;}
+template <typename> struct allocator;
+template <typename> struct allocator_traits;
+template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
+ using pointer = _Tp *;
+ template <typename _Up, typename... _Args>
+ static void construct(_Up __p, _Args...) {
+ construct_at(__p, forward<_Args>...);
+ }
+};
+struct __alloc_traits : allocator_traits<allocator<BasicPersistent>> {
+} push_back___x;
+__alloc_traits::pointer _M_impl_0;
+template <typename... _Args> void emplace_back(_Args...) {
+ __alloc_traits::construct(_M_impl_0, forward<_Args>...);
+}
+struct SourceLocation {
+ static SourceLocation Current(const char * = __builtin_FUNCTION());
+};
+struct BasicPersistent {
+ BasicPersistent(BasicPersistent &&,
+ SourceLocation = SourceLocation::Current());
+};
+void CFXJSE_EngineAddObjectToUpArray() { emplace_back(push_back___x); }
|
@@ -846,6 +846,7 @@ Bug Fixes to C++ Support | |||
- Fix a crash caused by improper use of ``__array_extent``. (#GH80474) | |||
- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), | |||
(#GH88081), (#GH89496), (#GH90669) and (#GH91633). | |||
- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Fix a crash when SourceLocExpr instantiated in a dependent context. (GH80210). | |
- Fix a crash when SourceLocExpr instantiated in a dependent context. (#GH80210). |
SourceLocation needs to be dependent because we want to make the name of the function and any template parameter The issue is that SourceLocation then is a dependent expression that does not depend on any parameters and its never re-transformed (hence the crash). I have so far been unable to find a solution. I wonder if we should attach the template parameters to the source location expression, but that seems a bit involved. |
Does that mean we should transform the |
I tested this patch locally with the code from #78128 and it works well. I doubt whether we need to make |
struct BasicPersistent;
struct SourceLocation {
static constexpr const char* Current(const char * func = __builtin_FUNCTION()) {
return func;
}
};
template <typename> BasicPersistent &&__declval(int);
template <typename _Tp> auto declval() -> decltype(__declval<_Tp>(0));
template <typename _Tp> _Tp forward;
template <typename _Tp, typename... _Args>
auto construct_at(_Tp *, _Args...) -> decltype(new _Tp(declval<_Args>()...)) {
constexpr auto *F = SourceLocation::Current();
static_assert(__builtin_strlen(F) == 12);
return 0;
}
template <typename> struct allocator;
template <typename> struct allocator_traits;
template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
using pointer = _Tp *;
template <typename _Up, typename... _Args>
static void construct(_Up __p, _Args...) {
construct_at(__p, forward<_Args>...);
}
};
struct __alloc_traits : allocator_traits<allocator<BasicPersistent>> {
} push_back___x;
__alloc_traits::pointer _M_impl_0;
template <typename... _Args> void emplace_back(_Args...) {
__alloc_traits::construct(_M_impl_0, forward<_Args>...);
}
struct BasicPersistent {
BasicPersistent(BasicPersistent &&,
const char* = SourceLocation::Current()) {}
};
void CFXJSE_EngineAddObjectToUpArray() { emplace_back(push_back___x); } I modify the testcase as above and I think we just need to make dependent if Kind is |
So, looked into this more. I apologize for not realizing earlier that your change was actually sensible in the case of |
nit: Please rephrase the commit message before you merge this patch. A large piece of AST involving memory addresses is really hard to decipher. In addition, it would be nice if you can simplify the test case further - it's super unclear why a bunch of templates are there outside of the |
Never mind! After looking into the code a little bit more, template<int N>
constexpr int g() {
return N;
}
template <typename T>
struct S {
void f(auto) {
constexpr const char* F = __builtin_FUNCSIG();
static_assert(__builtin_strlen(F)==g<__builtin_strlen(F)>());
}
};
void f(){
S<int>{}.f(0);
} However, it still crash when we changed from |
Consider the testcase, return type of
construct_at
iswhen in the process of instantiation. This type is dependent due to the dependency of
SourceLocExpr
which leads to the crash(only crash in codegen stage andclang-check -ast-dump
is OK).SourceLocExpr
is created in a dependent context when transforming the return type ofconstruct_at
because its context(Sema.CurContext
) is a dependentFunctionDecl
. ButSourceLocExpr
should not be dependent when we finish the transformation. RemovingSourceLocIdentKind::Function
makesSourceLocExpr
independent.attempt to fix #80210