forked from OSchip/llvm-project
[OpenCL] Added addrspace_cast operator in C++ mode.
This operator is intended for casting between pointers to objects in different address spaces and follows similar logic as const_cast in C++. Tags: #clang Differential Revision: https://reviews.llvm.org/D60193
This commit is contained in:
parent
f997370d9c
commit
a6a237f204
|
@ -2052,58 +2052,62 @@ enum CXCursorKind {
|
|||
*/
|
||||
CXCursor_CXXFunctionalCastExpr = 128,
|
||||
|
||||
/** OpenCL's addrspace_cast<> expression.
|
||||
*/
|
||||
CXCursor_CXXAddrspaceCastExpr = 129,
|
||||
|
||||
/** A C++ typeid expression (C++ [expr.typeid]).
|
||||
*/
|
||||
CXCursor_CXXTypeidExpr = 129,
|
||||
CXCursor_CXXTypeidExpr = 130,
|
||||
|
||||
/** [C++ 2.13.5] C++ Boolean Literal.
|
||||
*/
|
||||
CXCursor_CXXBoolLiteralExpr = 130,
|
||||
CXCursor_CXXBoolLiteralExpr = 131,
|
||||
|
||||
/** [C++0x 2.14.7] C++ Pointer Literal.
|
||||
*/
|
||||
CXCursor_CXXNullPtrLiteralExpr = 131,
|
||||
CXCursor_CXXNullPtrLiteralExpr = 132,
|
||||
|
||||
/** Represents the "this" expression in C++
|
||||
*/
|
||||
CXCursor_CXXThisExpr = 132,
|
||||
CXCursor_CXXThisExpr = 133,
|
||||
|
||||
/** [C++ 15] C++ Throw Expression.
|
||||
*
|
||||
* This handles 'throw' and 'throw' assignment-expression. When
|
||||
* assignment-expression isn't present, Op will be null.
|
||||
*/
|
||||
CXCursor_CXXThrowExpr = 133,
|
||||
CXCursor_CXXThrowExpr = 134,
|
||||
|
||||
/** A new expression for memory allocation and constructor calls, e.g:
|
||||
* "new CXXNewExpr(foo)".
|
||||
*/
|
||||
CXCursor_CXXNewExpr = 134,
|
||||
CXCursor_CXXNewExpr = 135,
|
||||
|
||||
/** A delete expression for memory deallocation and destructor calls,
|
||||
* e.g. "delete[] pArray".
|
||||
*/
|
||||
CXCursor_CXXDeleteExpr = 135,
|
||||
CXCursor_CXXDeleteExpr = 136,
|
||||
|
||||
/** A unary expression. (noexcept, sizeof, or other traits)
|
||||
*/
|
||||
CXCursor_UnaryExpr = 136,
|
||||
CXCursor_UnaryExpr = 137,
|
||||
|
||||
/** An Objective-C string literal i.e. @"foo".
|
||||
*/
|
||||
CXCursor_ObjCStringLiteral = 137,
|
||||
CXCursor_ObjCStringLiteral = 138,
|
||||
|
||||
/** An Objective-C \@encode expression.
|
||||
*/
|
||||
CXCursor_ObjCEncodeExpr = 138,
|
||||
CXCursor_ObjCEncodeExpr = 139,
|
||||
|
||||
/** An Objective-C \@selector expression.
|
||||
*/
|
||||
CXCursor_ObjCSelectorExpr = 139,
|
||||
CXCursor_ObjCSelectorExpr = 140,
|
||||
|
||||
/** An Objective-C \@protocol expression.
|
||||
*/
|
||||
CXCursor_ObjCProtocolExpr = 140,
|
||||
CXCursor_ObjCProtocolExpr = 141,
|
||||
|
||||
/** An Objective-C "bridged" cast expression, which casts between
|
||||
* Objective-C pointers and C pointers, transferring ownership in the process.
|
||||
|
@ -2112,7 +2116,7 @@ enum CXCursorKind {
|
|||
* NSString *str = (__bridge_transfer NSString *)CFCreateString();
|
||||
* \endcode
|
||||
*/
|
||||
CXCursor_ObjCBridgedCastExpr = 141,
|
||||
CXCursor_ObjCBridgedCastExpr = 142,
|
||||
|
||||
/** Represents a C++0x pack expansion that produces a sequence of
|
||||
* expressions.
|
||||
|
@ -2127,7 +2131,7 @@ enum CXCursorKind {
|
|||
* }
|
||||
* \endcode
|
||||
*/
|
||||
CXCursor_PackExpansionExpr = 142,
|
||||
CXCursor_PackExpansionExpr = 143,
|
||||
|
||||
/** Represents an expression that computes the length of a parameter
|
||||
* pack.
|
||||
|
@ -2139,7 +2143,7 @@ enum CXCursorKind {
|
|||
* };
|
||||
* \endcode
|
||||
*/
|
||||
CXCursor_SizeOfPackExpr = 143,
|
||||
CXCursor_SizeOfPackExpr = 144,
|
||||
|
||||
/* Represents a C++ lambda expression that produces a local function
|
||||
* object.
|
||||
|
@ -2153,37 +2157,37 @@ enum CXCursorKind {
|
|||
* }
|
||||
* \endcode
|
||||
*/
|
||||
CXCursor_LambdaExpr = 144,
|
||||
CXCursor_LambdaExpr = 145,
|
||||
|
||||
/** Objective-c Boolean Literal.
|
||||
*/
|
||||
CXCursor_ObjCBoolLiteralExpr = 145,
|
||||
CXCursor_ObjCBoolLiteralExpr = 146,
|
||||
|
||||
/** Represents the "self" expression in an Objective-C method.
|
||||
*/
|
||||
CXCursor_ObjCSelfExpr = 146,
|
||||
CXCursor_ObjCSelfExpr = 147,
|
||||
|
||||
/** OpenMP 4.0 [2.4, Array Section].
|
||||
*/
|
||||
CXCursor_OMPArraySectionExpr = 147,
|
||||
CXCursor_OMPArraySectionExpr = 148,
|
||||
|
||||
/** Represents an @available(...) check.
|
||||
*/
|
||||
CXCursor_ObjCAvailabilityCheckExpr = 148,
|
||||
CXCursor_ObjCAvailabilityCheckExpr = 149,
|
||||
|
||||
/**
|
||||
* Fixed point literal
|
||||
*/
|
||||
CXCursor_FixedPointLiteral = 149,
|
||||
CXCursor_FixedPointLiteral = 150,
|
||||
|
||||
/** OpenMP 5.0 [2.1.4, Array Shaping].
|
||||
*/
|
||||
CXCursor_OMPArrayShapingExpr = 150,
|
||||
CXCursor_OMPArrayShapingExpr = 151,
|
||||
|
||||
/**
|
||||
* OpenMP 5.0 [2.1.6 Iterators]
|
||||
*/
|
||||
CXCursor_OMPIteratorExpr = 151,
|
||||
CXCursor_OMPIteratorExpr = 152,
|
||||
|
||||
CXCursor_LastExpr = CXCursor_OMPIteratorExpr,
|
||||
|
||||
|
|
|
@ -366,7 +366,8 @@ public:
|
|||
/// This abstract class is inherited by all of the classes
|
||||
/// representing "named" casts: CXXStaticCastExpr for \c static_cast,
|
||||
/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for
|
||||
/// reinterpret_cast, and CXXConstCastExpr for \c const_cast.
|
||||
/// reinterpret_cast, CXXConstCastExpr for \c const_cast and
|
||||
/// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL).
|
||||
class CXXNamedCastExpr : public ExplicitCastExpr {
|
||||
private:
|
||||
// the location of the casting op
|
||||
|
@ -412,6 +413,7 @@ public:
|
|||
case CXXDynamicCastExprClass:
|
||||
case CXXReinterpretCastExprClass:
|
||||
case CXXConstCastExprClass:
|
||||
case CXXAddrspaceCastExprClass:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -569,6 +571,41 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// A C++ addrspace_cast expression (currently only enabled for OpenCL).
|
||||
///
|
||||
/// This expression node represents a cast between pointers to objects in
|
||||
/// different address spaces e.g.,
|
||||
/// \c addrspace_cast<global int*>(PtrToGenericInt).
|
||||
///
|
||||
/// A addrspace_cast can cast address space type qualifiers but does not change
|
||||
/// the underlying value.
|
||||
class CXXAddrspaceCastExpr final
|
||||
: public CXXNamedCastExpr,
|
||||
private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> {
|
||||
CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op,
|
||||
TypeSourceInfo *writtenTy, SourceLocation l,
|
||||
SourceLocation RParenLoc, SourceRange AngleBrackets)
|
||||
: CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0,
|
||||
writtenTy, l, RParenLoc, AngleBrackets) {}
|
||||
|
||||
explicit CXXAddrspaceCastExpr(EmptyShell Empty)
|
||||
: CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0) {}
|
||||
|
||||
public:
|
||||
friend class CastExpr;
|
||||
friend TrailingObjects;
|
||||
|
||||
static CXXAddrspaceCastExpr *
|
||||
Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind,
|
||||
Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L,
|
||||
SourceLocation RParenLoc, SourceRange AngleBrackets);
|
||||
static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXAddrspaceCastExprClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// A call to a literal operator (C++11 [over.literal])
|
||||
/// written as a user-defined literal (C++11 [lit.ext]).
|
||||
///
|
||||
|
|
|
@ -2355,6 +2355,10 @@ DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
|
|||
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXAddrspaceCastExpr, {
|
||||
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_STMT(CXXConstCastExpr, {
|
||||
TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
|
||||
})
|
||||
|
|
|
@ -833,7 +833,7 @@ def err_friend_decl_defines_type : Error<
|
|||
"cannot define a type in a friend declaration">;
|
||||
def err_missing_whitespace_digraph : Error<
|
||||
"found '<::' after a "
|
||||
"%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0"
|
||||
"%select{template name|addrspace_cast|const_cast|dynamic_cast|reinterpret_cast|static_cast}0"
|
||||
" which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">;
|
||||
|
||||
def ext_defaulted_deleted_function : ExtWarn<
|
||||
|
|
|
@ -4221,13 +4221,13 @@ def err_ovl_no_conversion_in_cast : Error<
|
|||
"cannot convert %1 to %2 without a conversion operator">;
|
||||
def err_ovl_no_viable_conversion_in_cast : Error<
|
||||
"no matching conversion for %select{|static_cast|reinterpret_cast|"
|
||||
"dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
|
||||
"dynamic_cast|C-style cast|functional-style cast|}0 from %1 to %2">;
|
||||
def err_ovl_ambiguous_conversion_in_cast : Error<
|
||||
"ambiguous conversion for %select{|static_cast|reinterpret_cast|"
|
||||
"dynamic_cast|C-style cast|functional-style cast}0 from %1 to %2">;
|
||||
"dynamic_cast|C-style cast|functional-style cast|}0 from %1 to %2">;
|
||||
def err_ovl_deleted_conversion_in_cast : Error<
|
||||
"%select{|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2 uses deleted function">;
|
||||
"functional-style cast|}0 from %1 to %2 uses deleted function">;
|
||||
def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
|
||||
def err_ref_init_ambiguous : Error<
|
||||
"reference initialization of type %0 with initializer of type %1 is ambiguous">;
|
||||
|
@ -6843,34 +6843,34 @@ def err_bad_cstyle_cast_overload : Error<
|
|||
|
||||
|
||||
def err_bad_cxx_cast_generic : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2 is not allowed">;
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|"
|
||||
"C-style cast|functional-style cast|addrspace_cast}0 from %1 to %2 is not allowed">;
|
||||
def err_bad_cxx_cast_unrelated_class : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2, which are not related by "
|
||||
"functional-style cast|}0 from %1 to %2, which are not related by "
|
||||
"inheritance, is not allowed">;
|
||||
def note_type_incomplete : Note<"%0 is incomplete">;
|
||||
def err_bad_cxx_cast_rvalue : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from rvalue to reference type %2">;
|
||||
"functional-style cast|addrspace_cast}0 from rvalue to reference type %2">;
|
||||
def err_bad_cxx_cast_bitfield : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from bit-field lvalue to reference type %2">;
|
||||
"functional-style cast|}0 from bit-field lvalue to reference type %2">;
|
||||
def err_bad_cxx_cast_qualifiers_away : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2 casts away qualifiers">;
|
||||
"functional-style cast|}0 from %1 to %2 casts away qualifiers">;
|
||||
def err_bad_cxx_cast_addr_space_mismatch : Error<
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2 converts between mismatching address"
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|"
|
||||
"C-style cast|functional-style cast|addrspace_cast}0 from %1 to %2 converts between mismatching address"
|
||||
" spaces">;
|
||||
def ext_bad_cxx_cast_qualifiers_away_incoherent : ExtWarn<
|
||||
"ISO C++ does not allow "
|
||||
"%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
|
||||
"functional-style cast}0 from %1 to %2 because it casts away qualifiers, "
|
||||
"functional-style cast|}0 from %1 to %2 because it casts away qualifiers, "
|
||||
"even though the source and destination types are unrelated">,
|
||||
SFINAEFailure, InGroup<DiagGroup<"cast-qual-unrelated">>;
|
||||
def err_bad_const_cast_dest : Error<
|
||||
"%select{const_cast||||C-style cast|functional-style cast}0 to %2, "
|
||||
"%select{const_cast||||C-style cast|functional-style cast|}0 to %2, "
|
||||
"which is not a reference, pointer-to-object, or pointer-to-data-member">;
|
||||
def ext_cast_fn_obj : Extension<
|
||||
"cast between pointer-to-function and pointer-to-object is an extension">;
|
||||
|
@ -6883,13 +6883,13 @@ def warn_cxx98_compat_cast_fn_obj : Warning<
|
|||
def err_bad_reinterpret_cast_small_int : Error<
|
||||
"cast from pointer to smaller type %2 loses information">;
|
||||
def err_bad_cxx_cast_vector_to_scalar_different_size : Error<
|
||||
"%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
|
||||
"%select{||reinterpret_cast||C-style cast||}0 from vector %1 "
|
||||
"to scalar %2 of different size">;
|
||||
def err_bad_cxx_cast_scalar_to_vector_different_size : Error<
|
||||
"%select{||reinterpret_cast||C-style cast|}0 from scalar %1 "
|
||||
"%select{||reinterpret_cast||C-style cast||}0 from scalar %1 "
|
||||
"to vector %2 of different size">;
|
||||
def err_bad_cxx_cast_vector_to_vector_different_size : Error<
|
||||
"%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
|
||||
"%select{||reinterpret_cast||C-style cast||}0 from vector %1 "
|
||||
"to vector %2 of different size">;
|
||||
def warn_bad_cxx_cast_nested_pointer_addr_space : Warning<
|
||||
"%select{reinterpret_cast|C-style cast}0 from %1 to %2 "
|
||||
|
@ -6906,7 +6906,7 @@ def err_bad_static_cast_pointer_nonpointer : Error<
|
|||
def err_bad_static_cast_member_pointer_nonmp : Error<
|
||||
"cannot cast from type %1 to member pointer type %2">;
|
||||
def err_bad_cxx_cast_member_pointer_size : Error<
|
||||
"cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
|
||||
"cannot %select{||reinterpret_cast||C-style cast||}0 from member pointer "
|
||||
"type %1 to member pointer type %2 of different size">;
|
||||
def err_bad_reinterpret_cast_reference : Error<
|
||||
"reinterpret_cast of a %0 to %1 needs its address, which is not allowed">;
|
||||
|
|
|
@ -120,6 +120,7 @@ def CXXStaticCastExpr : StmtNode<CXXNamedCastExpr>;
|
|||
def CXXDynamicCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXReinterpretCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXConstCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXAddrspaceCastExpr : StmtNode<CXXNamedCastExpr>;
|
||||
def CXXFunctionalCastExpr : StmtNode<ExplicitCastExpr>;
|
||||
def CXXTypeidExpr : StmtNode<Expr>;
|
||||
def UserDefinedLiteral : StmtNode<CallExpr>;
|
||||
|
|
|
@ -574,12 +574,13 @@ KEYWORD(__builtin_astype , KEYOPENCLC | KEYOPENCLCXX)
|
|||
KEYWORD(vec_step , KEYOPENCLC | KEYALTIVEC | KEYZVECTOR)
|
||||
#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCLC | KEYOPENCLCXX)
|
||||
#include "clang/Basic/OpenCLImageTypes.def"
|
||||
KEYWORD(pipe , KEYOPENCLC | KEYOPENCLCXX)
|
||||
// C++ for OpenCL s2.3.1: addrspace_cast operator
|
||||
KEYWORD(addrspace_cast , KEYOPENCLCXX)
|
||||
|
||||
// OpenMP Type Traits
|
||||
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
|
||||
|
||||
KEYWORD(pipe , KEYOPENCLC | KEYOPENCLCXX)
|
||||
|
||||
// Borland Extensions.
|
||||
KEYWORD(__pascal , KEYALL)
|
||||
|
||||
|
|
|
@ -5710,7 +5710,8 @@ public:
|
|||
void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
|
||||
bool IsDereference, SourceRange Range);
|
||||
|
||||
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||
/// ActOnCXXNamedCast - Parse
|
||||
/// {dynamic,static,reinterpret,const,addrspace}_cast's.
|
||||
ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind,
|
||||
SourceLocation LAngleBracketLoc,
|
||||
|
|
|
@ -1791,6 +1791,9 @@ namespace serialization {
|
|||
/// A CXXConstCastExpr record.
|
||||
EXPR_CXX_CONST_CAST,
|
||||
|
||||
/// A CXXAddrspaceCastExpr record.
|
||||
EXPR_CXX_ADDRSPACE_CAST,
|
||||
|
||||
/// A CXXFunctionalCastExpr record.
|
||||
EXPR_CXX_FUNCTIONAL_CAST,
|
||||
|
||||
|
|
|
@ -1711,12 +1711,13 @@ bool CastExpr::CastConsistency() const {
|
|||
auto Ty = getType();
|
||||
auto SETy = getSubExpr()->getType();
|
||||
assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
|
||||
if (isRValue()) {
|
||||
if (isRValue() && !Ty->isDependentType() && !SETy->isDependentType()) {
|
||||
Ty = Ty->getPointeeType();
|
||||
SETy = SETy->getPointeeType();
|
||||
}
|
||||
assert(!Ty.isNull() && !SETy.isNull() &&
|
||||
Ty.getAddressSpace() != SETy.getAddressSpace());
|
||||
assert((Ty->isDependentType() || SETy->isDependentType()) ||
|
||||
(!Ty.isNull() && !SETy.isNull() &&
|
||||
Ty.getAddressSpace() != SETy.getAddressSpace()));
|
||||
goto CheckNoBasePath;
|
||||
}
|
||||
// These should not have an inheritance path.
|
||||
|
@ -3205,6 +3206,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
|
|||
case ObjCBridgedCastExprClass:
|
||||
case CXXDynamicCastExprClass:
|
||||
case CXXReinterpretCastExprClass:
|
||||
case CXXAddrspaceCastExprClass:
|
||||
case CXXConstCastExprClass: {
|
||||
const CastExpr *CE = cast<CastExpr>(this);
|
||||
|
||||
|
@ -3496,6 +3498,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
|
|||
case CXXStaticCastExprClass:
|
||||
case CXXReinterpretCastExprClass:
|
||||
case CXXConstCastExprClass:
|
||||
case CXXAddrspaceCastExprClass:
|
||||
case CXXFunctionalCastExprClass:
|
||||
case BuiltinBitCastExprClass: {
|
||||
// While volatile reads are side-effecting in both C and C++, we treat them
|
||||
|
|
|
@ -676,6 +676,7 @@ const char *CXXNamedCastExpr::getCastName() const {
|
|||
case CXXDynamicCastExprClass: return "dynamic_cast";
|
||||
case CXXReinterpretCastExprClass: return "reinterpret_cast";
|
||||
case CXXConstCastExprClass: return "const_cast";
|
||||
case CXXAddrspaceCastExprClass: return "addrspace_cast";
|
||||
default: return "<invalid cast>";
|
||||
}
|
||||
}
|
||||
|
@ -800,6 +801,19 @@ CXXConstCastExpr *CXXConstCastExpr::CreateEmpty(const ASTContext &C) {
|
|||
return new (C) CXXConstCastExpr(EmptyShell());
|
||||
}
|
||||
|
||||
CXXAddrspaceCastExpr *
|
||||
CXXAddrspaceCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
|
||||
CastKind K, Expr *Op, TypeSourceInfo *WrittenTy,
|
||||
SourceLocation L, SourceLocation RParenLoc,
|
||||
SourceRange AngleBrackets) {
|
||||
return new (C) CXXAddrspaceCastExpr(T, VK, K, Op, WrittenTy, L, RParenLoc,
|
||||
AngleBrackets);
|
||||
}
|
||||
|
||||
CXXAddrspaceCastExpr *CXXAddrspaceCastExpr::CreateEmpty(const ASTContext &C) {
|
||||
return new (C) CXXAddrspaceCastExpr(EmptyShell());
|
||||
}
|
||||
|
||||
CXXFunctionalCastExpr *
|
||||
CXXFunctionalCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
|
||||
TypeSourceInfo *Written, CastKind K, Expr *Op,
|
||||
|
|
|
@ -352,6 +352,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
case Expr::CXXDynamicCastExprClass:
|
||||
case Expr::CXXReinterpretCastExprClass:
|
||||
case Expr::CXXConstCastExprClass:
|
||||
case Expr::CXXAddrspaceCastExprClass:
|
||||
case Expr::ObjCBridgedCastExprClass:
|
||||
case Expr::BuiltinBitCastExprClass:
|
||||
// Only in C++ can casts be interesting at all.
|
||||
|
|
|
@ -14203,6 +14203,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
|
|||
case Expr::StmtExprClass:
|
||||
case Expr::CXXMemberCallExprClass:
|
||||
case Expr::CUDAKernelCallExprClass:
|
||||
case Expr::CXXAddrspaceCastExprClass:
|
||||
case Expr::CXXDynamicCastExprClass:
|
||||
case Expr::CXXTypeidExprClass:
|
||||
case Expr::CXXUuidofExprClass:
|
||||
|
|
|
@ -4317,6 +4317,9 @@ recurse:
|
|||
case Expr::CXXConstCastExprClass:
|
||||
mangleCastExpression(E, "cc");
|
||||
break;
|
||||
case Expr::CXXAddrspaceCastExprClass:
|
||||
mangleCastExpression(E, "ac");
|
||||
break;
|
||||
|
||||
case Expr::CXXOperatorCallExprClass: {
|
||||
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
|
||||
|
|
|
@ -1788,6 +1788,10 @@ void StmtPrinter::VisitBuiltinBitCastExpr(BuiltinBitCastExpr *Node) {
|
|||
OS << ")";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
|
||||
VisitCXXNamedCastExpr(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
|
||||
OS << "typeid(";
|
||||
if (Node->isTypeOperand()) {
|
||||
|
|
|
@ -1723,6 +1723,10 @@ void StmtProfiler::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *S) {
|
|||
VisitType(S->getTypeInfoAsWritten()->getType());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitCXXAddrspaceCastExpr(const CXXAddrspaceCastExpr *S) {
|
||||
VisitCXXNamedCastExpr(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) {
|
||||
VisitCallExpr(S);
|
||||
}
|
||||
|
|
|
@ -1395,6 +1395,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
|
|||
case Expr::CXXDynamicCastExprClass:
|
||||
case Expr::CXXReinterpretCastExprClass:
|
||||
case Expr::CXXConstCastExprClass:
|
||||
case Expr::CXXAddrspaceCastExprClass:
|
||||
case Expr::ObjCBridgedCastExprClass:
|
||||
return EmitCastLValue(cast<CastExpr>(E));
|
||||
|
||||
|
|
|
@ -1428,6 +1428,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
|
|||
case tok::kw_dynamic_cast:
|
||||
case tok::kw_reinterpret_cast:
|
||||
case tok::kw_static_cast:
|
||||
case tok::kw_addrspace_cast:
|
||||
if (NotPrimaryExpression)
|
||||
*NotPrimaryExpression = true;
|
||||
Res = ParseCXXCasts();
|
||||
|
|
|
@ -31,10 +31,11 @@ static int SelectDigraphErrorMessage(tok::TokenKind Kind) {
|
|||
// template name
|
||||
case tok::unknown: return 0;
|
||||
// casts
|
||||
case tok::kw_const_cast: return 1;
|
||||
case tok::kw_dynamic_cast: return 2;
|
||||
case tok::kw_reinterpret_cast: return 3;
|
||||
case tok::kw_static_cast: return 4;
|
||||
case tok::kw_addrspace_cast: return 1;
|
||||
case tok::kw_const_cast: return 2;
|
||||
case tok::kw_dynamic_cast: return 3;
|
||||
case tok::kw_reinterpret_cast: return 4;
|
||||
case tok::kw_static_cast: return 5;
|
||||
default:
|
||||
llvm_unreachable("Unknown type for digraph error message.");
|
||||
}
|
||||
|
@ -1512,12 +1513,15 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
|
|||
/// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
|
||||
/// 'const_cast' '<' type-name '>' '(' expression ')'
|
||||
///
|
||||
/// C++ for OpenCL s2.3.1 adds:
|
||||
/// 'addrspace_cast' '<' type-name '>' '(' expression ')'
|
||||
ExprResult Parser::ParseCXXCasts() {
|
||||
tok::TokenKind Kind = Tok.getKind();
|
||||
const char *CastName = nullptr; // For error messages
|
||||
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Unknown C++ cast!");
|
||||
case tok::kw_addrspace_cast: CastName = "addrspace_cast"; break;
|
||||
case tok::kw_const_cast: CastName = "const_cast"; break;
|
||||
case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
|
||||
case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
|
||||
|
|
|
@ -48,7 +48,8 @@ enum CastType {
|
|||
CT_Reinterpret, ///< reinterpret_cast
|
||||
CT_Dynamic, ///< dynamic_cast
|
||||
CT_CStyle, ///< (Type)expr
|
||||
CT_Functional ///< Type(expr)
|
||||
CT_Functional, ///< Type(expr)
|
||||
CT_Addrspace ///< addrspace_cast
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
@ -88,6 +89,7 @@ namespace {
|
|||
void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
|
||||
void CheckCStyleCast();
|
||||
void CheckBuiltinBitCast();
|
||||
void CheckAddrspaceCast();
|
||||
|
||||
void updatePartOfExplicitCastFlags(CastExpr *CE) {
|
||||
// Walk down from the CE to the OrigSrcExpr, and mark all immediate
|
||||
|
@ -225,12 +227,14 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
|
|||
unsigned &msg);
|
||||
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
||||
QualType DestType, bool CStyle,
|
||||
SourceRange OpRange,
|
||||
unsigned &msg,
|
||||
SourceRange OpRange, unsigned &msg,
|
||||
CastKind &Kind);
|
||||
static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
||||
QualType DestType, bool CStyle,
|
||||
unsigned &msg, CastKind &Kind);
|
||||
|
||||
|
||||
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||
/// ActOnCXXNamedCast - Parse
|
||||
/// {dynamic,static,reinterpret,const,addrspace}_cast's.
|
||||
ExprResult
|
||||
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
||||
SourceLocation LAngleBracketLoc, Declarator &D,
|
||||
|
@ -272,6 +276,16 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
switch (Kind) {
|
||||
default: llvm_unreachable("Unknown C++ cast!");
|
||||
|
||||
case tok::kw_addrspace_cast:
|
||||
if (!TypeDependent) {
|
||||
Op.CheckAddrspaceCast();
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
return Op.complete(CXXAddrspaceCastExpr::Create(
|
||||
Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
||||
DestTInfo, OpLoc, Parens.getEnd(), AngleBrackets));
|
||||
|
||||
case tok::kw_const_cast:
|
||||
if (!TypeDependent) {
|
||||
Op.CheckConstCast();
|
||||
|
@ -375,6 +389,7 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
|
|||
case CT_Const:
|
||||
case CT_Reinterpret:
|
||||
case CT_Dynamic:
|
||||
case CT_Addrspace:
|
||||
return false;
|
||||
|
||||
// These do.
|
||||
|
@ -878,6 +893,18 @@ void CastOperation::CheckConstCast() {
|
|||
SrcExpr = ExprError();
|
||||
}
|
||||
|
||||
void CastOperation::CheckAddrspaceCast() {
|
||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
auto TCR =
|
||||
TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg, Kind);
|
||||
if (TCR != TC_Success && msg != 0) {
|
||||
Self.Diag(OpRange.getBegin(), msg)
|
||||
<< CT_Addrspace << SrcExpr.get()->getType() << DestType << OpRange;
|
||||
}
|
||||
if (!isValidCast(TCR))
|
||||
SrcExpr = ExprError();
|
||||
}
|
||||
|
||||
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
|
||||
/// or downcast between respective pointers or references.
|
||||
static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
|
||||
|
@ -2344,7 +2371,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
|||
|
||||
static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
||||
QualType DestType, bool CStyle,
|
||||
unsigned &msg) {
|
||||
unsigned &msg, CastKind &Kind) {
|
||||
if (!Self.getLangOpts().OpenCL)
|
||||
// FIXME: As compiler doesn't have any information about overlapping addr
|
||||
// spaces at the moment we have to be permissive here.
|
||||
|
@ -2353,6 +2380,9 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|||
// non-OpenCL mode too, we fast-path above because no other languages
|
||||
// define overlapping address spaces currently.
|
||||
auto SrcType = SrcExpr.get()->getType();
|
||||
// FIXME: Should this be generalized to references? The reference parameter
|
||||
// however becomes a reference pointee type here and therefore rejected.
|
||||
// Perhaps this is the right behavior though according to C++.
|
||||
auto SrcPtrType = SrcType->getAs<PointerType>();
|
||||
if (!SrcPtrType)
|
||||
return TC_NotApplicable;
|
||||
|
@ -2361,8 +2391,6 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|||
return TC_NotApplicable;
|
||||
auto SrcPointeeType = SrcPtrType->getPointeeType();
|
||||
auto DestPointeeType = DestPtrType->getPointeeType();
|
||||
if (SrcPointeeType.getAddressSpace() == DestPointeeType.getAddressSpace())
|
||||
return TC_NotApplicable;
|
||||
if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) {
|
||||
msg = diag::err_bad_cxx_cast_addr_space_mismatch;
|
||||
return TC_Failed;
|
||||
|
@ -2371,10 +2399,15 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|||
Self.Context.removeAddrSpaceQualType(SrcPointeeType.getCanonicalType());
|
||||
auto DestPointeeTypeWithoutAS =
|
||||
Self.Context.removeAddrSpaceQualType(DestPointeeType.getCanonicalType());
|
||||
return Self.Context.hasSameType(SrcPointeeTypeWithoutAS,
|
||||
DestPointeeTypeWithoutAS)
|
||||
? TC_Success
|
||||
: TC_NotApplicable;
|
||||
if (Self.Context.hasSameType(SrcPointeeTypeWithoutAS,
|
||||
DestPointeeTypeWithoutAS)) {
|
||||
Kind = SrcPointeeType.getAddressSpace() == DestPointeeType.getAddressSpace()
|
||||
? CK_NoOp
|
||||
: CK_AddressSpaceConversion;
|
||||
return TC_Success;
|
||||
} else {
|
||||
return TC_NotApplicable;
|
||||
}
|
||||
}
|
||||
|
||||
void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) {
|
||||
|
@ -2505,22 +2538,21 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
|
|||
Sema::CheckedConversionKind CCK =
|
||||
FunctionalStyle ? Sema::CCK_FunctionalCast : Sema::CCK_CStyleCast;
|
||||
if (tcr == TC_NotApplicable) {
|
||||
tcr = TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ true, msg);
|
||||
tcr = TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ true, msg,
|
||||
Kind);
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
||||
if (isValidCast(tcr))
|
||||
Kind = CK_AddressSpaceConversion;
|
||||
|
||||
if (tcr == TC_NotApplicable) {
|
||||
// ... or if that is not possible, a static_cast, ignoring const, ...
|
||||
// ... or if that is not possible, a static_cast, ignoring const and
|
||||
// addr space, ...
|
||||
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, msg, Kind,
|
||||
BasePath, ListInitialization);
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
||||
if (tcr == TC_NotApplicable) {
|
||||
// ... and finally a reinterpret_cast, ignoring const.
|
||||
// ... and finally a reinterpret_cast, ignoring const and addr space.
|
||||
tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/ true,
|
||||
OpRange, msg, Kind);
|
||||
if (SrcExpr.isInvalid())
|
||||
|
|
|
@ -1289,6 +1289,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
|
|||
|
||||
case Expr::CompoundLiteralExprClass:
|
||||
case Expr::CXXConstCastExprClass:
|
||||
case Expr::CXXAddrspaceCastExprClass:
|
||||
case Expr::CXXReinterpretCastExprClass:
|
||||
case Expr::BuiltinBitCastExprClass:
|
||||
// FIXME: Properly determine whether a variably-modified type can throw.
|
||||
|
|
|
@ -2735,6 +2735,10 @@ public:
|
|||
RAngleLoc, LParenLoc,
|
||||
SubExpr, RParenLoc);
|
||||
|
||||
case Stmt::CXXAddrspaceCastExprClass:
|
||||
return getDerived().RebuildCXXAddrspaceCastExpr(
|
||||
OpLoc, LAngleLoc, TInfo, RAngleLoc, LParenLoc, SubExpr, RParenLoc);
|
||||
|
||||
default:
|
||||
llvm_unreachable("Invalid C++ named cast");
|
||||
}
|
||||
|
@ -2808,6 +2812,16 @@ public:
|
|||
SourceRange(LParenLoc, RParenLoc));
|
||||
}
|
||||
|
||||
ExprResult
|
||||
RebuildCXXAddrspaceCastExpr(SourceLocation OpLoc, SourceLocation LAngleLoc,
|
||||
TypeSourceInfo *TInfo, SourceLocation RAngleLoc,
|
||||
SourceLocation LParenLoc, Expr *SubExpr,
|
||||
SourceLocation RParenLoc) {
|
||||
return getSema().BuildCXXNamedCast(
|
||||
OpLoc, tok::kw_addrspace_cast, TInfo, SubExpr,
|
||||
SourceRange(LAngleLoc, RAngleLoc), SourceRange(LParenLoc, RParenLoc));
|
||||
}
|
||||
|
||||
/// Build a new C++ functional-style cast expression.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new expression.
|
||||
|
@ -11107,6 +11121,12 @@ TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) {
|
|||
return getDerived().TransformCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *E) {
|
||||
return getDerived().TransformCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult
|
||||
TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
|
||||
|
|
|
@ -1721,6 +1721,10 @@ void ASTStmtReader::VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E) {
|
|||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
@ -3593,6 +3597,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
|||
S = CXXConstCastExpr::CreateEmpty(Context);
|
||||
break;
|
||||
|
||||
case EXPR_CXX_ADDRSPACE_CAST:
|
||||
S = CXXAddrspaceCastExpr::CreateEmpty(Context);
|
||||
break;
|
||||
|
||||
case EXPR_CXX_FUNCTIONAL_CAST:
|
||||
S = CXXFunctionalCastExpr::CreateEmpty(Context,
|
||||
/*PathSize*/ Record[ASTStmtReader::NumExprFields]);
|
||||
|
|
|
@ -660,6 +660,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
|
|||
RECORD(EXPR_CXX_DYNAMIC_CAST);
|
||||
RECORD(EXPR_CXX_REINTERPRET_CAST);
|
||||
RECORD(EXPR_CXX_CONST_CAST);
|
||||
RECORD(EXPR_CXX_ADDRSPACE_CAST);
|
||||
RECORD(EXPR_CXX_FUNCTIONAL_CAST);
|
||||
RECORD(EXPR_USER_DEFINED_LITERAL);
|
||||
RECORD(EXPR_CXX_STD_INITIALIZER_LIST);
|
||||
|
|
|
@ -1630,6 +1630,11 @@ void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
|
|||
Code = serialization::EXPR_CXX_CONST_CAST;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *E) {
|
||||
VisitCXXNamedCastExpr(E);
|
||||
Code = serialization::EXPR_CXX_ADDRSPACE_CAST;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) {
|
||||
VisitExplicitCastExpr(E);
|
||||
Record.AddSourceLocation(E->getLParenLoc());
|
||||
|
|
|
@ -1716,7 +1716,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
|||
case Stmt::CXXConstCastExprClass:
|
||||
case Stmt::CXXFunctionalCastExprClass:
|
||||
case Stmt::BuiltinBitCastExprClass:
|
||||
case Stmt::ObjCBridgedCastExprClass: {
|
||||
case Stmt::ObjCBridgedCastExprClass:
|
||||
case Stmt::CXXAddrspaceCastExprClass: {
|
||||
Bldr.takeNodes(Pred);
|
||||
const auto *C = cast<CastExpr>(S);
|
||||
ExplodedNodeSet dstExpr;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
//RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s
|
||||
|
||||
//CHECK-LABEL: define spir_func void @_Z3barPU3AS1i
|
||||
void bar(global int *gl) {
|
||||
//CHECK: addrspacecast i32 addrspace(1)* %{{[0-9]+}} to i32 addrspace(4)*
|
||||
int *gen = addrspace_cast<int *>(gl);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// C++ for OpenCL specific logic.
|
||||
void test(int *ptr) {
|
||||
addrspace_cast<__global int*>(ptr);
|
||||
}
|
||||
|
||||
// RUN: c-index-test -test-load-source all %s -cl-std=clc++ | FileCheck %s
|
||||
// CHECK: cxx.cl:3:3: CXXAddrspaceCastExpr
|
|
@ -0,0 +1,39 @@
|
|||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -fsyntax-only
|
||||
|
||||
void foo(global int *gl, const global int *gl_const, global int &gl_ref) {
|
||||
//FIXME: Diagnostics can be improved to be more specific in some cases.
|
||||
float *gen_fl = addrspace_cast<float *>(gl); //expected-error{{addrspace_cast from '__global int *__private' to '__generic float *' is not allowed}}
|
||||
|
||||
int i = addrspace_cast<int>(gl); //expected-error{{addrspace_cast from '__global int *__private' to 'int' is not allowed}}
|
||||
|
||||
int *gen = addrspace_cast<int *>(*gl); //expected-error{{addrspace_cast from '__global int' to '__generic int *' is not allowed}}
|
||||
|
||||
local int *loc = addrspace_cast<local int *>(gl); //expected-error{{addrspace_cast from '__global int *__private' to '__local int *' converts between mismatching address spaces}}
|
||||
|
||||
int *gen2 = addrspace_cast<int *>(gl_const); //expected-error{{addrspace_cast from 'const __global int *__private' to '__generic int *' is not allowed}}
|
||||
|
||||
//FIXME: Do we expect this behavior? This will get cast successfully as reinterpret_cast.
|
||||
int &gen_ref = addrspace_cast<int &>(gl_ref); //expected-error{{addrspace_cast from '__global int' to '__generic int &' is not allowed}}
|
||||
|
||||
__private int *priv = addrspace_cast<__private int *>(&i);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void test_temp(__global int *par) {
|
||||
T *var1 = addrspace_cast<T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
|
||||
__private T *var2 = addrspace_cast<__private T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
|
||||
T var3 = addrspace_cast<T>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int' is not allowed}}
|
||||
}
|
||||
|
||||
void bar() {
|
||||
__global int* var;
|
||||
test_temp<__private int>(var); //expected-note{{in instantiation of function template specialization 'test_temp<__private int>' requested here}}
|
||||
}
|
||||
// We don't give any errors on non-instantiated template as types are not concrete yet.
|
||||
template <class T>
|
||||
void test_temp1(__global int *par) {
|
||||
T *var1 = addrspace_cast<T *>(par);
|
||||
__private T *var2 = addrspace_cast<__private T *>(par);
|
||||
T var3 = addrspace_cast<T>(par);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -ast-dump | FileCheck %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
//CHECK:`-FunctionDecl {{.*}} bar 'void (__global int *__private)'
|
||||
//CHECK: |-ParmVarDecl {{.*}} used gl '__global int *__private'
|
||||
//CHECK: `-VarDecl {{.*}} gen '__generic int *__private' cinit
|
||||
//CHECK: `-CXXAddrspaceCastExpr {{.*}} '__generic int *' addrspace_cast<__generic int *> <AddressSpaceConversion>
|
||||
//CHECK: `-DeclRefExpr {{.*}} '__global int *__private' lvalue ParmVar {{.*}} 'gl' '__global int *__private'
|
||||
|
||||
void bar(global int *gl) {
|
||||
int *gen = addrspace_cast<int *>(gl);
|
||||
}
|
|
@ -5239,6 +5239,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
|||
return cxstring::createRef("CXXConstCastExpr");
|
||||
case CXCursor_CXXFunctionalCastExpr:
|
||||
return cxstring::createRef("CXXFunctionalCastExpr");
|
||||
case CXCursor_CXXAddrspaceCastExpr:
|
||||
return cxstring::createRef("CXXAddrspaceCastExpr");
|
||||
case CXCursor_CXXTypeidExpr:
|
||||
return cxstring::createRef("CXXTypeidExpr");
|
||||
case CXCursor_CXXBoolLiteralExpr:
|
||||
|
|
|
@ -491,6 +491,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
|||
K = CXCursor_CXXFunctionalCastExpr;
|
||||
break;
|
||||
|
||||
case Stmt::CXXAddrspaceCastExprClass:
|
||||
K = CXCursor_CXXAddrspaceCastExpr;
|
||||
break;
|
||||
|
||||
case Stmt::CXXTypeidExprClass:
|
||||
K = CXCursor_CXXTypeidExpr;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue