[OpenCL] Support template parameters for as_type

Implement the TreeTransform for AsTypeExpr.  Split `BuildAsTypeExpr`
out of `ActOnAsTypeExpr`, such that we can call the Build method from
the TreeTransform.

Fixes PR47979.

Differential Revision: https://reviews.llvm.org/D98855
This commit is contained in:
Sven van Haastregt 2021-03-22 11:59:05 +00:00
parent f71404c37c
commit 2bbc9bccf0
4 changed files with 49 additions and 10 deletions

View File

@ -5581,6 +5581,9 @@ public:
ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc);
ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc);
//===---------------------------- C++ Features --------------------------===//

View File

@ -6497,24 +6497,30 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
ExecConfig, IsExecConfig);
}
/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments.
/// Parse a __builtin_astype expression.
///
/// __builtin_astype( value, dst type )
///
ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
QualType DstTy = GetTypeFromParser(ParsedDestTy);
return BuildAsTypeExpr(E, DstTy, BuiltinLoc, RParenLoc);
}
/// Create a new AsTypeExpr node (bitcast) from the arguments.
ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType DstTy = GetTypeFromParser(ParsedDestTy);
QualType SrcTy = E->getType();
if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy))
return ExprError(Diag(BuiltinLoc,
diag::err_invalid_astype_of_different_size)
<< DstTy
<< SrcTy
<< E->getSourceRange());
return new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, RParenLoc);
if (!SrcTy->isDependentType() &&
Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
return ExprError(
Diag(BuiltinLoc, diag::err_invalid_astype_of_different_size)
<< DestTy << SrcTy << E->getSourceRange());
return new (Context) AsTypeExpr(E, DestTy, VK, OK, BuiltinLoc, RParenLoc);
}
/// ActOnConvertVectorExpr - create a new convert-vector expression from the

View File

@ -13971,7 +13971,14 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) {
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) {
llvm_unreachable("Cannot transform asType expressions yet");
ExprResult SrcExpr = getDerived().TransformExpr(E->getSrcExpr());
if (SrcExpr.isInvalid())
return ExprError();
QualType Type = getDerived().TransformType(E->getType());
return SemaRef.BuildAsTypeExpr(SrcExpr.get(), Type, E->getBuiltinLoc(),
E->getRParenLoc());
}
template<typename Derived>

View File

@ -0,0 +1,23 @@
// RUN: %clang_cc1 -fdeclare-opencl-builtins -finclude-default-header %s -cl-std=clc++ -verify
// Test as_type, which is defined in terms of __builtin_astype.
template <typename T>
auto templated_astype(T x) {
return as_int2(x);
// expected-error@-1{{invalid reinterpretation: sizes of 'int2' (vector of 2 'int' values) and '__private int' must match}}
}
auto test_long(long x) { return templated_astype(x); }
auto neg_test_int(int x) { return templated_astype(x); }
// expected-note@-1{{in instantiation of function template specialization 'templated_astype<int>' requested here}}
auto test_short4(short4 x) { return templated_astype(x); }
// Test __builtin_astype.
template <typename T>
auto templated_builtin_astype(T x) {
return __builtin_astype(x, int2);
}
auto test_builtin(char8 x) { return templated_builtin_astype(x); }