Skip to content

Commit

Permalink
[OpenCL] Added addrspace_cast operator in C++ mode.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Anastasia Stulova committed May 18, 2020
1 parent f997370 commit a6a237f
Show file tree
Hide file tree
Showing 32 changed files with 298 additions and 71 deletions.
50 changes: 27 additions & 23 deletions clang/include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -2127,7 +2131,7 @@ enum CXCursorKind {
* }
* \endcode
*/
CXCursor_PackExpansionExpr = 142,
CXCursor_PackExpansionExpr = 143,

/** Represents an expression that computes the length of a parameter
* pack.
Expand All @@ -2139,7 +2143,7 @@ enum CXCursorKind {
* };
* \endcode
*/
CXCursor_SizeOfPackExpr = 143,
CXCursor_SizeOfPackExpr = 144,

/* Represents a C++ lambda expression that produces a local function
* object.
Expand All @@ -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,

Expand Down
39 changes: 38 additions & 1 deletion clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ class CXXRewrittenBinaryOperator : public Expr {
/// 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
Expand Down Expand Up @@ -412,6 +413,7 @@ class CXXNamedCastExpr : public ExplicitCastExpr {
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
case CXXAddrspaceCastExprClass:
return true;
default:
return false;
Expand Down Expand Up @@ -569,6 +571,41 @@ class CXXConstCastExpr final
}
};

/// 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]).
///
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
})
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
Expand Down
34 changes: 17 additions & 17 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;
Expand Down Expand Up @@ -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">;
Expand All @@ -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 "
Expand All @@ -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">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -5710,7 +5710,8 @@ class Sema final {
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,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
9 changes: 6 additions & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit a6a237f

Please sign in to comment.