[clang][bytecode] Fix a crash in CheckConstantExpression (#129752)
The APValue we generated for a pointer with a LValueReferenceType base
had an incorrect lvalue path attached.
The attached test case is extracted from libc++'s regex.cpp.
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp
index 324097a..8abdc54b 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -210,7 +210,8 @@
};
bool UsePath = true;
- if (getType()->isLValueReferenceType())
+ if (const ValueDecl *VD = getDeclDesc()->asValueDecl();
+ VD && VD->getType()->isLValueReferenceType())
UsePath = false;
// Build the path into the object.
diff --git a/clang/test/AST/ByteCode/references.cpp b/clang/test/AST/ByteCode/references.cpp
index 7610655..36609b7 100644
--- a/clang/test/AST/ByteCode/references.cpp
+++ b/clang/test/AST/ByteCode/references.cpp
@@ -140,3 +140,41 @@
static_assert(j.a.n == 1, ""); // both-error {{not an integral constant expression}} \
// both-note {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}}
}
+
+namespace Params {
+ typedef __SIZE_TYPE__ size_t;
+
+ template <class _Tp, size_t _Np>
+ constexpr _Tp* end(_Tp (&__array)[_Np]) noexcept {
+ return __array + _Np;
+ }
+
+
+ struct classnames {
+ const char* elem_;
+ int a;
+ };
+
+ constexpr classnames ClassNames[] = {
+ {"a", 0},
+ {"b", 1},
+ {"b", 1},
+ {"b", 1},
+ {"b", 1},
+ {"b", 1},
+ {"b", 1},
+ {"b", 1},
+ };
+
+ constexpr bool foo() {
+ /// This will instantiate end() with ClassNames.
+ /// In Sema, we will constant-evaluate the return statement, which is
+ /// something like __array + 8. The APValue we return for this
+ /// may NOT have a LValuePath set, since it's for a parameter
+ /// of LValueReferenceType.
+ end(ClassNames);
+ return true;
+ }
+
+ static_assert(foo());
+}