diff options
Diffstat (limited to 'clang/lib/Sema/Sema.cpp')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 367 |
1 files changed, 179 insertions, 188 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 55cb3aee6194..5d3de06e9576 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -14,6 +14,7 @@ #include "UsedDeclVisitor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -21,12 +22,14 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/StmtCXX.h" +#include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/CXXFieldCollector.h" #include "clang/Sema/DelayedDiagnostic.h" @@ -54,6 +57,26 @@ SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) { ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); } +DarwinSDKInfo * +Sema::getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc, + StringRef Platform) { + if (CachedDarwinSDKInfo) + return CachedDarwinSDKInfo->get(); + auto SDKInfo = parseDarwinSDKInfo( + PP.getFileManager().getVirtualFileSystem(), + PP.getHeaderSearchInfo().getHeaderSearchOpts().Sysroot); + if (SDKInfo && *SDKInfo) { + CachedDarwinSDKInfo = std::make_unique<DarwinSDKInfo>(std::move(**SDKInfo)); + return CachedDarwinSDKInfo->get(); + } + if (!SDKInfo) + llvm::consumeError(SDKInfo.takeError()); + Diag(Loc, diag::warn_missing_sdksettings_for_availability_checking) + << Platform; + CachedDarwinSDKInfo = std::unique_ptr<DarwinSDKInfo>(); + return nullptr; +} + IdentifierInfo * Sema::InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName, unsigned int Index) { @@ -182,6 +205,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr), CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) { + assert(pp.TUKind == TUKind); TUScope = nullptr; isConstantEvaluatedOverride = false; @@ -298,7 +322,6 @@ void Sema::Initialize() { if (getLangOpts().OpenCL) { getOpenCLOptions().addSupport( Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts()); - getOpenCLOptions().enableSupportedCore(getLangOpts()); addImplicitTypedef("sampler_t", Context.OCLSamplerTy); addImplicitTypedef("event_t", Context.OCLEventTy); if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) { @@ -308,25 +331,12 @@ void Sema::Initialize() { addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy)); addImplicitTypedef("atomic_uint", Context.getAtomicType(Context.UnsignedIntTy)); - 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)); - 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)); - 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 @@ -339,31 +349,50 @@ void Sema::Initialize() { // 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); + + auto AddPointerSizeDependentTypes = [&]() { + auto AtomicSizeT = Context.getAtomicType(Context.getSizeType()); + auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType()); + auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType()); + auto AtomicPtrDiffT = + Context.getAtomicType(Context.getPointerDiffType()); + addImplicitTypedef("atomic_size_t", AtomicSizeT); + addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT); + addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT); + addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT); + }; + + if (Context.getTypeSize(Context.getSizeType()) == 32) { + AddPointerSizeDependentTypes(); } - for (auto &I : Atomic64BitTypes) - setOpenCLExtensionForType(I, - "cl_khr_int64_base_atomics cl_khr_int64_extended_atomics"); - setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64"); + std::vector<QualType> Atomic64BitTypes; + if (getOpenCLOptions().isSupported("cl_khr_int64_base_atomics", + getLangOpts()) && + getOpenCLOptions().isSupported("cl_khr_int64_extended_atomics", + getLangOpts())) { + if (getOpenCLOptions().isSupported("cl_khr_fp64", getLangOpts())) { + auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy); + addImplicitTypedef("atomic_double", AtomicDoubleT); + Atomic64BitTypes.push_back(AtomicDoubleT); + } + auto AtomicLongT = Context.getAtomicType(Context.LongTy); + auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy); + addImplicitTypedef("atomic_long", AtomicLongT); + addImplicitTypedef("atomic_ulong", AtomicULongT); + + + if (Context.getTypeSize(Context.getSizeType()) == 64) { + AddPointerSizeDependentTypes(); + } + } } - setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64"); -#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \ - setOpenCLExtensionForType(Context.Id, Ext); -#include "clang/Basic/OpenCLImageTypes.def" -#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ - addImplicitTypedef(#ExtType, Context.Id##Ty); \ - setOpenCLExtensionForType(Context.Id##Ty, #Ext); +#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ + if (getOpenCLOptions().isSupported(#Ext, getLangOpts())) { \ + addImplicitTypedef(#ExtType, Context.Id##Ty); \ + } #include "clang/Basic/OpenCLExtensionTypes.def" } @@ -385,6 +414,12 @@ void Sema::Initialize() { #include "clang/Basic/PPCTypes.def" } + if (Context.getTargetInfo().hasRISCVVTypes()) { +#define RVV_TYPE(Name, Id, SingletonId) \ + addImplicitTypedef(Name, Context.SingletonId); +#include "clang/Basic/RISCVVTypes.def" + } + if (Context.getTargetInfo().hasBuiltinMSVaList()) { DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list"); if (IdResolver.begin(MSVaList) == IdResolver.end()) @@ -537,6 +572,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) return; + // Don't diagnose the conversion from a 0 literal to a null pointer argument + // in a synthesized call to operator<=>. + if (!CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().Kind == + CodeSynthesisContext::RewritingOperatorAsSpaceship) + return; + // If it is a macro from system header, and if the macro name is not "NULL", // do not warn. SourceLocation MaybeMacroLoc = E->getBeginLoc(); @@ -557,13 +599,14 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, const CXXCastPath *BasePath, CheckedConversionKind CCK) { #ifndef NDEBUG - if (VK == VK_RValue && !E->isRValue()) { + if (VK == VK_PRValue && !E->isPRValue()) { switch (Kind) { default: - llvm_unreachable(("can't implicitly cast lvalue to rvalue with this cast " - "kind: " + - std::string(CastExpr::getCastKindName(Kind))) - .c_str()); + llvm_unreachable( + ("can't implicitly cast glvalue to prvalue with this cast " + "kind: " + + std::string(CastExpr::getCastKindName(Kind))) + .c_str()); case CK_Dependent: case CK_LValueToRValue: case CK_ArrayToPointerDecay: @@ -573,8 +616,8 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, break; } } - assert((VK == VK_RValue || Kind == CK_Dependent || !E->isRValue()) && - "can't cast rvalue to lvalue"); + assert((VK == VK_PRValue || Kind == CK_Dependent || !E->isPRValue()) && + "can't cast prvalue to glvalue"); #endif diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getBeginLoc()); @@ -586,16 +629,36 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, if (ExprTy == TypeTy) return E; - // C++1z [conv.array]: The temporary materialization conversion is applied. - // We also use this to fuel C++ DR1213, which applies to C++11 onwards. - if (Kind == CK_ArrayToPointerDecay && getLangOpts().CPlusPlus && - E->getValueKind() == VK_RValue) { - // The temporary is an lvalue in C++98 and an xvalue otherwise. - ExprResult Materialized = CreateMaterializeTemporaryExpr( - E->getType(), E, !getLangOpts().CPlusPlus11); - if (Materialized.isInvalid()) - return ExprError(); - E = Materialized.get(); + if (Kind == CK_ArrayToPointerDecay) { + // C++1z [conv.array]: The temporary materialization conversion is applied. + // We also use this to fuel C++ DR1213, which applies to C++11 onwards. + if (getLangOpts().CPlusPlus && E->isPRValue()) { + // The temporary is an lvalue in C++98 and an xvalue otherwise. + ExprResult Materialized = CreateMaterializeTemporaryExpr( + E->getType(), E, !getLangOpts().CPlusPlus11); + if (Materialized.isInvalid()) + return ExprError(); + E = Materialized.get(); + } + // C17 6.7.1p6 footnote 124: The implementation can treat any register + // declaration simply as an auto declaration. However, whether or not + // addressable storage is actually used, the address of any part of an + // object declared with storage-class specifier register cannot be + // computed, either explicitly(by use of the unary & operator as discussed + // in 6.5.3.2) or implicitly(by converting an array name to a pointer as + // discussed in 6.3.2.1).Thus, the only operator that can be applied to an + // array declared with storage-class specifier register is sizeof. + if (VK == VK_PRValue && !getLangOpts().CPlusPlus && !E->isPRValue()) { + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) { + if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + if (VD->getStorageClass() == SC_Register) { + Diag(E->getExprLoc(), diag::err_typecheck_address_of) + << /*register variable*/ 3 << E->getSourceRange(); + return ExprError(); + } + } + } + } } if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { @@ -792,8 +855,21 @@ static void checkUndefinedButUsed(Sema &S) { // FIXME: We can promote this to an error. The function or variable can't // be defined anywhere else, so the program must necessarily violate the // one definition rule. - S.Diag(VD->getLocation(), diag::warn_undefined_internal) - << isa<VarDecl>(VD) << VD; + bool IsImplicitBase = false; + if (const auto *BaseD = dyn_cast<FunctionDecl>(VD)) { + auto *DVAttr = BaseD->getAttr<OMPDeclareVariantAttr>(); + if (DVAttr && !DVAttr->getTraitInfo().isExtensionActive( + llvm::omp::TraitProperty:: + implementation_extension_disable_implicit_base)) { + const auto *Func = cast<FunctionDecl>( + cast<DeclRefExpr>(DVAttr->getVariantFuncRef())->getDecl()); + IsImplicitBase = BaseD->isImplicit() && + Func->getIdentifier()->isMangledOpenMPVariantName(); + } + } + if (!S.getLangOpts().OpenMP || !IsImplicitBase) + S.Diag(VD->getLocation(), diag::warn_undefined_internal) + << isa<VarDecl>(VD) << VD; } else if (auto *FD = dyn_cast<FunctionDecl>(VD)) { (void)FD; assert(FD->getMostRecentDecl()->isInlined() && @@ -1548,6 +1624,8 @@ public: DeferredDiagnosticsEmitter(Sema &S) : Inherited(S), ShouldEmitRootNode(false), InOMPDeviceContext(0) {} + bool shouldVisitDiscardedStmt() const { return false; } + void VisitOMPTargetDirective(OMPTargetDirective *Node) { ++InOMPDeviceContext; Inherited::VisitOMPTargetDirective(Node); @@ -1733,11 +1811,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { } } -Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder +Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) { + FD = FD ? FD : getCurFunctionDecl(); if (LangOpts.OpenMP) - return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) - : diagIfOpenMPHostCode(Loc, DiagID); + return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) + : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) : CUDADiagIfHostCode(Loc, DiagID); @@ -1746,7 +1825,7 @@ Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, return SYCLDiagIfDeviceCode(Loc, DiagID); return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID, - getCurFunctionDecl(), *this); + FD, *this); } Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, @@ -1754,7 +1833,7 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, bool IsError = Diags.getDiagnosticIDs()->isDefaultMappingAsError(DiagID); bool ShouldDefer = getLangOpts().CUDA && LangOpts.GPUDeferDiag && DiagnosticIDs::isDeferrable(DiagID) && - (DeferHint || !IsError); + (DeferHint || DeferDiags || !IsError); auto SetIsLastErrorImmediate = [&](bool Flag) { if (IsError) IsLastErrorImmediate = Flag; @@ -1765,15 +1844,14 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, DiagID, getCurFunctionDecl(), *this); } - SemaDiagnosticBuilder DB = - getLangOpts().CUDAIsDevice - ? CUDADiagIfDeviceCode(Loc, DiagID) - : CUDADiagIfHostCode(Loc, DiagID); + SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice + ? CUDADiagIfDeviceCode(Loc, DiagID) + : CUDADiagIfHostCode(Loc, DiagID); SetIsLastErrorImmediate(DB.isImmediate()); return DB; } -void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { +void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) { if (isUnevaluatedContext()) return; @@ -1791,13 +1869,17 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { return; } + // Try to associate errors with the lexical context, if that is a function, or + // the value declaration otherwise. + FunctionDecl *FD = + isa<FunctionDecl>(C) ? cast<FunctionDecl>(C) : dyn_cast<FunctionDecl>(D); auto CheckType = [&](QualType Ty) { if (Ty->isDependentType()) return; if (Ty->isExtIntType()) { if (!Context.getTargetInfo().hasExtIntType()) { - targetDiag(Loc, diag::err_device_unsupported_type) + targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << false /*show bit size*/ << 0 /*bitsize*/ << Ty << Context.getTargetInfo().getTriple().str(); } @@ -1810,11 +1892,12 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { !Context.getTargetInfo().hasFloat128Type()) || (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 && !Context.getTargetInfo().hasInt128Type())) { - targetDiag(Loc, diag::err_device_unsupported_type) + if (targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << true /*show bit size*/ << static_cast<unsigned>(Context.getTypeSize(Ty)) << Ty - << Context.getTargetInfo().getTriple().str(); - targetDiag(D->getLocation(), diag::note_defined_here) << D; + << Context.getTargetInfo().getTriple().str()) + D->setInvalidDecl(); + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } }; @@ -1826,6 +1909,8 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { CheckType(ParamTy); CheckType(FPTy->getReturnType()); } + if (const auto *FNPTy = dyn_cast<FunctionNoProtoType>(Ty)) + CheckType(FNPTy->getReturnType()); } /// Looks through the macro-expansion chain for the given @@ -1913,6 +1998,9 @@ void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) { // Check that the type of the VarDecl has an accessible copy constructor and // resolve its destructor's exception specification. +// This also performs initialization of block variables when they are moved +// to the heap. It uses the same rules as applicable for implicit moves +// according to the C++ standard in effect ([class.copy.elision]p3). static void checkEscapingByref(VarDecl *VD, Sema &S) { QualType T = VD->getType(); EnterExpressionEvaluationContext scope( @@ -1920,9 +2008,18 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) { SourceLocation Loc = VD->getLocation(); Expr *VarRef = new (S.Context) DeclRefExpr(S.Context, VD, false, T, VK_LValue, Loc); - ExprResult Result = S.PerformMoveOrCopyInitialization( - InitializedEntity::InitializeBlock(Loc, T, false), VD, VD->getType(), - VarRef, /*AllowNRVO=*/true); + ExprResult Result; + auto IE = InitializedEntity::InitializeBlock(Loc, T, false); + if (S.getLangOpts().CPlusPlus2b) { + auto *E = ImplicitCastExpr::Create(S.Context, T, CK_NoOp, VarRef, nullptr, + VK_XValue, FPOptionsOverride()); + Result = S.PerformCopyInitialization(IE, SourceLocation(), E); + } else { + Result = S.PerformMoveOrCopyInitialization( + IE, Sema::NamedReturnInfo{VD, Sema::NamedReturnInfo::MoveEligible}, + VarRef); + } + if (!Result.isInvalid()) { Result = S.MaybeCreateExprWithCleanups(Result); Expr *Init = Result.getAs<Expr>(); @@ -2047,6 +2144,11 @@ void Sema::setFunctionHasIndirectGoto() { FunctionScopes.back()->setHasIndirectGoto(); } +void Sema::setFunctionHasMustTail() { + if (!FunctionScopes.empty()) + FunctionScopes.back()->setHasMustTail(); +} + BlockScopeInfo *Sema::getCurBlock() { if (FunctionScopes.empty()) return nullptr; @@ -2287,13 +2389,11 @@ bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, /// ill-formed expression. static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, const SourceLocation FinalNoteLoc) { - int ShownOverloads = 0; - int SuppressedOverloads = 0; + unsigned ShownOverloads = 0; + unsigned SuppressedOverloads = 0; for (UnresolvedSetImpl::iterator It = Overloads.begin(), DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { - // FIXME: Magic number for max shown overloads stolen from - // OverloadCandidateSet::NoteCandidates. - if (ShownOverloads >= 4 && S.Diags.getShowOverloads() == Ovl_Best) { + if (ShownOverloads >= S.Diags.getNumOverloadCandidatesToShow()) { ++SuppressedOverloads; continue; } @@ -2309,6 +2409,8 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, ++ShownOverloads; } + S.Diags.overloadCandidatesShown(ShownOverloads); + if (SuppressedOverloads) S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) << SuppressedOverloads; @@ -2433,114 +2535,3 @@ 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); -} - -std::string Sema::getOpenCLExtensionsFromDeclExtMap(FunctionDecl *FD) { - if (!OpenCLDeclExtMap.empty()) - return getOpenCLExtensionsFromExtMap(FD, OpenCLDeclExtMap); - - return ""; -} - -std::string Sema::getOpenCLExtensionsFromTypeExtMap(FunctionType *FT) { - if (!OpenCLTypeExtMap.empty()) - return getOpenCLExtensionsFromExtMap(FT, OpenCLTypeExtMap); - - return ""; -} - -template <typename T, typename MapT> -std::string Sema::getOpenCLExtensionsFromExtMap(T *FDT, MapT &Map) { - auto Loc = Map.find(FDT); - return llvm::join(Loc->second, " "); -} - -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(); - - // Check extensions for vector types. - // e.g. double4 is not allowed when cl_khr_fp64 is absent. - if (QT->isExtVectorType()) { - auto TypePtr = QT->castAs<ExtVectorType>()->getElementType().getTypePtr(); - return checkOpenCLDisabledTypeOrDecl(TypePtr, Loc, QT, OpenCLTypeExtMap); - } - - 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 NamedDecl &D, const Expr &E) { - IdentifierInfo *FnName = D.getIdentifier(); - return checkOpenCLDisabledTypeOrDecl(&D, E.getBeginLoc(), FnName, - OpenCLDeclExtMap, 1, D.getSourceRange()); -} |