Skip to content

Commit 4eee13f

Browse files
committed
[ExtVectorType] Support conditional select operator for C++.
This patch implements the conditional select operator for ext_vector_types in C++. It does so by using the same semantics as for C. D71463 added support for the conditional select operator for VectorType in C++. Unfortunately the semantics between ext_vector_type in C are different to VectorType in C++. Select for ext_vector_type is based on the MSB of the condition vector, whereas for VectorType it is `!= 0`. This unfortunately means that the behavior is inconsistent between ExtVectorType and VectorType, but I think using the C semantics for ExtVectorType in C++ as well should be less surprising for users. Reviewed By: erichkeane, aaron.ballman Differential Revision: https://reviews.llvm.org/D98055
1 parent 775d335 commit 4eee13f

File tree

7 files changed

+503
-39
lines changed

7 files changed

+503
-39
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7478,9 +7478,10 @@ def err_conditional_vector_element_size : Error<
74787478
def err_conditional_vector_has_void : Error<
74797479
"GNU vector conditional operand cannot be %select{void|a throw expression}0">;
74807480
def err_conditional_vector_operand_type
7481-
: Error<"%select{enumeration|extended vector}0 type %1 is not allowed in a "
7482-
"vector conditional">;
7483-
def err_conditional_vector_mismatched_vectors
7481+
: Error<"enumeration type %0 is not allowed in a vector conditional">;
7482+
def err_conditional_vector_cond_result_mismatch
7483+
: Error<"cannot mix vectors and extended vectors in a vector conditional">;
7484+
def err_conditional_vector_mismatched
74847485
: Error<"vector operands to the vector conditional must be the same type "
74857486
"%diff{($ and $)|}0,1}">;
74867487

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11474,9 +11474,9 @@ class Sema final {
1147411474
QualType CXXCheckConditionalOperands( // C++ 5.16
1147511475
ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
1147611476
ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
11477-
QualType CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
11478-
ExprResult &RHS,
11479-
SourceLocation QuestionLoc);
11477+
QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
11478+
ExprResult &RHS,
11479+
SourceLocation QuestionLoc);
1148011480
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
1148111481
bool ConvertArgs = true);
1148211482
QualType FindCompositePointerType(SourceLocation Loc,

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5918,19 +5918,18 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
59185918
// extension.
59195919
static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
59205920
QualType CondTy) {
5921-
if (!CondTy->isVectorType() || CondTy->isExtVectorType())
5921+
if (!CondTy->isVectorType() && !CondTy->isExtVectorType())
59225922
return false;
59235923
const QualType EltTy =
59245924
cast<VectorType>(CondTy.getCanonicalType())->getElementType();
5925-
59265925
assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() &&
59275926
"Vectors cant be boolean or enum types");
59285927
return EltTy->isIntegralType(Ctx);
59295928
}
59305929

