Skip to content

Commit fc8d376

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 265bc5a commit fc8d376

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
@@ -7423,9 +7423,10 @@ def err_conditional_vector_element_size : Error<
74237423
def err_conditional_vector_has_void : Error<
74247424
"GNU vector conditional operand cannot be %select{void|a throw expression}0">;
74257425
def err_conditional_vector_operand_type
7426-
: Error<"%select{enumeration|extended vector}0 type %1 is not allowed in a "
7427-
"vector conditional">;
7428-
def err_conditional_vector_mismatched_vectors
7426+
: Error<"enumeration type %0 is not allowed in a vector conditional">;
7427+
def err_conditional_vector_cond_result_mismatch
7428+
: Error<"cannot mix vectors and extended vectors in a vector conditional">;
7429+
def err_conditional_vector_mismatched
74297430
: Error<"vector operands to the vector conditional must be the same type "
74307431
"%diff{($ and $)|}0,1}">;
74317432

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11557,9 +11557,9 @@ class Sema final {
1155711557
QualType CXXCheckConditionalOperands( // C++ 5.16
1155811558
ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
1155911559
ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
11560-
QualType CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
11561-
ExprResult &RHS,
11562-
SourceLocation QuestionLoc);
11560+
QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
11561+
ExprResult &RHS,
11562+
SourceLocation QuestionLoc);
1156311563
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
1156411564
bool ConvertArgs = true);
1156511565
QualType FindCompositePointerType(SourceLocation Loc,

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5970,19 +5970,18 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
59705970
// extension.
59715971
static bool isValidVectorForConditionalCondition(ASTContext &Ctx,
59725972
QualType CondTy) {
5973-
if (!CondTy->isVectorType() || CondTy->isExtVectorType())
5973+
if (!CondTy->isVectorType() && !CondTy->isExtVectorType())
59745974
return false;
59755975
const QualType EltTy =
59765976
cast<VectorType>(CondTy.getCanonicalType())->getElementType();
5977-
59785977
assert(!EltTy->isBooleanType() && !EltTy->isEnumeralType() &&
59795978
"Vectors cant be boolean or enum types");
59805979
return EltTy->isIntegralType(Ctx);
59815980
}
59825981

5983-
QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
5984-
ExprResult &RHS,
5985-
SourceLocation QuestionLoc) {
5982+
QualType Sema::CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
5983+
ExprResult &RHS,
5984+
SourceLocation QuestionLoc) {
59865985
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
59875986
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
59885987

@@ -5997,24 +5996,17 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
59975996

59985997
QualType ResultType;
59995998

6000-
// FIXME: In the future we should define what the Extvector conditional
6001-
// operator looks like.
6002-
if (LHSVT && isa<ExtVectorType>(LHSVT)) {
6003-
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
6004-
<< /*isExtVector*/ true << LHSType;
6005-
return {};
6006-
}
6007-
6008-
if (RHSVT && isa<ExtVectorType>(RHSVT)) {
6009-
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
6010-
<< /*isExtVector*/ true << RHSType;
6011-
return {};
6012-
}
60135999

60146000
if (LHSVT && RHSVT) {
6001+
if (isa<ExtVectorType>(CondVT) != isa<ExtVectorType>(LHSVT)) {
6002+
Diag(QuestionLoc, diag::err_conditional_vector_cond_result_mismatch)
6003+
<< /*isExtVector*/ isa<ExtVectorType>(CondVT);
6004+
return {};
6005+
}
6006+
60156007
// If both are vector types, they must be the same type.
60166008
if (!Context.hasSameType(LHSType, RHSType)) {
6017-
Diag(QuestionLoc, diag::err_conditional_vector_mismatched_vectors)
6009+
Diag(QuestionLoc, diag::err_conditional_vector_mismatched)
60186010
<< LHSType << RHSType;
60196011
return {};
60206012
}
@@ -6039,18 +6031,22 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
60396031

60406032
if (ResultElementTy->isEnumeralType()) {
60416033
Diag(QuestionLoc, diag::err_conditional_vector_operand_type)
6042-
<< /*isExtVector*/ false << ResultElementTy;
6034+
<< ResultElementTy;
60436035
return {};
60446036
}
6045-
ResultType = Context.getVectorType(
6046-
ResultElementTy, CondType->castAs<VectorType>()->getNumElements(),
6047-
VectorType::GenericVector);
6037+
if (CondType->isExtVectorType())
6038+
ResultType =
6039+
Context.getExtVectorType(ResultElementTy, CondVT->getNumElements());
6040+
else
6041+
ResultType = Context.getVectorType(
6042+
ResultElementTy, CondVT->getNumElements(), VectorType::GenericVector);
60486043

60496044
LHS = ImpCastExprToType(LHS.get(), ResultType, CK_VectorSplat);
60506045
RHS = ImpCastExprToType(RHS.get(), ResultType, CK_VectorSplat);
60516046
}
60526047

60536048
assert(!ResultType.isNull() && ResultType->isVectorType() &&
6049+
(!CondType->isExtVectorType() || ResultType->isExtVectorType()) &&
60546050
"Result should have been a vector type");
60556051
auto *ResultVectorTy = ResultType->castAs<VectorType>();
60566052
QualType ResultElementTy = ResultVectorTy->getElementType();
@@ -6077,15 +6073,21 @@ QualType Sema::CheckGNUVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
60776073
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
60786074
/// extension. In this case, LHS == Cond. (But they're not aliases.)
60796075
///
6080-
/// This function also implements GCC's vector extension for conditionals.
6081-
/// GCC's vector extension permits the use of a?b:c where the type of
6082-
/// a is that of a integer vector with the same number of elements and
6083-
/// size as the vectors of b and c. If one of either b or c is a scalar
6084-
/// it is implicitly converted to match the type of the vector.
6085-
/// Otherwise the expression is ill-formed. If both b and c are scalars,
6086-
/// then b and c are checked and converted to the type of a if possible.
6087-
/// Unlike the OpenCL ?: operator, the expression is evaluated as
6088-
/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
6076+
/// This function also implements GCC's vector extension and the
6077+
/// OpenCL/ext_vector_type extension for conditionals. The vector extensions
6078+
/// permit the use of a?b:c where the type of a is that of a integer vector with
6079+
/// the same number of elements and size as the vectors of b and c. If one of
6080+
/// either b or c is a scalar it is implicitly converted to match the type of
6081+
/// the vector. Otherwise the expression is ill-formed. If both b and c are
6082+
/// scalars, then b and c are checked and converted to the type of a if
6083+
/// possible.
6084+
///
6085+
/// The expressions are evaluated differently for GCC's and OpenCL's extensions.
6086+
/// For the GCC extension, the ?: operator is evaluated as
6087+
/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]).
6088+
/// For the OpenCL extensions, the ?: operator is evaluated as
6089+
/// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. ,
6090+
/// most-significant-bit-set(a[n]) ? b[n] : c[n]).
60896091
QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
60906092
ExprResult &RHS, ExprValueKind &VK,
60916093
ExprObjectKind &OK,
@@ -6169,7 +6171,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
61696171

61706172
// Neither is void.
61716173
if (IsVectorConditional)
6172-
return CheckGNUVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
6174+
return CheckVectorConditionalTypes(Cond, LHS, RHS, QuestionLoc);
61736175

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

0 commit comments

Comments
 (0)