summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/DeclSpec.cpp2
-rw-r--r--clang/lib/Sema/Sema.cpp155
-rw-r--r--clang/lib/Sema/SemaCast.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp9
-rw-r--r--clang/lib/Sema/SemaExpr.cpp13
-rw-r--r--clang/lib/Sema/SemaOverload.cpp16
-rw-r--r--clang/lib/Sema/SemaType.cpp57
7 files changed, 173 insertions, 82 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index cc644c7093b..a55cdcccee5 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/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/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index fc76a86cbb7..412f944f89c 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/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/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index d1e37c02c15..6222e4cec47 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7878355fc19..c32757565dd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c81d8052830..b8883456911 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/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/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1cf685091ef..1899e41ba96 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/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/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 9a01040ba9c..04668359397 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/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();
OpenPOWER on IntegriCloud