Anastasia updated this revision to Diff 262479.
Anastasia added a subscriber: jeroen.dobbelaere.
Anastasia added a comment.
Herald added subscribers: martong, arphaman.
Sorry for long latency. I have rebased the patch to the current master and
addressed the comments from @mantognini too.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D60193/new/
https://reviews.llvm.org/D60193
Files:
clang/include/clang-c/Index.h
clang/include/clang/AST/ExprCXX.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/StmtNodes.td
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprCXX.cpp
clang/lib/AST/ExprClassification.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Parse/ParseExprCXX.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/CodeGenOpenCLCXX/addrspace_cast.cl
clang/test/Index/cxx.cl
clang/test/SemaOpenCLCXX/addrspace_cast.cl
clang/test/SemaOpenCLCXX/addrspace_cast_ast_dump.cl
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/CXCursor.cpp
Index: clang/tools/libclang/CXCursor.cpp
===================================================================
--- clang/tools/libclang/CXCursor.cpp
+++ clang/tools/libclang/CXCursor.cpp
@@ -491,6 +491,10 @@
K = CXCursor_CXXFunctionalCastExpr;
break;
+ case Stmt::CXXAddrspaceCastExprClass:
+ K = CXCursor_CXXAddrspaceCastExpr;
+ break;
+
case Stmt::CXXTypeidExprClass:
K = CXCursor_CXXTypeidExpr;
break;
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -5237,6 +5237,8 @@
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:
Index: clang/test/SemaOpenCLCXX/addrspace_cast_ast_dump.cl
===================================================================
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace_cast_ast_dump.cl
@@ -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);
+}
Index: clang/test/SemaOpenCLCXX/addrspace_cast.cl
===================================================================
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace_cast.cl
@@ -0,0 +1,24 @@
+// 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}}
+}
+
+template <class T>
+void test_temp(__global int *par) {
+ T *var1 = addrspace_cast<T *>(par);
+ __private T *var2 = addrspace_cast<__private T *>(par);
+ T var3 = addrspace_cast<T>(par);
+}
Index: clang/test/Index/cxx.cl
===================================================================
--- /dev/null
+++ clang/test/Index/cxx.cl
@@ -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
Index: clang/test/CodeGenOpenCLCXX/addrspace_cast.cl
===================================================================
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/addrspace_cast.cl
@@ -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);
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1716,7 +1716,8 @@
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;
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1630,6 +1630,11 @@
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());
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -641,6 +641,7 @@
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);
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1721,6 +1721,10 @@
return VisitCXXNamedCastExpr(E);
}
+void ASTStmtReader::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *E) {
+ return VisitCXXNamedCastExpr(E);
+}
+
void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
return VisitCXXNamedCastExpr(E);
}
@@ -3593,6 +3597,10 @@
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]);
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -2725,6 +2725,10 @@
RAngleLoc, LParenLoc,
SubExpr, RParenLoc);
+ case Stmt::CXXAddrspaceCastExprClass:
+ return getDerived().RebuildCXXAddrspaceCastExpr(
+ OpLoc, LAngleLoc, TInfo, RAngleLoc, LParenLoc, SubExpr, RParenLoc);
+
default:
llvm_unreachable("Invalid C++ named cast");
}
@@ -2798,6 +2802,16 @@
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.
@@ -11017,6 +11031,12 @@
return getDerived().TransformCXXNamedCastExpr(E);
}
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *E) {
+ return getDerived().TransformCXXNamedCastExpr(E);
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCXXFunctionalCastExpr(
Index: clang/lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- clang/lib/Sema/SemaExceptionSpec.cpp
+++ clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1289,6 +1289,7 @@
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.
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -48,7 +48,8 @@
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 @@
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
@@ -228,9 +230,12 @@
SourceRange OpRange,
unsigned &msg,
CastKind &Kind);
+static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg);
-
-/// 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 +277,18 @@
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.SrcExpr.get(),
+ DestTInfo,
+ OpLoc, Parens.getEnd(),
+ AngleBrackets));
+
case tok::kw_const_cast:
if (!TypeDependent) {
Op.CheckConstCast();
@@ -375,6 +392,7 @@
case CT_Const:
case CT_Reinterpret:
case CT_Dynamic:
+ case CT_Addrspace:
return false;
// These do.
@@ -878,6 +896,18 @@
SrcExpr = ExprError();
}
+void CastOperation::CheckAddrspaceCast() {
+ unsigned msg = diag::err_bad_cxx_cast_generic;
+ auto TCR =
+ TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg);
+ 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,
@@ -2353,6 +2383,9 @@
// 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;
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -31,10 +31,11 @@
// 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 @@
/// '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;
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1428,6 +1428,7 @@
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();
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1384,6 +1384,7 @@
case Expr::CXXDynamicCastExprClass:
case Expr::CXXReinterpretCastExprClass:
case Expr::CXXConstCastExprClass:
+ case Expr::CXXAddrspaceCastExprClass:
case Expr::ObjCBridgedCastExprClass:
return EmitCastLValue(cast<CastExpr>(E));
Index: clang/lib/AST/StmtProfile.cpp
===================================================================
--- clang/lib/AST/StmtProfile.cpp
+++ clang/lib/AST/StmtProfile.cpp
@@ -1723,6 +1723,10 @@
VisitType(S->getTypeInfoAsWritten()->getType());
}
+void StmtProfiler::VisitCXXAddrspaceCastExpr(const CXXAddrspaceCastExpr *S) {
+ VisitCXXNamedCastExpr(S);
+}
+
void StmtProfiler::VisitUserDefinedLiteral(const UserDefinedLiteral *S) {
VisitCallExpr(S);
}
Index: clang/lib/AST/StmtPrinter.cpp
===================================================================
--- clang/lib/AST/StmtPrinter.cpp
+++ clang/lib/AST/StmtPrinter.cpp
@@ -1788,6 +1788,10 @@
OS << ")";
}
+void StmtPrinter::VisitCXXAddrspaceCastExpr(CXXAddrspaceCastExpr *Node) {
+ VisitCXXNamedCastExpr(Node);
+}
+
void StmtPrinter::VisitCXXTypeidExpr(CXXTypeidExpr *Node) {
OS << "typeid(";
if (Node->isTypeOperand()) {
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -4290,6 +4290,9 @@
case Expr::CXXConstCastExprClass:
mangleCastExpression(E, "cc");
break;
+ case Expr::CXXAddrspaceCastExprClass:
+ mangleCastExpression(E, "ac");
+ break;
case Expr::CXXOperatorCallExprClass: {
const CXXOperatorCallExpr *CE = cast<CXXOperatorCallExpr>(E);
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14202,6 +14202,7 @@
case Expr::StmtExprClass:
case Expr::CXXMemberCallExprClass:
case Expr::CUDAKernelCallExprClass:
+ case Expr::CXXAddrspaceCastExprClass:
case Expr::CXXDynamicCastExprClass:
case Expr::CXXTypeidExprClass:
case Expr::CXXUuidofExprClass:
Index: clang/lib/AST/ExprClassification.cpp
===================================================================
--- clang/lib/AST/ExprClassification.cpp
+++ clang/lib/AST/ExprClassification.cpp
@@ -352,6 +352,7 @@
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.
Index: clang/lib/AST/ExprCXX.cpp
===================================================================
--- clang/lib/AST/ExprCXX.cpp
+++ clang/lib/AST/ExprCXX.cpp
@@ -676,6 +676,7 @@
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 @@
return new (C) CXXConstCastExpr(EmptyShell());
}
+CXXAddrspaceCastExpr *
+CXXAddrspaceCastExpr::Create(const ASTContext &C, QualType T, ExprValueKind VK,
+ Expr *Op, TypeSourceInfo *WrittenTy,
+ SourceLocation L, SourceLocation RParenLoc,
+ SourceRange AngleBrackets) {
+ return new (C)
+ CXXAddrspaceCastExpr(T, VK, 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,
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -1711,12 +1711,13 @@
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 @@
case ObjCBridgedCastExprClass:
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
+ case CXXAddrspaceCastExprClass:
case CXXConstCastExprClass: {
const CastExpr *CE = cast<CastExpr>(this);
@@ -3496,6 +3498,7 @@
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
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -1791,6 +1791,9 @@
/// A CXXConstCastExpr record.
EXPR_CXX_CONST_CAST,
+ /// A CXXAddrspaceCastExpr record.
+ EXPR_CXX_ADDRSPACE_CAST,
+
/// A CXXFunctionalCastExpr record.
EXPR_CXX_FUNCTIONAL_CAST,
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5706,7 +5706,8 @@
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,
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -574,12 +574,13 @@
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)
Index: clang/include/clang/Basic/StmtNodes.td
===================================================================
--- clang/include/clang/Basic/StmtNodes.td
+++ clang/include/clang/Basic/StmtNodes.td
@@ -120,6 +120,7 @@
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>;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4222,13 +4222,13 @@
"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">;
@@ -6828,34 +6828,34 @@
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">;
@@ -6868,13 +6868,13 @@
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 "
@@ -6891,7 +6891,7 @@
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">;
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -814,7 +814,7 @@
"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<
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2332,6 +2332,10 @@
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()));
})
Index: clang/include/clang/AST/ExprCXX.h
===================================================================
--- clang/include/clang/AST/ExprCXX.h
+++ clang/include/clang/AST/ExprCXX.h
@@ -366,7 +366,8 @@
/// 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 @@
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
+ case CXXAddrspaceCastExprClass:
return true;
default:
return false;
@@ -569,6 +571,42 @@
}
};
+/// 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, Expr *op,
+ TypeSourceInfo *writtenTy, SourceLocation l,
+ SourceLocation RParenLoc, SourceRange AngleBrackets)
+ : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK,
+ CK_AddressSpaceConversion, 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, 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]).
///
Index: clang/include/clang-c/Index.h
===================================================================
--- clang/include/clang-c/Index.h
+++ clang/include/clang-c/Index.h
@@ -2052,58 +2052,62 @@
*/
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 @@
* 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 @@
* }
* \endcode
*/
- CXCursor_PackExpansionExpr = 142,
+ CXCursor_PackExpansionExpr = 143,
/** Represents an expression that computes the length of a parameter
* pack.
@@ -2139,7 +2143,7 @@
* };
* \endcode
*/
- CXCursor_SizeOfPackExpr = 143,
+ CXCursor_SizeOfPackExpr = 144,
/* Represents a C++ lambda expression that produces a local function
* object.
@@ -2153,37 +2157,37 @@
* }
* \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,
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits