diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
| commit | 145449b1e420787bb99721a429341fa6be3adfb6 (patch) | |
| tree | 1d56ae694a6de602e348dd80165cf881a36600ed /clang/lib/Sema/SemaCUDA.cpp | |
| parent | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff) | |
Diffstat (limited to 'clang/lib/Sema/SemaCUDA.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaCUDA.cpp | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index efa38554bc83..8f8144d658d8 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -145,9 +145,11 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D, Sema::CUDAVariableTarget Sema::IdentifyCUDATarget(const VarDecl *Var) { if (Var->hasAttr<HIPManagedAttr>()) return CVT_Unified; - if (Var->isConstexpr() && !hasExplicitAttr<CUDAConstantAttr>(Var)) - return CVT_Both; - if (Var->getType().isConstQualified() && Var->hasAttr<CUDAConstantAttr>() && + // Only constexpr and const variabless with implicit constant attribute + // are emitted on both sides. Such variables are promoted to device side + // only if they have static constant intializers on device side. + if ((Var->isConstexpr() || Var->getType().isConstQualified()) && + Var->hasAttr<CUDAConstantAttr>() && !hasExplicitAttr<CUDAConstantAttr>(Var)) return CVT_Both; if (Var->hasAttr<CUDADeviceAttr>() || Var->hasAttr<CUDAConstantAttr>() || @@ -353,9 +355,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, } if (!ClassDecl->isAbstract()) { - for (const auto &VB : ClassDecl->vbases()) { - Bases.push_back(&VB); - } + llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases())); } for (const auto *B : Bases) { @@ -377,7 +377,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, continue; CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR.getMethod()); - if (!InferredTarget.hasValue()) { + if (!InferredTarget) { InferredTarget = BaseMethodTarget; } else { bool ResolutionError = resolveCalleeCUDATargetConflict( @@ -421,7 +421,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CUDAFunctionTarget FieldMethodTarget = IdentifyCUDATarget(SMOR.getMethod()); - if (!InferredTarget.hasValue()) { + if (!InferredTarget) { InferredTarget = FieldMethodTarget; } else { bool ResolutionError = resolveCalleeCUDATargetConflict( @@ -444,7 +444,7 @@ bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, // If no target was inferred, mark this member as __host__ __device__; // it's the least restrictive option that can be invoked from any target. bool NeedsH = true, NeedsD = true; - if (InferredTarget.hasValue()) { + if (InferredTarget) { if (InferredTarget.getValue() == CFT_Device) NeedsH = false; else if (InferredTarget.getValue() == CFT_Host) @@ -718,9 +718,9 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { !VD->hasAttr<CUDAConstantAttr>() && !VD->hasAttr<CUDASharedAttr>() && (VD->isFileVarDecl() || VD->isStaticDataMember()) && !IsDependentVar(VD) && - (VD->isConstexpr() || (VD->getType().isConstQualified() && - HasAllowedCUDADeviceStaticInitializer( - *this, VD, CICK_DeviceOrConstant)))) { + ((VD->isConstexpr() || VD->getType().isConstQualified()) && + HasAllowedCUDADeviceStaticInitializer(*this, VD, + CICK_DeviceOrConstant))) { VD->addAttr(CUDAConstantAttr::CreateImplicit(getASTContext())); } } @@ -728,8 +728,9 @@ void Sema::MaybeAddCUDAConstantAttr(VarDecl *VD) { Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); + FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { - if (!isa<FunctionDecl>(CurContext)) + if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { case CFT_Global: @@ -743,7 +744,7 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, return SemaDiagnosticBuilder::K_Nop; if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(cast<FunctionDecl>(CurContext)) == + return (getEmissionStatus(CurFunContext) == FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; @@ -751,15 +752,15 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfDeviceCode(SourceLocation Loc, return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, - dyn_cast<FunctionDecl>(CurContext), *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); } Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID) { assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); + FunctionDecl *CurFunContext = getCurFunctionDecl(/*AllowLambda=*/true); SemaDiagnosticBuilder::Kind DiagKind = [&] { - if (!isa<FunctionDecl>(CurContext)) + if (!CurFunContext) return SemaDiagnosticBuilder::K_Nop; switch (CurrentCUDATarget()) { case CFT_Host: @@ -772,7 +773,7 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, return SemaDiagnosticBuilder::K_Nop; if (IsLastErrorImmediate && Diags.getDiagnosticIDs()->isBuiltinNote(DiagID)) return SemaDiagnosticBuilder::K_Immediate; - return (getEmissionStatus(cast<FunctionDecl>(CurContext)) == + return (getEmissionStatus(CurFunContext) == FunctionEmissionStatus::Emitted) ? SemaDiagnosticBuilder::K_ImmediateWithCallStack : SemaDiagnosticBuilder::K_Deferred; @@ -780,8 +781,7 @@ Sema::SemaDiagnosticBuilder Sema::CUDADiagIfHostCode(SourceLocation Loc, return SemaDiagnosticBuilder::K_Nop; } }(); - return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, - dyn_cast<FunctionDecl>(CurContext), *this); + return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, CurFunContext, *this); } bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { @@ -794,7 +794,7 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { // FIXME: Is bailing out early correct here? Should we instead assume that // the caller is a global initializer? - FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); + FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return true; @@ -819,8 +819,13 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { } }(); - if (DiagKind == SemaDiagnosticBuilder::K_Nop) + if (DiagKind == SemaDiagnosticBuilder::K_Nop) { + // For -fgpu-rdc, keep track of external kernels used by host functions. + if (LangOpts.CUDAIsDevice && LangOpts.GPURelocatableDeviceCode && + Callee->hasAttr<CUDAGlobalAttr>() && !Callee->isDefined()) + getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Callee); return true; + } // Avoid emitting this error twice for the same location. Using a hashtable // like this is unfortunate, but because we must continue parsing as normal @@ -860,7 +865,7 @@ void Sema::CUDACheckLambdaCapture(CXXMethodDecl *Callee, // File-scope lambda can only do init captures for global variables, which // results in passing by value for these global variables. - FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); + FunctionDecl *Caller = getCurFunctionDecl(/*AllowLambda=*/true); if (!Caller) return; |
