Skip to content

Commit 76079ec

Browse files
authored
[clang][Sema] Merge Check[Sizeless]VectorConditionalTypes implementations (#169165)
These two functions are almost identical, except for the handling different vector types, so merging them eliminates some duplication. This also fixes some bugs, as "sizeless" vector code was missing checks for several cases. This meant type checking would crash if: - The LHS or RHS type was void - The LHS or RHS type was a fixed-length vector type - There was not a scalable vector type for the result element count/size These are fixed with this patch and tested in Sema/AArch64/sve-vector-conditional-op.cpp. Fixes #169025
1 parent 1965523 commit 76079ec

File tree

4 files changed

+93
-134
lines changed

4 files changed

+93
-134
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8661,6 +8661,8 @@ def err_conditional_vector_size : Error<
86618661
def err_conditional_vector_element_size : Error<
86628662
"vector condition type %0 and result type %1 do not have elements of the "
86638663
"same size">;
8664+
def err_conditional_vector_scalar_type_unsupported : Error<
8665+
"scalar type %0 not supported with vector condition type %1">;
86648666
def err_conditional_vector_has_void : Error<
86658667
"GNU vector conditional operand cannot be %select{void|a throw expression}0">;
86668668
def err_conditional_vector_operand_type

clang/include/clang/Sema/Sema.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8721,10 +8721,6 @@ class Sema final : public SemaBase {
87218721
ExprResult &RHS,
87228722
SourceLocation QuestionLoc);
87238723

8724-
QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond,
8725-
ExprResult &LHS, ExprResult &RHS,
8726-
SourceLocation QuestionLoc);
8727-
87288724
//// Determines if a type is trivially relocatable
87298725
/// according to the C++26 rules.
87308726
// FIXME: This is in Sema because it requires

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 54 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -5658,20 +5658,13 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
56585658
// extension.
56595659
static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
56605660
QualType CondTy) {
5661-
if (!CondTy->isVectorType() && !CondTy->isExtVectorType())
5661+
bool IsSVEVectorType = CondTy->isSveVLSBuiltinType();
5662+
if (!CondTy->isVectorType() && !CondTy->isExtVectorType() && !IsSVEVectorType)
56625663
return false;
56635664
const QualType EltTy =
5664-
cast<VectorType>(CondTy.getCanonicalType())->getElementType();
5665-
assert(!EltTy->isEnumeralType() && "Vectors cant be enum types");
5666-
return EltTy->isIntegralType(Ctx);
5667-
}
5668-
5669-
static bool isValidSizelessVectorForConditionalCondition(ASTContext &Ctx,
5670-
QualType CondTy) {
5671-
if (!CondTy->isSveVLSBuiltinType())
5672-
return false;
5673-
const QualType EltTy =
5674-
cast<BuiltinType>(CondTy.getCanonicalType())->getSveEltType(Ctx);
5665+
IsSVEVectorType
5666+
? cast<BuiltinType>(CondTy.getCanonicalType())->getSveEltType(Ctx)
5667+
: cast<VectorType>(CondTy.getCanonicalType())->getElementType();
56755668
assert(!EltTy->isEnumeralType() && "Vectors cant be enum types");
56765669
return EltTy->isIntegralType(Ctx);
56775670
}
@@ -5683,21 +5676,29 @@ QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
56835676
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
56845677

56855678
QualType CondType = Cond.get()->getType();
5686-
const auto *CondVT = CondType->castAs<VectorType>();
5687-
QualType CondElementTy = CondVT->getElementType();
5688-
unsigned CondElementCount = CondVT->getNumElements();
56895679
QualType LHSType = LHS.get()->getType();
5690-
const auto *LHSVT = LHSType->getAs<VectorType>();
56915680
QualType RHSType = RHS.get()->getType();
5692-
const auto *RHSVT = RHSType->getAs<VectorType>();
56935681

