diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 155 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 57 |
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(); |