-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[clang][ExprConst] allow single element access of vector object to be constant expression #101126
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
… constant expression
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-clang Author: Vikram Hegde (vikramRH) ChangesThis is a slightly updated version of #72607 (I could not find a way to continue with the same PR, hopefully this is not very confusing). @sethp , I have tried addressing your views here although I have not given much thought on extending pathEntry for vector elements. originally authored by @yuanfang-chen (perhaps we could close the old PR?) Full diff: https://github.com/llvm/llvm-project/pull/101126.diff 7 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ddad083571eb1..2179aaea12387 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -64,6 +64,9 @@ sections with improvements to Clang's support for those languages.
C++ Language Changes
--------------------
+- Allow single element access of vector object to be constant expression.
+ Supports the `V.xyzw` syntax and other tidbits as seen in OpenCL.
+ Selecting multiple elements is left as a future work.
C++17 Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 558e20ed3e423..08f49ac896153 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -222,6 +222,11 @@ namespace {
ArraySize = 2;
MostDerivedLength = I + 1;
IsArray = true;
+ } else if (const auto *VT = Type->getAs<VectorType>()) {
+ Type = VT->getElementType();
+ ArraySize = VT->getNumElements();
+ MostDerivedLength = I + 1;
+ IsArray = true;
} else if (const FieldDecl *FD = getAsField(Path[I])) {
Type = FD->getType();
ArraySize = 0;
@@ -268,7 +273,6 @@ namespace {
/// If the current array is an unsized array, the value of this is
/// undefined.
uint64_t MostDerivedArraySize;
-
/// The type of the most derived object referred to by this address.
QualType MostDerivedType;
@@ -442,6 +446,16 @@ namespace {
MostDerivedArraySize = 2;
MostDerivedPathLength = Entries.size();
}
+
+ void addVectorElementUnchecked(QualType EltTy, uint64_t Size,
+ uint64_t Idx) {
+ Entries.push_back(PathEntry::ArrayIndex(Idx));
+ MostDerivedType = EltTy;
+ MostDerivedPathLength = Entries.size();
+ MostDerivedArraySize = 0;
+ MostDerivedIsArrayElement = false;
+ }
+
void diagnoseUnsizedArrayPointerArithmetic(EvalInfo &Info, const Expr *E);
void diagnosePointerArithmetic(EvalInfo &Info, const Expr *E,
const APSInt &N);
@@ -1737,6 +1751,11 @@ namespace {
if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real))
Designator.addComplexUnchecked(EltTy, Imag);
}
+ void addVectorElement(EvalInfo &Info, const Expr *E, QualType EltTy,
+ uint64_t Size, uint64_t Idx) {
+ if (checkSubobject(Info, E, CSK_VectorElement))
+ Designator.addVectorElementUnchecked(EltTy, Size, Idx);
+ }
void clearIsNullPointer() {
IsNullPtr = false;
}
@@ -3310,6 +3329,19 @@ static bool HandleLValueComplexElement(EvalInfo &Info, const Expr *E,
return true;
}
+static bool HandleLValueVectorElement(EvalInfo &Info, const Expr *E,
+ LValue &LVal, QualType EltTy,
+ uint64_t Size, uint64_t Idx) {
+ if (Idx) {
+ CharUnits SizeOfElement;
+ if (!HandleSizeof(Info, E->getExprLoc(), EltTy, SizeOfElement))
+ return false;
+ LVal.Offset += SizeOfElement * Idx;
+ }
+ LVal.addVectorElement(Info, E, EltTy, Size, Idx);
+ return true;
+}
+
/// Try to evaluate the initializer for a variable declaration.
///
/// \param Info Information about the ongoing evaluation.
@@ -3855,6 +3887,19 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
return handler.found(Index ? O->getComplexFloatImag()
: O->getComplexFloatReal(), ObjType);
}
+ } else if (const auto *VT = ObjType->getAs<VectorType>()) {
+ uint64_t Index = Sub.Entries[I].getAsArrayIndex();
+ if (Index >= VT->getNumElements()) {
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.FFDiag(E, diag::note_constexpr_access_past_end)
+ << handler.AccessKind;
+ else
+ Info.FFDiag(E);
+ return handler.failed();
+ }
+ ObjType = VT->getElementType();
+ assert(I == N - 1 && "extracting subobject of scalar?");
+ return handler.found(O->getVectorElt(Index), ObjType);
} else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
if (Field->isMutable() &&
!Obj.mayAccessMutableMembers(Info, handler.AccessKind)) {
@@ -8509,6 +8554,7 @@ class LValueExprEvaluator
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
+ bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
bool VisitUnaryDeref(const UnaryOperator *E);
bool VisitUnaryReal(const UnaryOperator *E);
bool VisitUnaryImag(const UnaryOperator *E);
@@ -8850,15 +8896,63 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
return LValueExprEvaluatorBaseTy::VisitMemberExpr(E);
}
+bool LValueExprEvaluator::VisitExtVectorElementExpr(
+ const ExtVectorElementExpr *E) {
+ bool Success = true;
+
+ APValue Val;
+ if (!Evaluate(Val, Info, E->getBase())) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+
+ SmallVector<uint32_t, 4> Indices;
+ E->getEncodedElementAccess(Indices);
+ // FIXME: support accessing more than one element
+ if (Indices.size() > 1)
+ return false;
+
+ if (Success) {
+ Result.setFrom(Info.Ctx, Val);
+ const auto *VT = E->getBase()->getType()->castAs<VectorType>();
+ HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
+ VT->getNumElements(), Indices[0]);
+ }
+
+ return Success;
+}
+
bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
- // FIXME: Deal with vectors as array subscript bases.
- if (E->getBase()->getType()->isVectorType() ||
- E->getBase()->getType()->isSveVLSBuiltinType())
+ if (E->getBase()->getType()->isSveVLSBuiltinType())
return Error(E);
APSInt Index;
bool Success = true;
+ if (const auto *VT = E->getBase()->getType()->getAs<VectorType>()) {
+ APValue Val;
+ if (!Evaluate(Val, Info, E->getBase())) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+
+ if (!EvaluateInteger(E->getIdx(), Index, Info)) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+
+ if (Success) {
+ Result.setFrom(Info.Ctx, Val);
+ HandleLValueVectorElement(Info, E, Result, VT->getElementType(),
+ VT->getNumElements(), Index.getExtValue());
+ }
+
+ return Success;
+ }
+
// C++17's rules require us to evaluate the LHS first, regardless of which
// side is the base.
for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) {
diff --git a/clang/lib/AST/Interp/State.h b/clang/lib/AST/Interp/State.h
index f1e8e3618f34f..44d6c037c5ad9 100644
--- a/clang/lib/AST/Interp/State.h
+++ b/clang/lib/AST/Interp/State.h
@@ -44,7 +44,8 @@ enum CheckSubobjectKind {
CSK_ArrayToPointer,
CSK_ArrayIndex,
CSK_Real,
- CSK_Imag
+ CSK_Imag,
+ CSK_VectorElement
};
namespace interp {
diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp
index 0a17106449faf..b179298fee9bd 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -866,11 +866,11 @@ namespace convertvector {
constexpr vector8BitInt128 from_vector8BitInt128_to_vector8BitInt128_var =
__builtin_convertvector((vector8BitInt128){0, 1, 2, 3, 4, 5, 6, 7},
vector8BitInt128);
- static_assert(from_vector8BitInt128_to_vector8BitInt128_var[0] == 0, ""); // ref-error {{not an integral constant expression}}
- static_assert(from_vector8BitInt128_to_vector8BitInt128_var[1] == 1, ""); // ref-error {{not an integral constant expression}}
- static_assert(from_vector8BitInt128_to_vector8BitInt128_var[2] == 2, ""); // ref-error {{not an integral constant expression}}
- static_assert(from_vector8BitInt128_to_vector8BitInt128_var[3] == 3, ""); // ref-error {{not an integral constant expression}}
- static_assert(from_vector8BitInt128_to_vector8BitInt128_var[4] == 4, ""); // ref-error {{not an integral constant expression}}
+ static_assert(from_vector8BitInt128_to_vector8BitInt128_var[0] == 0, "");
+ static_assert(from_vector8BitInt128_to_vector8BitInt128_var[1] == 1, "");
+ static_assert(from_vector8BitInt128_to_vector8BitInt128_var[2] == 2, "");
+ static_assert(from_vector8BitInt128_to_vector8BitInt128_var[3] == 3, "");
+ static_assert(from_vector8BitInt128_to_vector8BitInt128_var[4] == 4, "");
}
namespace shufflevector {
@@ -890,14 +890,14 @@ namespace shufflevector {
constexpr vector8char vectorShuffle6 = __builtin_shufflevector(
vector4charConst1, vector4charConst2, 0, 2, 4, 6, 1, 3, 5, 7);
- static_assert(vectorShuffle6[0] == 0, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[1] == 2, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[2] == 4, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[3] == 6, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[4] == 1, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[5] == 3, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[6] == 5, "");// ref-error {{not an integral constant expression}}
- static_assert(vectorShuffle6[7] == 7, "");// ref-error {{not an integral constant expression}}
+ static_assert(vectorShuffle6[0] == 0, "");
+ static_assert(vectorShuffle6[1] == 2, "");
+ static_assert(vectorShuffle6[2] == 4, "");
+ static_assert(vectorShuffle6[3] == 6, "");
+ static_assert(vectorShuffle6[4] == 1, "");
+ static_assert(vectorShuffle6[5] == 3, "");
+ static_assert(vectorShuffle6[6] == 5, "");
+ static_assert(vectorShuffle6[7] == 7, "");
constexpr vector4char vectorShuffleFail1 = __builtin_shufflevector( // both-error {{must be initialized by a constant expression}}\
// ref-error {{index for __builtin_shufflevector not within the bounds of the input vectors; index of -1 found at position 0 is not permitted in a constexpr context}}
diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp
index 6991a348b07a9..b6a9579f67ee2 100644
--- a/clang/test/AST/Interp/vectors.cpp
+++ b/clang/test/AST/Interp/vectors.cpp
@@ -3,25 +3,25 @@
typedef int __attribute__((vector_size(16))) VI4;
constexpr VI4 A = {1,2,3,4};
-static_assert(A[0] == 1, ""); // ref-error {{not an integral constant expression}}
-static_assert(A[1] == 2, ""); // ref-error {{not an integral constant expression}}
-static_assert(A[2] == 3, ""); // ref-error {{not an integral constant expression}}
-static_assert(A[3] == 4, ""); // ref-error {{not an integral constant expression}}
+static_assert(A[0] == 1, "");
+static_assert(A[1] == 2, "");
+static_assert(A[2] == 3, "");
+static_assert(A[3] == 4, "");
/// FIXME: It would be nice if the note said 'vector' instead of 'array'.
-static_assert(A[12] == 4, ""); // ref-error {{not an integral constant expression}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}}
+static_assert(A[12] == 4, ""); // both-error {{not an integral constant expression}} \
+ // expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}} \
+ // ref-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
/// VectorSplat casts
typedef __attribute__(( ext_vector_type(4) )) float float4;
constexpr float4 vec4_0 = (float4)0.5f;
-static_assert(vec4_0[0] == 0.5, ""); // ref-error {{not an integral constant expression}}
-static_assert(vec4_0[1] == 0.5, ""); // ref-error {{not an integral constant expression}}
-static_assert(vec4_0[2] == 0.5, ""); // ref-error {{not an integral constant expression}}
-static_assert(vec4_0[3] == 0.5, ""); // ref-error {{not an integral constant expression}}
+static_assert(vec4_0[0] == 0.5, "");
+static_assert(vec4_0[1] == 0.5, "");
+static_assert(vec4_0[2] == 0.5, "");
+static_assert(vec4_0[3] == 0.5, "");
constexpr int vec4_0_discarded = ((float4)12.0f, 0);
@@ -29,14 +29,14 @@ constexpr int vec4_0_discarded = ((float4)12.0f, 0);
constexpr float4 arr4[2] = {
{1,2,3,4},
};
-static_assert(arr4[0][0] == 1, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[0][1] == 2, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[0][2] == 3, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[0][3] == 4, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
-static_assert(arr4[1][0] == 0, ""); // ref-error {{not an integral constant expression}}
+static_assert(arr4[0][0] == 1, "");
+static_assert(arr4[0][1] == 2, "");
+static_assert(arr4[0][2] == 3, "");
+static_assert(arr4[0][3] == 4, "");
+static_assert(arr4[1][0] == 0, "");
+static_assert(arr4[1][0] == 0, "");
+static_assert(arr4[1][0] == 0, "");
+static_assert(arr4[1][0] == 0, "");
/// From constant-expression-cxx11.cpp
@@ -65,10 +65,10 @@ namespace {
namespace BoolToSignedIntegralCast{
typedef __attribute__((__ext_vector_type__(4))) unsigned int int4;
constexpr int4 intsT = (int4)true;
- static_assert(intsT[0] == -1, "");// ref-error {{not an integral constant expression}}
- static_assert(intsT[1] == -1, "");// ref-error {{not an integral constant expression}}
- static_assert(intsT[2] == -1, "");// ref-error {{not an integral constant expression}}
- static_assert(intsT[3] == -1, "");// ref-error {{not an integral constant expression}}
+ static_assert(intsT[0] == -1, "");
+ static_assert(intsT[1] == -1, "");
+ static_assert(intsT[2] == -1, "");
+ static_assert(intsT[3] == -1, "");
}
namespace VectorElementExpr {
@@ -78,8 +78,8 @@ namespace VectorElementExpr {
static_assert(oneElt == 3);
constexpr int2 twoElts = ((int4){11, 22, 33, 44}).yz;
- static_assert(twoElts.x == 22, ""); // ref-error {{not an integral constant expression}}
- static_assert(twoElts.y == 33, ""); // ref-error {{not an integral constant expression}}
+ static_assert(twoElts.x == 22, "");
+ static_assert(twoElts.y == 33, "");
}
namespace Temporaries {
diff --git a/clang/test/CodeGenCXX/temporaries.cpp b/clang/test/CodeGenCXX/temporaries.cpp
index 9f697bd9bf3ef..0990c804b8bcf 100644
--- a/clang/test/CodeGenCXX/temporaries.cpp
+++ b/clang/test/CodeGenCXX/temporaries.cpp
@@ -64,6 +64,26 @@ namespace RefTempSubobject {
constexpr const SelfReferential &sr = SelfReferential();
}
+namespace Vector {
+ typedef __attribute__((vector_size(16))) int vi4a;
+ typedef __attribute__((ext_vector_type(4))) int vi4b;
+ struct S {
+ vi4a v;
+ vi4b w;
+ };
+
+ int &&r = S().v[1];
+ // CHECK: @_ZGRN6Vector1rE_ = internal global i32 0, align 4
+ // CHECK: @_ZN6Vector1rE = constant ptr @_ZGRN6Vector1rE_, align 8
+
+ int &&s = S().w[1];
+ // CHECK: @_ZGRN6Vector1sE_ = internal global i32 0, align 4
+ // CHECK: @_ZN6Vector1sE = constant ptr @_ZGRN6Vector1sE_, align 8
+
+ int &&t = S().w.y;
+ // CHECK: @_ZGRN6Vector1tE_ = internal global i32 0, align 4
+ // CHECK: @_ZN6Vector1tE = constant ptr @_ZGRN6Vector1tE_, align 8
+}
struct A {
A();
~A();
@@ -665,27 +685,6 @@ namespace Bitfield {
int &&r = S().a;
}
-namespace Vector {
- typedef __attribute__((vector_size(16))) int vi4a;
- typedef __attribute__((ext_vector_type(4))) int vi4b;
- struct S {
- vi4a v;
- vi4b w;
- };
- // CHECK: alloca
- // CHECK: extractelement
- // CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1rE_
- // CHECK: store ptr @_ZGRN6Vector1rE_, ptr @_ZN6Vector1rE,
- int &&r = S().v[1];
-
- // CHECK: alloca
- // CHECK: extractelement
- // CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1sE_
- // CHECK: store ptr @_ZGRN6Vector1sE_, ptr @_ZN6Vector1sE,
- int &&s = S().w[1];
- int &&ss = S().w.y;
-}
-
namespace ImplicitTemporaryCleanup {
struct A { A(int); ~A(); };
void g();
diff --git a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp
new file mode 100644
index 0000000000000..d31db4c496840
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++17 -fsyntax-only -verify
+
+namespace Vector {
+
+using TwoIntsVecSize __attribute__((vector_size(8))) = int;
+
+constexpr TwoIntsVecSize a = {1,2};
+static_assert(a[1] == 2);
+static_assert(a[2]); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
+
+}
+
+namespace ExtVector {
+
+using FourIntsExtVec __attribute__((ext_vector_type(4))) = int;
+
+constexpr FourIntsExtVec b = {1,2,3,4};
+static_assert(b[0] == 1 && b[1] == 2 && b[2] == 3 && b[3] == 4);
+static_assert(b.s0 == 1 && b.s1 == 2 && b.s2 == 3 && b.s3 == 4);
+static_assert(b.x == 1 && b.y == 2 && b.z == 3 && b.w == 4);
+static_assert(b.r == 1 && b.g == 2 && b.b == 3 && b.a == 4);
+static_assert(b[5]); // expected-error {{not an integral constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
+
+// FIXME: support selecting multiple elements
+static_assert(b.lo.lo == 1); // expected-error {{not an integral constant expression}}
+// static_assert(b.lo.lo==1 && b.lo.hi==2 && b.hi.lo == 3 && b.hi.hi == 4);
+// static_assert(b.odd[0]==1 && b.odd[1]==2 && b.even[0] == 3 && b.even[1] == 4);
+
+}
|
clang/test/AST/Interp/vectors.cpp
Outdated
// expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}} | ||
static_assert(A[12] == 4, ""); // both-error {{not an integral constant expression}} \ | ||
// expected-note {{cannot refer to element 12 of array of 4 elements in a constant expression}} \ | ||
// ref-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} |
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.
Can you explain why this note is being generated? I don't see how A[12]
is a one-past-the-end pointer.
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.
I just kept the original version of the PR, but the message "cannot refer to element 12 of array of 4 elements" seems correct here. I shall update this
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.
done, let me know if the updated changes are okay
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.
Thank you for working to get this PR finished up. I see at least two comments from the previous PR not addressed here. Please, let's try and get those addressed.
@AaronBallman wanted a test to make sure we reject &V[0]
which I don't see: #72607 (comment)
|
||
void addVectorElementUnchecked(QualType EltTy, uint64_t Size, | ||
uint64_t Idx) { | ||
Entries.push_back(PathEntry::ArrayIndex(Idx)); |
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.
@sethp had a comment in the previous PR that is not address here: #72607 (comment)
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.
Yes, I thought about having a new accessor of the sort "vectorIndex" but all it seems to achieve is just adding new API that returns does the exact same thing as array (other than perhaps adding a new meaning to PathEntry value). I will update it if you feel this makes sense.
static_assert(A[0] == 1, ""); | ||
static_assert(A[1] == 2, ""); | ||
static_assert(A[2] == 3, ""); | ||
static_assert(A[3] == 4, ""); | ||
|
||
|
||
/// FIXME: It would be nice if the note said 'vector' instead of 'array'. |
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.
Resolving this fixme comment would be a nice follow-up.
If nobody else still has concerns, this LGTM from my end. |
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.
LGTM!
@vikramRH Do you need someone else to merge this for you? |
sorry for the delay, merged. |
… constant expression (llvm#101126) This is a slightly updated version of llvm#72607, originally authored by @yuanfang-chen Change-Id: Ifdf143d4d766b076bf3010048ab121932c83bb1e
… constant expression (llvm#101126) This is a slightly updated version of llvm#72607, originally authored by @yuanfang-chen Change-Id: Id9f94ebb5ce74e853ad9704c97170a128bfd2bc9
clang crashes compiling the following code.
I created a PR that fixes the crash: #136771 |
Clang crashes: https://godbolt.org/z/sx74s1bqd |
Can confirm the crash is happening. The issue is related to the constructor being Can you file an issue so we don't lose track of the bug? Also @vikramRH any chance you can look into this? |
@AaronBallman do you think my original example is well-defined according to the standard? I saw there is a warning |
It's well defined, even if only after c++20. It should work fine, but the root of the problem is pre-existing (which is why it also fails with complex values). |
@AaronBallman @tbaederr I can look into this, shall i assign #84315 to myself ? |
Yup! FWIW, we don't require assignments in GitHub issue, you're always welcome to post a PR even if an issue isn't assigned to you. |
This is a slightly updated version of #72607 (I could not find a way to continue with the same PR, hopefully this is not very confusing). @sethp , I have tried addressing your views here although I have not given much thought on extending pathEntry for vector elements.
originally authored by @yuanfang-chen (perhaps we could close the old PR?)