5694-
QualType ResultType;
5682+
bool LHSIsVector = LHSType->isVectorType() || LHSType->isSizelessVectorType();
5683+
bool RHSIsVector = RHSType->isVectorType() || RHSType->isSizelessVectorType();
5684+
5685+
auto GetVectorInfo =
5686+
[&](QualType Type) -> std::pair<QualType, llvm::ElementCount> {
5687+
if (const auto *VT = Type->getAs<VectorType>())
5688+
return std::make_pair(VT->getElementType(),
5689+
llvm::ElementCount::getFixed(VT->getNumElements()));
5690+
ASTContext::BuiltinVectorTypeInfo VectorInfo =
5691+
Context.getBuiltinVectorTypeInfo(Type->castAs<BuiltinType>());
5692+
return std::make_pair(VectorInfo.ElementType, VectorInfo.EC);
5693+
};
56955694

5695+
auto [CondElementTy, CondElementCount] = GetVectorInfo(CondType);
56965696

5697-
if (LHSVT && RHSVT) {
5698-
if (isa<ExtVectorType>(CondVT) != isa<ExtVectorType>(LHSVT)) {
5697+
QualType ResultType;
5698+
if (LHSIsVector && RHSIsVector) {
5699+
if (CondType->isExtVectorType() != LHSType->isExtVectorType()) {
56995700
Diag(QuestionLoc, diag::err_conditional_vector_cond_result_mismatch)
5700-
<< /*isExtVector*/ isa<ExtVectorType>(CondVT);
5701+
<< /*isExtVector*/ CondType->isExtVectorType();
57015702
return {};
57025703
}
57035704

@@ -5708,12 +5709,17 @@ QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
57085709
return {};
57095710
}
57105711
ResultType = Context.getCommonSugaredType(LHSType, RHSType);
5711-
} else if (LHSVT || RHSVT) {
5712-
ResultType = CheckVectorOperands(
5713-
LHS, RHS, QuestionLoc, /*isCompAssign*/ false, /*AllowBothBool*/ true,
5714-
/*AllowBoolConversions*/ false,
5715-
/*AllowBoolOperation*/ true,
5716-
/*ReportInvalid*/ true);
5712+
} else if (LHSIsVector || RHSIsVector) {
5713+
if (CondType->isSizelessVectorType())
5714+
ResultType = CheckSizelessVectorOperands(LHS, RHS, QuestionLoc,
5715+
/*IsCompAssign*/ false,
5716+
ArithConvKind::Conditional);
5717+
else
5718+
ResultType = CheckVectorOperands(
5719+
LHS, RHS, QuestionLoc, /*isCompAssign*/ false, /*AllowBothBool*/ true,
5720+
/*AllowBoolConversions*/ false,
5721+
/*AllowBoolOperation*/ true,
5722+
/*ReportInvalid*/ true);
57175723
if (ResultType.isNull())
57185724
return {};
57195725
} else {
@@ -5731,24 +5737,33 @@ QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
57315737
<< ResultElementTy;
57325738
return {};
57335739
}
5734-
if (CondType->isExtVectorType())
5735-
ResultType =
5736-
Context.getExtVectorType(ResultElementTy, CondVT->getNumElements());
5737-
else
5738-
ResultType = Context.getVectorType(
5739-
ResultElementTy, CondVT->getNumElements(), VectorKind::Generic);
5740-
5740+
if (CondType->isExtVectorType()) {
5741+
ResultType = Context.getExtVectorType(ResultElementTy,
5742+
CondElementCount.getFixedValue());
5743+
} else if (CondType->isSizelessVectorType()) {
5744+
ResultType = Context.getScalableVectorType(
5745+
ResultElementTy, CondElementCount.getKnownMinValue());
5746+
// There are not scalable vector type mappings for all element counts.
5747+
if (ResultType.isNull()) {
5748+
Diag(QuestionLoc, diag::err_conditional_vector_scalar_type_unsupported)
5749+
<< ResultElementTy << CondType;
5750+
return {};
5751+
}
5752+
} else {
5753+
ResultType = Context.getVectorType(ResultElementTy,
5754+
CondElementCount.getFixedValue(),
5755+
VectorKind::Generic);
5756+
}
57415757
LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
57425758
RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
57435759
}
57445760

