summaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorYaxun Liu <Yaxun.Liu@amd.com>2016-12-16 19:22:08 +0000
committerYaxun Liu <Yaxun.Liu@amd.com>2016-12-16 19:22:08 +0000
commit30d9d8921a58be7a796ab22bd3ac6eb350ab9629 (patch)
tree9abe2cae1232fb6dfad42540f24cdc185e62e608 /lib/Sema
parentb206e2ea7775db49cd2a0b21f64c792b2b9e1ec7 (diff)
downloadclang-30d9d8921a58be7a796ab22bd3ac6eb350ab9629.tar.gz
[OpenCL] Allow disabling types and declarations associated with extensions
Added a map to associate types and declarations with extensions. Refactored existing diagnostic for disabled types associated with extensions and extended it to declarations for generic situation. Fixed some bugs for types associated with extensions. Allow users to use pragma to declare types and functions for supported extensions, e.g. #pragma OPENCL EXTENSION the_new_extension_name : begin // declare types and functions associated with the extension here #pragma OPENCL EXTENSION the_new_extension_name : end Differential Revision: https://reviews.llvm.org/D21698 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@289979 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/DeclSpec.cpp2
-rw-r--r--lib/Sema/Sema.cpp155
-rw-r--r--lib/Sema/SemaCast.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp9
-rw-r--r--lib/Sema/SemaExpr.cpp13
-rw-r--r--lib/Sema/SemaOverload.cpp16
-rw-r--r--lib/Sema/SemaType.cpp57
7 files changed, 173 insertions, 82 deletions
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index cc644c7093..a55cdcccee 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -558,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc,
// OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
// specifiers are not supported."
if (S.getLangOpts().OpenCL &&
- !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+ !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
switch (SC) {
case SCS_extern:
case SCS_private_extern:
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fc76a86cbb..412f944f89 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -207,14 +207,11 @@ void Sema::Initialize() {
addImplicitTypedef("size_t", Context.getSizeType());
}
- // Initialize predefined OpenCL types and supported optional core features.
+ // Initialize predefined OpenCL types and supported extensions and (optional)
+ // core features.
if (getLangOpts().OpenCL) {
-#define OPENCLEXT(Ext) \
- if (Context.getTargetInfo().getSupportedOpenCLOpts().is_##Ext##_supported_core( \
- getLangOpts().OpenCLVersion)) \
- getOpenCLOptions().Ext = 1;
-#include "clang/Basic/OpenCLExtensions.def"
-
+ getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts());
+ getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion);
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
if (getLangOpts().OpenCLVersion >= 200) {
@@ -225,26 +222,60 @@ void Sema::Initialize() {
addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
addImplicitTypedef("atomic_uint",
Context.getAtomicType(Context.UnsignedIntTy));
- addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy));
- addImplicitTypedef("atomic_ulong",
- Context.getAtomicType(Context.UnsignedLongTy));
+ auto AtomicLongT = Context.getAtomicType(Context.LongTy);
+ addImplicitTypedef("atomic_long", AtomicLongT);
+ auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
+ addImplicitTypedef("atomic_ulong", AtomicULongT);
addImplicitTypedef("atomic_float",
Context.getAtomicType(Context.FloatTy));
- addImplicitTypedef("atomic_double",
- Context.getAtomicType(Context.DoubleTy));
+ auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
+ addImplicitTypedef("atomic_double", AtomicDoubleT);
// OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
// 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
- addImplicitTypedef("atomic_intptr_t",
- Context.getAtomicType(Context.getIntPtrType()));
- addImplicitTypedef("atomic_uintptr_t",
- Context.getAtomicType(Context.getUIntPtrType()));
- addImplicitTypedef("atomic_size_t",
- Context.getAtomicType(Context.getSizeType()));
- addImplicitTypedef("atomic_ptrdiff_t",
- Context.getAtomicType(Context.getPointerDiffType()));
+ auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
+ addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
+ auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
+ addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
+ auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
+ addImplicitTypedef("atomic_size_t", AtomicSizeT);
+ auto AtomicPtrDiffT = Context.getAtomicType(Context.getPointerDiffType());
+ addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
+
+ // OpenCL v2.0 s6.13.11.6:
+ // - The atomic_long and atomic_ulong types are supported if the
+ // cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
+ // extensions are supported.
+ // - The atomic_double type is only supported if double precision
+ // is supported and the cl_khr_int64_base_atomics and
+ // cl_khr_int64_extended_atomics extensions are supported.
+ // - If the device address space is 64-bits, the data types
+ // atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
+ // atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
+ // cl_khr_int64_extended_atomics extensions are supported.
+ std::vector<QualType> Atomic64BitTypes;
+ Atomic64BitTypes.push_back(AtomicLongT);
+ Atomic64BitTypes.push_back(AtomicULongT);
+ Atomic64BitTypes.push_back(AtomicDoubleT);
+ if (Context.getTypeSize(AtomicSizeT) == 64) {
+ Atomic64BitTypes.push_back(AtomicSizeT);
+ Atomic64BitTypes.push_back(AtomicIntPtrT);
+ Atomic64BitTypes.push_back(AtomicUIntPtrT);
+ Atomic64BitTypes.push_back(AtomicPtrDiffT);
+ }
+ for (auto &I : Atomic64BitTypes)
+ setOpenCLExtensionForType(I,
+ "cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
+
+ setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
}
- }
+
+ setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64");
+
+#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
+ setOpenCLExtensionForType(Context.Id, Ext);
+#include "clang/Basic/OpenCLImageTypes.def"
+ };
if (Context.getTargetInfo().hasBuiltinMSVaList()) {
DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
@@ -1542,3 +1573,85 @@ const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> &
Sema::getMismatchingDeleteExpressions() const {
return DeleteExprs;
}
+
+void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
+ if (ExtStr.empty())
+ return;
+ llvm::SmallVector<StringRef, 1> Exts;
+ ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+ auto CanT = T.getCanonicalType().getTypePtr();
+ for (auto &I : Exts)
+ OpenCLTypeExtMap[CanT].insert(I.str());
+}
+
+void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
+ llvm::SmallVector<StringRef, 1> Exts;
+ ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+ if (Exts.empty())
+ return;
+ for (auto &I : Exts)
+ OpenCLDeclExtMap[FD].insert(I.str());
+}
+
+void Sema::setCurrentOpenCLExtensionForType(QualType T) {
+ if (CurrOpenCLExtension.empty())
+ return;
+ setOpenCLExtensionForType(T, CurrOpenCLExtension);
+}
+
+void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
+ if (CurrOpenCLExtension.empty())
+ return;
+ setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
+}
+
+bool Sema::isOpenCLDisabledDecl(Decl *FD) {
+ auto Loc = OpenCLDeclExtMap.find(FD);
+ if (Loc == OpenCLDeclExtMap.end())
+ return false;
+ for (auto &I : Loc->second) {
+ if (!getOpenCLOptions().isEnabled(I))
+ return true;
+ }
+ return false;
+}
+
+template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
+ DiagInfoT DiagInfo, MapT &Map,
+ unsigned Selector,
+ SourceRange SrcRange) {
+ auto Loc = Map.find(D);
+ if (Loc == Map.end())
+ return false;
+ bool Disabled = false;
+ for (auto &I : Loc->second) {
+ if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) {
+ Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
+ << I << SrcRange;
+ Disabled = true;
+ }
+ }
+ return Disabled;
+}
+
+bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
+ // Check extensions for declared types.
+ Decl *Decl = nullptr;
+ if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
+ Decl = TypedefT->getDecl();
+ if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
+ Decl = TagT->getDecl();
+ auto Loc = DS.getTypeSpecTypeLoc();
+ if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
+ return true;
+
+ // Check extensions for builtin types.
+ return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
+ QT, OpenCLTypeExtMap);
+}
+
+bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
+ return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+ OpenCLDeclExtMap, 1, D.getSourceRange());
+}
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index d1e37c02c1..6222e4cec4 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -2529,7 +2529,8 @@ void CastOperation::CheckCStyleCast() {
}
}
- if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
+ if (Self.getLangOpts().OpenCL &&
+ !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
if (DestType->isHalfType()) {
Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
<< DestType << SrcExpr.get()->getSourceRange();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7878355fc1..c32757565d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4838,6 +4838,9 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) {
Dcl && Dcl->getDeclContext()->isFileContext())
Dcl->setTopLevelDeclInObjCContainer();
+ if (getLangOpts().OpenCL)
+ setCurrentOpenCLExtensionForDecl(Dcl);
+
return Dcl;
}
@@ -5939,7 +5942,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NR = NR->getPointeeType();
}
- if (!getOpenCLOptions().cl_khr_fp16) {
+ if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
// half array type (unless the cl_khr_fp16 extension is enabled).
if (Context.getBaseElementType(R)->isHalfType()) {
@@ -6909,7 +6912,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
// OpenCL v1.2 s6.8 - The static qualifier is valid only in program
// scope.
if (getLangOpts().OpenCLVersion == 120 &&
- !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+ !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
NewVD->isStaticLocal()) {
Diag(NewVD->getLocation(), diag::err_static_function_scope);
NewVD->setInvalidDecl();
@@ -7617,7 +7620,7 @@ static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
// OpenCL extension spec v1.2 s9.5:
// This extension adds support for half scalar and vector types as built-in
// types that can be used for arithmetic operations, conversions etc.
- if (!S.getOpenCLOptions().cl_khr_fp16 && PT->isHalfType())
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType())
return InvalidKernelParam;
if (PT->isRecordType())
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c81d805283..b888345691 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -657,7 +657,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
- if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+ if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
T->isHalfType()) {
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
<< 0 << T;
@@ -819,7 +819,7 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
- !(getOpenCLOptions().cl_khr_fp64)) {
+ !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
if (BTy->getKind() == BuiltinType::Half) {
E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
}
@@ -3386,7 +3386,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
- if (getOpenCLOptions().cl_khr_fp16)
+ if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
Ty = Context.HalfTy;
else {
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -3410,7 +3410,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
} else if (getLangOpts().OpenCL &&
- !(getOpenCLOptions().cl_khr_fp64)) {
+ !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
// Impose single-precision float type when cl_khr_fp64 is not enabled.
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
@@ -5289,6 +5289,9 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
Fn->getLocStart()))
return ExprError();
+ if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
+ return ExprError();
+
// CheckEnableIf assumes that the we're passing in a sane number of args for
// FD, but that doesn't always hold true here. This is because, in some
// cases, we'll emit a diag about an ill-formed function call, but then
@@ -10186,7 +10189,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
// OpenCL v1.2 s6.1.1.1 p2:
// The half data type can only be used to declare a pointer to a buffer that
// contains half values
- if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+ if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
LHSType->isHalfType()) {
Diag(Loc, diag::err_opencl_half_load_store) << 1
<< LHSType.getUnqualifiedType();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 1cf685091e..1899e41ba9 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5949,6 +5949,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
Candidate.DeductionFailure.Data = FailedAttr;
return;
}
+
+ if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_ext_disabled;
+ return;
+ }
}
ObjCMethodDecl *
@@ -9798,6 +9804,13 @@ static void DiagnoseFailedEnableIfAttr(Sema &S, OverloadCandidate *Cand) {
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
}
+static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
+ FunctionDecl *Callee = Cand->Function;
+
+ S.Diag(Callee->getLocation(),
+ diag::note_ovl_candidate_disabled_by_extension);
+}
+
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@@ -9875,6 +9888,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_enable_if:
return DiagnoseFailedEnableIfAttr(S, Cand);
+ case ovl_fail_ext_disabled:
+ return DiagnoseOpenCLExtensionDisabled(S, Cand);
+
case ovl_fail_addr_not_available: {
bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
(void)Available;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 9a01040ba9..0466835939 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1401,13 +1401,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
-
- if (S.getLangOpts().OpenCL &&
- !(S.getOpenCLOptions().cl_khr_fp64)) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_fp64";
- declarator.setInvalidType(true);
- }
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type())
@@ -1459,48 +1452,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = S.GetTypeFromParser(DS.getRepAsType());
if (Result.isNull()) {
declarator.setInvalidType(true);
- } else if (S.getLangOpts().OpenCL) {
- if (Result->getAs<AtomicType>()) {
- StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
- bool NoExtTypes =
- llvm::StringSwitch<bool>(TypeName)
- .Cases("atomic_int", "atomic_uint", "atomic_float",
- "atomic_flag", true)
- .Default(false);
- if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_int64_base_atomics";
- declarator.setInvalidType(true);
- }
- if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
- !NoExtTypes) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_int64_extended_atomics";
- declarator.setInvalidType(true);
- }
- if (!S.getOpenCLOptions().cl_khr_fp64 &&
- !TypeName.compare("atomic_double")) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_fp64";
- declarator.setInvalidType(true);
- }
- } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
- (Result->isOCLImage2dArrayMSAADepthROType() ||
- Result->isOCLImage2dArrayMSAADepthWOType() ||
- Result->isOCLImage2dArrayMSAADepthRWType() ||
- Result->isOCLImage2dArrayMSAAROType() ||
- Result->isOCLImage2dArrayMSAARWType() ||
- Result->isOCLImage2dArrayMSAAWOType() ||
- Result->isOCLImage2dMSAADepthROType() ||
- Result->isOCLImage2dMSAADepthRWType() ||
- Result->isOCLImage2dMSAADepthWOType() ||
- Result->isOCLImage2dMSAAROType() ||
- Result->isOCLImage2dMSAARWType() ||
- Result->isOCLImage2dMSAAWOType())) {
- S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
- << Result << "cl_khr_gl_msaa_sharing";
- declarator.setInvalidType(true);
- }
}
// TypeQuals handled by caller.
@@ -1636,6 +1587,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
break;
}
+ if (S.getLangOpts().OpenCL &&
+ S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
+ declarator.setInvalidType(true);
+
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
@@ -4185,7 +4140,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// FIXME: This really should be in BuildFunctionType.
if (T->isHalfType()) {
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().cl_khr_fp16) {
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
@@ -4418,7 +4373,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
- if (!S.getOpenCLOptions().cl_khr_fp16) {
+ if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(Param->getLocation(),
diag::err_opencl_half_param) << ParamTy;
D.setInvalidType();