summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/OperationKinds.def3
-rw-r--r--clang/include/clang/Sema/Initialization.h5
-rw-r--r--clang/include/clang/Sema/Overload.h1
-rw-r--r--clang/lib/AST/ExprConstant.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp1
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp1
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp5
-rw-r--r--clang/lib/Sema/SemaExpr.cpp12
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaInit.cpp41
-rw-r--r--clang/lib/Sema/SemaOverload.cpp6
-rw-r--r--clang/test/CodeGenOpenCL/null_queue.cl18
-rw-r--r--clang/test/SemaOpenCL/null_queue.cl12
-rw-r--r--clang/test/SemaOpenCL/queue_t_overload.cl12
14 files changed, 124 insertions, 1 deletions
diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def
index 03a61e94e29..2d48a7df47b 100644
--- a/clang/include/clang/AST/OperationKinds.def
+++ b/clang/include/clang/AST/OperationKinds.def
@@ -321,6 +321,9 @@ CAST_OPERATION(BuiltinFnToFnPtr)
// Convert a zero value for OpenCL event_t initialization.
CAST_OPERATION(ZeroToOCLEvent)
+// Convert a zero value for OpenCL queue_t initialization.
+CAST_OPERATION(ZeroToOCLQueue)
+
// Convert a pointer to a different address space.
CAST_OPERATION(AddressSpaceConversion)
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index c2795fcaf3a..a7b8cce3269 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -751,6 +751,8 @@ public:
SK_StdInitializerListConstructorCall,
/// \brief Initialize an OpenCL sampler from an integer.
SK_OCLSamplerInit,
+ /// \brief Initialize queue_t from 0.
+ SK_OCLZeroQueue,
/// \brief Passing zero to a function where OpenCL event_t is expected.
SK_OCLZeroEvent
};
@@ -1148,6 +1150,9 @@ public:
/// constant.
void AddOCLZeroEventStep(QualType T);
+ /// \brief Add a step to initialize an OpenCL queue_t from 0.
+ void AddOCLZeroQueueStep(QualType T);
+
/// \brief Add steps to unwrap a initializer list for a reference around a
/// single element and rewrap it at the end.
void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic);
diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index 7c6699aca01..9771044a075 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -83,6 +83,7 @@ namespace clang {
ICK_TransparentUnionConversion, ///< Transparent Union Conversions
ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion
ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10)
+ ICK_Zero_Queue_Conversion, ///< Zero constant to queue
ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++
ICK_Incompatible_Pointer_Conversion, ///< C-only conversion between pointers
/// with incompatible types
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 0abdaa879ec..c7310a8feb5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8340,6 +8340,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_IntegralComplexToFloatingComplex:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
@@ -8837,6 +8838,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_NonAtomicToAtomic:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 35148bea001..009244784e5 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -751,6 +751,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
llvm_unreachable("cast kind invalid for aggregate types");
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 60bbc5cfac1..59bc9cdbc05 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -480,6 +480,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_CopyAndAutoreleaseBlockObject:
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
+ case CK_ZeroToOCLQueue:
case CK_AddressSpaceConversion:
case CK_IntToOCLSampler:
llvm_unreachable("invalid cast kind for complex value");
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index e9bdbda34aa..1b85c45cd4b 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1593,6 +1593,11 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
return llvm::Constant::getNullValue(ConvertType(DestTy));
}
+ case CK_ZeroToOCLQueue: {
+ assert(DestTy->isQueueT() && "CK_ZeroToOCLQueue cast on non queue_t type");
+ return llvm::Constant::getNullValue(ConvertType(DestTy));
+ }
+
case CK_IntToOCLSampler:
return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index b8883456911..3c554c9a524 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -9635,6 +9635,18 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
return ResultTy;
}
+ if (getLangOpts().OpenCLVersion >= 200) {
+ if (LHSIsNull && RHSType->isQueueT()) {
+ LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+
+ if (LHSType->isQueueT() && RHSIsNull) {
+ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
+ return ResultTy;
+ }
+ }
+
return InvalidOperands(Loc, LHS, RHS);
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 74beeac7244..6967a4babd6 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3878,6 +3878,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
From->getValueKind()).get();
break;
+ case ICK_Zero_Queue_Conversion:
+ From = ImpCastExprToType(From, ToType,
+ CK_ZeroToOCLQueue,
+ From->getValueKind()).get();
+ break;
+
case ICK_Lvalue_To_Rvalue:
case ICK_Array_To_Pointer:
case ICK_Function_To_Pointer:
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index ce012896f5b..895ccb54844 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -3077,6 +3077,7 @@ void InitializationSequence::Step::Destroy() {
case SK_StdInitializerListConstructorCall:
case SK_OCLSamplerInit:
case SK_OCLZeroEvent:
+ case SK_OCLZeroQueue:
break;
case SK_ConversionSequence:
@@ -3365,6 +3366,13 @@ void InitializationSequence::AddOCLZeroEventStep(QualType T) {
Steps.push_back(S);
}
+void InitializationSequence::AddOCLZeroQueueStep(QualType T) {
+ Step S;
+ S.Kind = SK_OCLZeroQueue;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
void InitializationSequence::RewrapReferenceInitList(QualType T,
InitListExpr *Syntactic) {
assert(Syntactic->getNumInits() == 1 &&
@@ -5030,6 +5038,20 @@ static bool TryOCLZeroEventInitialization(Sema &S,
return true;
}
+static bool TryOCLZeroQueueInitialization(Sema &S,
+ InitializationSequence &Sequence,
+ QualType DestType,
+ Expr *Initializer) {
+ if (!S.getLangOpts().OpenCL || S.getLangOpts().OpenCLVersion < 200 ||
+ !DestType->isQueueT() ||
+ !Initializer->isIntegerConstantExpr(S.getASTContext()) ||
+ (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0))
+ return false;
+
+ Sequence.AddOCLZeroQueueStep(DestType);
+ return true;
+}
+
InitializationSequence::InitializationSequence(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -5292,6 +5314,9 @@ void InitializationSequence::InitializeFrom(Sema &S,
if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer))
return;
+ if (TryOCLZeroQueueInitialization(S, *this, DestType, Initializer))
+ return;
+
// Handle initialization in C
AddCAssignmentStep(DestType);
MaybeProduceObjCObject(S, *this, Entity);
@@ -6529,7 +6554,8 @@ InitializationSequence::Perform(Sema &S,
case SK_ProduceObjCObject:
case SK_StdInitializerList:
case SK_OCLSamplerInit:
- case SK_OCLZeroEvent: {
+ case SK_OCLZeroEvent:
+ case SK_OCLZeroQueue: {
assert(Args.size() == 1);
CurInit = Args[0];
if (!CurInit.get()) return ExprError();
@@ -7213,6 +7239,15 @@ InitializationSequence::Perform(Sema &S,
CurInit.get()->getValueKind());
break;
}
+ case SK_OCLZeroQueue: {
+ assert(Step->Type->isQueueT() &&
+ "Event initialization on non queue type.");
+
+ CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,
+ CK_ZeroToOCLQueue,
+ CurInit.get()->getValueKind());
+ break;
+ }
}
}
@@ -8041,6 +8076,10 @@ void InitializationSequence::dump(raw_ostream &OS) const {
case SK_OCLZeroEvent:
OS << "OpenCL event_t from zero";
break;
+
+ case SK_OCLZeroQueue:
+ OS << "OpenCL queue_t from zero";
+ break;
}
OS << " [" << S->Type.getAsString() << ']';
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d49142b8d85..c8a45013e9e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -1785,6 +1785,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
From->EvaluateKnownConstInt(S.getASTContext()) == 0) {
SCS.Second = ICK_Zero_Event_Conversion;
FromType = ToType;
+ } else if (ToType->isQueueT() &&
+ From->isIntegerConstantExpr(S.getASTContext()) &&
+ (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) {
+ SCS.Second = ICK_Zero_Queue_Conversion;
+ FromType = ToType;
} else {
// No second conversion required.
SCS.Second = ICK_Identity;
@@ -5162,6 +5167,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
case ICK_Function_Conversion:
case ICK_Integral_Promotion:
case ICK_Integral_Conversion: // Narrowing conversions are checked elsewhere.
+ case ICK_Zero_Queue_Conversion:
return true;
case ICK_Boolean_Conversion:
diff --git a/clang/test/CodeGenOpenCL/null_queue.cl b/clang/test/CodeGenOpenCL/null_queue.cl
new file mode 100644
index 00000000000..cdcd7eef2ed
--- /dev/null
+++ b/clang/test/CodeGenOpenCL/null_queue.cl
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -O0 -cl-std=CL2.0 -emit-llvm %s -o - | FileCheck %s
+extern queue_t get_default_queue();
+
+bool compare() {
+ return 0 == get_default_queue() &&
+ get_default_queue() == 0;
+ // CHECK: icmp eq %opencl.queue_t* null, %{{.*}}
+ // CHECK: icmp eq %opencl.queue_t* %{{.*}}, null
+}
+
+void func(queue_t q);
+
+void init() {
+ queue_t q = 0;
+ func(0);
+ // CHECK: store %opencl.queue_t* null, %opencl.queue_t** %q
+ // CHECK: call void @func(%opencl.queue_t* null)
+}
diff --git a/clang/test/SemaOpenCL/null_queue.cl b/clang/test/SemaOpenCL/null_queue.cl
new file mode 100644
index 00000000000..518f7138de6
--- /dev/null
+++ b/clang/test/SemaOpenCL/null_queue.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
+extern queue_t get_default_queue();
+
+bool compare() {
+ return 1 == get_default_queue() && // expected-error{{invalid operands to binary expression ('int' and 'queue_t')}}
+ get_default_queue() == 1; // expected-error{{invalid operands to binary expression ('queue_t' and 'int')}}
+}
+
+void init() {
+ queue_t q1 = 1; // expected-error{{initializing 'queue_t' with an expression of incompatible type 'int'}}
+ queue_t q = 0;
+}
diff --git a/clang/test/SemaOpenCL/queue_t_overload.cl b/clang/test/SemaOpenCL/queue_t_overload.cl
new file mode 100644
index 00000000000..0048895ac80
--- /dev/null
+++ b/clang/test/SemaOpenCL/queue_t_overload.cl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only
+
+void __attribute__((overloadable)) foo(queue_t, __local char *); // expected-note {{candidate function not viable: no known conversion from 'int' to 'queue_t' for 1st argument}} // expected-note {{candidate function}}
+void __attribute__((overloadable)) foo(queue_t, __local float *); // expected-note {{candidate function not viable: no known conversion from 'int' to 'queue_t' for 1st argument}} // expected-note {{candidate function}}
+
+void kernel ker(__local char *src1, __local float *src2, __global int *src3) {
+ queue_t q;
+ foo(q, src1);
+ foo(0, src2);
+ foo(q, src3); // expected-error {{call to 'foo' is ambiguous}}
+ foo(1, src3); // expected-error {{no matching function for call to 'foo'}}
+}
OpenPOWER on IntegriCloud