5931-
QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
5932-
ExprResult &RHS,
5933-
SourceLocation QuestionLoc) {
5930+
QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
5931+
ExprResult &RHS,
5932+
SourceLocation QuestionLoc) {
59345933
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
59355934
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
59365935

@@ -5945,24 +5944,17 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
59455944

59465945
QualType ResultType;
59475946

5948-
// FIXME: In the future we should define what the Extvector conditional
5949-
// operator looks like.
5950-
if (LHSVT && isa<ExtVectorType>(LHSVT)) {
5951-
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
5952-
<< /*isExtVector*/ true << LHSType;
5953-
return {};
5954-
}
5955-
5956-
if (RHSVT && isa<ExtVectorType>(RHSVT)) {
5957-
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
5958-
<< /*isExtVector*/ true << RHSType;
5959-
return {};
5960-
}
59615947

59625948
if (LHSVT && RHSVT) {
5949+
if (isa<ExtVectorType>(CondVT) != isa<ExtVectorType>(LHSVT)) {
5950+
Diag(QuestionLoc, diag::err_conditional_vector_cond_result_mismatch)
5951+
<< /*isExtVector*/ isa<ExtVectorType>(CondVT);
5952+
return {};
5953+
}
5954+
59635955
// If both are vector types, they must be the same type.
59645956
if (!Context.hasSameType(LHSType, RHSType)) {
5965-
Diag(QuestionLoc, diag::err_conditional_vector_mismatched_vectors)
5957+
Diag(QuestionLoc, diag::err_conditional_vector_mismatched)
59665958
<< LHSType << RHSType;
59675959
return {};
59685960
}
@@ -5987,18 +5979,22 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
59875979

59885980
if (ResultElementTy->isEnumeralType()) {
59895981
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
5990-
<< /*isExtVector*/ false << ResultElementTy;
5982+
<< ResultElementTy;
59915983
return {};
59925984
}
5993-
ResultType = Context.getVectorType(
5994-
ResultElementTy, CondType->castAs<VectorType>()->getNumElements(),
5995-
VectorType::GenericVector);
5985+
if (CondType->isExtVectorType())
5986+
ResultType =
5987+
Context.getExtVectorType(ResultElementTy, CondVT->getNumElements());
5988+
else
5989+
ResultType = Context.getVectorType(
5990+
ResultElementTy, CondVT->getNumElements(), VectorType::GenericVector);
59965991

59975992
LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
59985993
RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
59995994
}
60005995

60015996
assert(!ResultType.isNull() && ResultType->isVectorType() &&
5997+
(!CondType->isExtVectorType() || ResultType->isExtVectorType()) &&
60025998
"Result should have been a vector type");
60035999
auto *ResultVectorTy = ResultType->castAs<VectorType>();
60046000
QualType ResultElementTy = ResultVectorTy->getElementType();
@@ -6025,15 +6021,21 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
60256021
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
60266022
/// extension. In this case, LHS == Cond. (But they're not aliases.)
60276023
///
6028-
/// This function also implements GCC's vector extension for conditionals.
6029-
/// GCC's vector extension permits the use of a?b:c where the type of
6030-
/// a is that of a integer vector with the same number of elements and
6031-
/// size as the vectors of b and c. If one of either b or c is a scalar
6032-
/// it is implicitly converted to match the type of the vector.
6033-
/// Otherwise the expression is ill-formed. If both b and c are scalars,
6034-
/// then b and c are checked and converted to the type of a if possible.
6035-
/// Unlike the OpenCL ?: operator, the expression is evaluated as
6036-
/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
6024+
/// This function also implements GCC's vector extension and the
6025+
/// OpenCL/ext_vector_type extension for conditionals. The vector extensions
6026+
/// permit the use of a?b:c where the type of a is that of a integer vector with
6027+
/// the same number of elements and size as the vectors of b and c. If one of
6028+
/// either b or c is a scalar it is implicitly converted to match the type of
6029+
/// the vector. Otherwise the expression is ill-formed. If both b and c are
6030+
/// scalars, then b and c are checked and converted to the type of a if
6031+
/// possible.
6032+
///
6033+
/// The expressions are evaluated differently for GCC's and OpenCL's extensions.
6034+
/// For the GCC extension, the ?: operator is evaluated as
6035+
/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
6036+
/// For the OpenCL extensions, the ?: operator is evaluated as
6037+
/// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. ,
6038+
/// most-significant-bit-set(a[n]) ? b[n] : c[n]).
60376039
QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
60386040
ExprResult &RHS, ExprValueKind &VK,
60396041
ExprObjectKind &OK,
@@ -6117,7 +6119,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
61176119

61186120
// Neither is void.
61196121
if (IsVectorConditional)
6120-
return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
6122+
return CheckVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
61216123

61226124
// C++11 [expr.cond]p3
61236125
// Otherwise, if the second and third operand have different types, and

0 commit comments

Comments
 (0)