5745-
assert(!ResultType.isNull() && ResultType->isVectorType() &&
5761+
assert(!ResultType.isNull() &&
5762+
(ResultType->isVectorType() || ResultType->isSizelessVectorType()) &&
57465763
(!CondType->isExtVectorType() || ResultType->isExtVectorType()) &&
57475764
"Result should have been a vector type");
5748-
auto *ResultVectorTy = ResultType->castAs<VectorType>();
5749-
QualType ResultElementTy = ResultVectorTy->getElementType();
5750-
unsigned ResultElementCount = ResultVectorTy->getNumElements();
57515765

5766+
auto [ResultElementTy, ResultElementCount] = GetVectorInfo(ResultType);
57525767
if (ResultElementCount != CondElementCount) {
57535768
Diag(QuestionLoc, diag::err_conditional_vector_size) << CondType
57545769
<< ResultType;
@@ -5767,90 +5782,6 @@ QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
57675782
return ResultType;
57685783
}
57695784

5770-
QualType Sema::CheckSizelessVectorConditionalTypes(ExprResult &Cond,
5771-
ExprResult &LHS,
5772-
ExprResult &RHS,
5773-
SourceLocation QuestionLoc) {
5774-
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
5775-
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
5776-
5777-
QualType CondType = Cond.get()->getType();
5778-
const auto *CondBT = CondType->castAs<BuiltinType>();
5779-
QualType CondElementTy = CondBT->getSveEltType(Context);
5780-
llvm::ElementCount CondElementCount =
5781-
Context.getBuiltinVectorTypeInfo(CondBT).EC;
5782-
5783-
QualType LHSType = LHS.get()->getType();
5784-
const auto *LHSBT =
5785-
LHSType->isSveVLSBuiltinType() ? LHSType->getAs<BuiltinType>() : nullptr;
5786-
QualType RHSType = RHS.get()->getType();
5787-
const auto *RHSBT =
5788-
RHSType->isSveVLSBuiltinType() ? RHSType->getAs<BuiltinType>() : nullptr;
5789-
5790-
QualType ResultType;
5791-
5792-
if (LHSBT && RHSBT) {
5793-
// If both are sizeless vector types, they must be the same type.
5794-
if (!Context.hasSameType(LHSType, RHSType)) {
5795-
Diag(QuestionLoc, diag::err_conditional_vector_mismatched)
5796-
<< LHSType << RHSType;
5797-
return QualType();
5798-
}
5799-
ResultType = LHSType;
5800-
} else if (LHSBT || RHSBT) {
5801-
ResultType = CheckSizelessVectorOperands(LHS, RHS, QuestionLoc,
5802-
/*IsCompAssign*/ false,
5803-
ArithConvKind::Conditional);
5804-
if (ResultType.isNull())
5805-
return QualType();
5806-
} else {
5807-
// Both are scalar so splat
5808-
QualType ResultElementTy;
5809-
LHSType = LHSType.getCanonicalType().getUnqualifiedType();
5810-
RHSType = RHSType.getCanonicalType().getUnqualifiedType();
5811-
5812-
if (Context.hasSameType(LHSType, RHSType))
5813-
ResultElementTy = LHSType;
5814-
else
5815-
ResultElementTy = UsualArithmeticConversions(LHS, RHS, QuestionLoc,
5816-
ArithConvKind::Conditional);
5817-
5818-
if (ResultElementTy->isEnumeralType()) {
5819-
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
5820-
<< ResultElementTy;
5821-
return QualType();
5822-
}
5823-
5824-
ResultType = Context.getScalableVectorType(
5825-
ResultElementTy, CondElementCount.getKnownMinValue());
5826-
5827-
LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
5828-
RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
5829-
}
5830-
5831-
assert(!ResultType.isNull() && ResultType->isSveVLSBuiltinType() &&
5832-
"Result should have been a vector type");
5833-
auto *ResultBuiltinTy = ResultType->castAs<BuiltinType>();
5834-
QualType ResultElementTy = ResultBuiltinTy->getSveEltType(Context);
5835-
llvm::ElementCount ResultElementCount =
5836-
Context.getBuiltinVectorTypeInfo(ResultBuiltinTy).EC;
5837-
5838-
if (ResultElementCount != CondElementCount) {
5839-
Diag(QuestionLoc, diag::err_conditional_vector_size)
5840-
<< CondType << ResultType;
5841-
return QualType();
5842-
}
5843-
5844-
if (Context.getTypeSize(ResultElementTy) !=
5845-
Context.getTypeSize(CondElementTy)) {
5846-
Diag(QuestionLoc, diag::err_conditional_vector_element_size)
5847-
<< CondType << ResultType;
5848-
return QualType();
5849-
}
5850-
5851-
return ResultType;
5852-
}
5853-
58545785
QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
58555786
ExprResult &RHS, ExprValueKind &VK,
58565787
ExprObjectKind &OK,
@@ -5864,14 +5795,10 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
58645795
bool IsVectorConditional =
58655796
isValidVectorForConditionalCondition(Context, Cond.get()->getType());
58665797

5867-
bool IsSizelessVectorConditional =
5868-
isValidSizelessVectorForConditionalCondition(Context,
5869-
Cond.get()->getType());
5870-
58715798
// C++11 [expr.cond]p1
58725799
// The first expression is contextually converted to bool.
58735800
if (!Cond.get()->isTypeDependent()) {
5874-
ExprResult CondRes = IsVectorConditional || IsSizelessVectorConditional
5801+
ExprResult CondRes = IsVectorConditional
58755802
? DefaultFunctionArrayLvalueConversion(Cond.get())
58765803
: CheckCXXBooleanCondition(Cond.get());
58775804
if (CondRes.isInvalid())
@@ -5940,9 +5867,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
59405867
if (IsVectorConditional)
59415868
return CheckVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
59425869

5943-
if (IsSizelessVectorConditional)
5944-
return CheckSizelessVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
5945-
59465870
// WebAssembly tables are not allowed as conditional LHS or RHS.
59475871
if (LTy->isWebAssemblyTableType() || RTy->isWebAssemblyTableType()) {
59485872
Diag(QuestionLoc, diag::err_wasm_table_conditional_expression)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -triple aarch64-none-linux-gnu -target-feature +sve -verify
2+
3+
typedef int fixed_vector __attribute__((vector_size(4)));
4+
5+
auto error_fixed_vector_result(__SVBool_t svbool, fixed_vector a, fixed_vector b) {
6+
// expected-error@+1 {{vector condition type '__SVBool_t' and result type 'fixed_vector' (vector of 1 'int' value) do not have the same number of elements}}
7+
return svbool ? a : b;
8+
}
9+
10+
auto error_void_result(__SVBool_t svbool) {
11+
// expected-error@+1 {{GNU vector conditional operand cannot be void}}
12+
return svbool ? (void)0 : (void)1;
13+
}
14+
15+
auto error_sve_splat_result_unsupported(__SVBool_t svbool, long long a, long long b) {
16+
// expected-error@+1 {{scalar type 'long long' not supported with vector condition type '__SVBool_t'}}
17+
return svbool ? a : b;
18+
}
19+
20+
auto error_sve_vector_result_matched_element_count(__SVBool_t svbool, __SVUint32_t a, __SVUint32_t b) {
21+
// expected-error@+1 {{vector condition type '__SVBool_t' and result type '__SVUint32_t' do not have the same number of elements}}
22+
return svbool ? a : b;
23+
}
24+
25+
// The following cases should be supported:
26+
27+
__SVBool_t cond_svbool(__SVBool_t a, __SVBool_t b) {
28+
return a < b ? a : b;
29+
}
30+
31+
__SVFloat32_t cond_svf32(__SVFloat32_t a, __SVFloat32_t b) {
32+
return a < b ? a : b;
33+
}
34+
35+
__SVUint64_t cond_u64_splat(__SVUint64_t a) {
36+
return a < 1ul ? a : 1ul;
37+
}

0 commit comments

Comments
 (0)