Lines Matching +full:compound +full:- +full:device

1 //===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 //===----------------------------------------------------------------------===//
36 if (auto *A = D->getAttr<AttrT>()) in hasExplicitAttr()
37 return !A->isImplicit(); in hasExplicitAttr()
50 ForceHostDeviceDepth--; in PopForceHostDevice()
61 QualType ConfigQTy = ConfigDecl->getType(); in ActOnExecConfigExpr()
105 return CUDAFunctionTarget::Device; in IdentifyTarget()
112 return D->hasAttrs() && llvm::any_of(D->getAttrs(), [&](Attr *Attribute) { in hasAttr()
114 !(IgnoreImplicitAttr && Attribute->isImplicit()); in hasAttr()
124 if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) { in CUDATargetContextRAII()
130 Target = CUDAFunctionTarget::Device; in CUDATargetContextRAII()
135 /// IdentifyTarget - Determine the CUDA compilation target for this function
142 if (D->hasAttr<CUDAInvalidTargetAttr>()) in IdentifyTarget()
145 if (D->hasAttr<CUDAGlobalAttr>()) in IdentifyTarget()
151 return CUDAFunctionTarget::Device; in IdentifyTarget()
154 } else if ((D->isImplicit() || !D->isUserProvided()) && in IdentifyTarget()
164 /// IdentifyTarget - Determine the CUDA compilation target for this variable.
166 if (Var->hasAttr<HIPManagedAttr>()) in IdentifyTarget()
169 // are emitted on both sides. Such variables are promoted to device side in IdentifyTarget()
170 // only if they have static constant intializers on device side. in IdentifyTarget()
171 if ((Var->isConstexpr() || Var->getType().isConstQualified()) && in IdentifyTarget()
172 Var->hasAttr<CUDAConstantAttr>() && in IdentifyTarget()
175 if (Var->hasAttr<CUDADeviceAttr>() || Var->hasAttr<CUDAConstantAttr>() || in IdentifyTarget()
176 Var->hasAttr<CUDASharedAttr>() || in IdentifyTarget()
177 Var->getType()->isCUDADeviceBuiltinSurfaceType() || in IdentifyTarget()
178 Var->getType()->isCUDADeviceBuiltinTextureType()) in IdentifyTarget()
180 // Function-scope static variable without explicit device or constant in IdentifyTarget()
182 // - on both sides in host device functions in IdentifyTarget()
183 // - on device side in device or global functions in IdentifyTarget()
184 if (auto *FD = dyn_cast<FunctionDecl>(Var->getDeclContext())) { in IdentifyTarget()
188 case CUDAFunctionTarget::Device: in IdentifyTarget()
200 // F - from,
201 // T - to
202 // Ph - preference in host mode
203 // Pd - preference in device mode
204 // H - handled in (x)
205 // Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never.
208 // |----+----+-----+-----+-----+
210 // | d | g | -- | -- | (a) |
211 // | d | h | -- | -- | (e) |
214 // | g | g | -- | -- | (a) |
215 // | g | h | -- | -- | (e) |
217 // | h | d | -- | -- | (e) |
222 // | hd | g | SS | -- |(d/a)|
231 // Treat ctor/dtor as host device function in device var initializer to allow in IdentifyPreference()
232 // trivial ctor/dtor without device attr to be used. Non-trivial ctor/dtor in IdentifyPreference()
235 CurCUDATargetCtx.Target == CUDAFunctionTarget::Device && in IdentifyPreference()
252 CallerTarget == CUDAFunctionTarget::Device)) in IdentifyPreference()
264 CalleeTarget == CUDAFunctionTarget::Device)) in IdentifyPreference()
267 // HipStdPar mode is special, in that assessing whether a device side call to in IdentifyPreference()
272 CallerTarget == CUDAFunctionTarget::Device || in IdentifyPreference()
279 // It's OK to call a compilation-mode matching function from an HD one. in IdentifyPreference()
281 CalleeTarget == CUDAFunctionTarget::Device) || in IdentifyPreference()
287 // Calls from HD to non-mode-matching functions (i.e., to host functions in IdentifyPreference()
288 // when compiling in device mode or to device functions when compiling in in IdentifyPreference()
294 // (e) Calling across device/host boundary is not something you should do. in IdentifyPreference()
296 CalleeTarget == CUDAFunctionTarget::Device) || in IdentifyPreference()
297 (CallerTarget == CUDAFunctionTarget::Device && in IdentifyPreference()
309 if (auto *A = D->getAttr<AttrT>()) in hasImplicitAttr()
310 return A->isImplicit(); in hasImplicitAttr()
311 return D->isImplicit(); in hasImplicitAttr()
343 /// When an implicitly-declared special member has to invoke more than one
378 // owning class, or the special member already has explicit device or host in inferTargetForImplicitSpecialMember()
380 bool InClass = MemberDecl->getLexicalParent() == MemberDecl->getParent(); in inferTargetForImplicitSpecialMember()
381 bool HasH = MemberDecl->hasAttr<CUDAHostAttr>(); in inferTargetForImplicitSpecialMember()
382 bool HasD = MemberDecl->hasAttr<CUDADeviceAttr>(); in inferTargetForImplicitSpecialMember()
384 (HasD && !MemberDecl->getAttr<CUDADeviceAttr>()->isImplicit()) || in inferTargetForImplicitSpecialMember()
385 (HasH && !MemberDecl->getAttr<CUDAHostAttr>()->isImplicit()); in inferTargetForImplicitSpecialMember()
399 for (const auto &B : ClassDecl->bases()) { in inferTargetForImplicitSpecialMember()
405 if (!ClassDecl->isAbstract()) { in inferTargetForImplicitSpecialMember()
406 llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases())); in inferTargetForImplicitSpecialMember()
410 const RecordType *BaseType = B->getType()->getAs<RecordType>(); in inferTargetForImplicitSpecialMember()
415 CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); in inferTargetForImplicitSpecialMember()
435 Diag(ClassDecl->getLocation(), in inferTargetForImplicitSpecialMember()
440 MemberDecl->addAttr( in inferTargetForImplicitSpecialMember()
448 for (const auto *F : ClassDecl->fields()) { in inferTargetForImplicitSpecialMember()
449 if (F->isInvalidDecl()) { in inferTargetForImplicitSpecialMember()
454 getASTContext().getBaseElementType(F->getType())->getAs<RecordType>(); in inferTargetForImplicitSpecialMember()
459 CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl()); in inferTargetForImplicitSpecialMember()
462 /* ConstArg */ ConstRHS && !F->isMutable(), in inferTargetForImplicitSpecialMember()
479 Diag(ClassDecl->getLocation(), in inferTargetForImplicitSpecialMember()
484 MemberDecl->addAttr( in inferTargetForImplicitSpecialMember()
496 if (*InferredTarget == CUDAFunctionTarget::Device) in inferTargetForImplicitSpecialMember()
505 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); in inferTargetForImplicitSpecialMember()
507 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); in inferTargetForImplicitSpecialMember()
513 if (!CD->isDefined() && CD->isTemplateInstantiation()) in isEmptyConstructor()
514 SemaRef.InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); in isEmptyConstructor()
519 if (CD->isTrivial()) in isEmptyConstructor()
525 // and the function body is an empty compound statement. in isEmptyConstructor()
526 if (!(CD->hasTrivialBody() && CD->getNumParams() == 0)) in isEmptyConstructor()
530 if (CD->getParent()->isDynamicClass()) in isEmptyConstructor()
534 if (CD->getParent()->isUnion()) in isEmptyConstructor()
539 if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) { in isEmptyConstructor()
541 dyn_cast<CXXConstructExpr>(CI->getInit())) in isEmptyConstructor()
542 return isEmptyConstructor(Loc, CE->getConstructor()); in isEmptyConstructor()
551 // No destructor -> no problem. in isEmptyDestructor()
555 if (!DD->isDefined() && DD->isTemplateInstantiation()) in isEmptyDestructor()
556 SemaRef.InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); in isEmptyDestructor()
561 if (DD->isTrivial()) in isEmptyDestructor()
566 // and the function body is an empty compound statement. in isEmptyDestructor()
567 if (!DD->hasTrivialBody()) in isEmptyDestructor()
570 const CXXRecordDecl *ClassDecl = DD->getParent(); in isEmptyDestructor()
573 if (ClassDecl->isDynamicClass()) in isEmptyDestructor()
578 if (DD->getParent()->isUnion()) in isEmptyDestructor()
583 if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) { in isEmptyDestructor()
584 if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl()) in isEmptyDestructor()
585 return isEmptyDestructor(Loc, RD->getDestructor()); in isEmptyDestructor()
591 if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) { in isEmptyDestructor()
592 if (CXXRecordDecl *RD = Field->getType() in isEmptyDestructor()
593 ->getBaseElementTypeUnsafe() in isEmptyDestructor()
594 ->getAsCXXRecordDecl()) in isEmptyDestructor()
595 return isEmptyDestructor(Loc, RD->getDestructor()); in isEmptyDestructor()
605 CICK_DeviceOrConstant, // Check initializer for device/constant variable
610 if (VD->getType()->isDependentType()) in IsDependentVar()
612 if (const auto *Init = VD->getInit()) in IsDependentVar()
613 return Init->isValueDependent(); in IsDependentVar()
617 // Check whether a variable has an allowed initializer for a CUDA device side
619 // potential promotion to device side variable.
628 assert(!VD->isInvalidDecl() && VD->hasGlobalStorage()); in HasAllowedCUDADeviceStaticInitializer()
630 const Expr *Init = VD->getInit(); in HasAllowedCUDADeviceStaticInitializer()
635 return S.isEmptyConstructor(VD->getLocation(), CE->getConstructor()); in HasAllowedCUDADeviceStaticInitializer()
643 return Init->isConstantInitializer(S.getASTContext(), in HasAllowedCUDADeviceStaticInitializer()
644 VD->getType()->isReferenceType()); in HasAllowedCUDADeviceStaticInitializer()
647 if (const auto *RD = VD->getType()->getAsCXXRecordDecl()) in HasAllowedCUDADeviceStaticInitializer()
648 return S.isEmptyDestructor(VD->getLocation(), RD->getDestructor()); in HasAllowedCUDADeviceStaticInitializer()
659 // Return early if VD is inside a non-instantiated template function since in checkAllowedInitializer()
662 dyn_cast_or_null<FunctionDecl>(VD->getDeclContext())) in checkAllowedInitializer()
663 if (FD->isDependentContext()) in checkAllowedInitializer()
668 if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage() || in checkAllowedInitializer()
671 const Expr *Init = VD->getInit(); in checkAllowedInitializer()
672 bool IsSharedVar = VD->hasAttr<CUDASharedAttr>(); in checkAllowedInitializer()
675 (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()); in checkAllowedInitializer()
680 Diag(VD->getLocation(), in checkAllowedInitializer()
682 << Init->getSourceRange(); in checkAllowedInitializer()
683 VD->setInvalidDecl(); in checkAllowedInitializer()
685 // This is a host-side global variable. Check that the initializer is in checkAllowedInitializer()
689 InitFn = CE->getConstructor(); in checkAllowedInitializer()
691 InitFn = CE->getDirectCallee(); in checkAllowedInitializer()
697 Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer) in checkAllowedInitializer()
699 Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn; in checkAllowedInitializer()
700 VD->setInvalidDecl(); in checkAllowedInitializer()
717 // Record whether an implicit host device function is used on device side. in RecordImplicitHostDeviceFuncUsedByDevice()
718 if (CallerTarget != CUDAFunctionTarget::Device && in RecordImplicitHostDeviceFuncUsedByDevice()
728 // With -fcuda-host-device-constexpr, an unattributed constexpr function is
730 // * it is a variadic function (device-side variadic functions are not
745 if (!NewD->hasAttr<CUDAHostAttr>()) in maybeAddHostDeviceAttrs()
746 NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
747 if (!NewD->hasAttr<CUDADeviceAttr>()) in maybeAddHostDeviceAttrs()
748 NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
752 // If a template function has no host/device/global attributes, in maybeAddHostDeviceAttrs()
753 // make it implicitly host device function. in maybeAddHostDeviceAttrs()
755 !NewD->hasAttr<CUDAHostAttr>() && !NewD->hasAttr<CUDADeviceAttr>() && in maybeAddHostDeviceAttrs()
756 !NewD->hasAttr<CUDAGlobalAttr>() && in maybeAddHostDeviceAttrs()
757 (NewD->getDescribedFunctionTemplate() || in maybeAddHostDeviceAttrs()
758 NewD->isFunctionTemplateSpecialization())) { in maybeAddHostDeviceAttrs()
759 NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
760 NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
764 if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() || in maybeAddHostDeviceAttrs()
765 NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() || in maybeAddHostDeviceAttrs()
766 NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>()) in maybeAddHostDeviceAttrs()
773 D = Using->getTargetDecl(); in maybeAddHostDeviceAttrs()
774 FunctionDecl *OldD = D->getAsFunction(); in maybeAddHostDeviceAttrs()
775 return OldD && OldD->hasAttr<CUDADeviceAttr>() && in maybeAddHostDeviceAttrs()
776 !OldD->hasAttr<CUDAHostAttr>() && in maybeAddHostDeviceAttrs()
786 // host+device. in maybeAddHostDeviceAttrs()
788 if (!SemaRef.getSourceManager().isInSystemHeader(Match->getLocation())) { in maybeAddHostDeviceAttrs()
789 Diag(NewD->getLocation(), in maybeAddHostDeviceAttrs()
792 Diag(Match->getLocation(), in maybeAddHostDeviceAttrs()
798 NewD->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
799 NewD->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); in maybeAddHostDeviceAttrs()
808 if (getLangOpts().CUDAIsDevice && !VD->hasAttr<CUDAConstantAttr>() && in MaybeAddConstantAttr()
809 !VD->hasAttr<CUDASharedAttr>() && in MaybeAddConstantAttr()
810 (VD->isFileVarDecl() || VD->isStaticDataMember()) && in MaybeAddConstantAttr()
812 ((VD->isConstexpr() || VD->getType().isConstQualified()) && in MaybeAddConstantAttr()
815 VD->addAttr(CUDAConstantAttr::CreateImplicit(getASTContext())); in MaybeAddConstantAttr()
829 case CUDAFunctionTarget::Device: in DiagIfDeviceCode()
833 // device code if we're compiling for device. Defer any errors in device in DiagIfDeviceCode()
834 // mode until the function is known-emitted. in DiagIfDeviceCode()
838 getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) in DiagIfDeviceCode()
864 // device code if we're compiling for device. Defer any errors in device in DiagIfHostCode()
865 // mode until the function is known-emitted. in DiagIfHostCode()
869 getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID)) in DiagIfHostCode()
896 // If the caller is known-emitted, mark the callee as known-emitted. in CheckCall()
905 assert(Caller && "Never/wrongSide calls require a non-null caller"); in CheckCall()
906 // If we know the caller will be emitted, we know this wrong-side call in CheckCall()
918 // For -fgpu-rdc, keep track of external kernels used by host functions. in CheckCall()
920 Callee->hasAttr<CUDAGlobalAttr>() && !Callee->isDefined() && in CheckCall()
921 (!Caller || (!Caller->getDescribedFunctionTemplate() && in CheckCall()
939 if (!Callee->getBuiltinID()) in CheckCall()
940 SemaDiagnosticBuilder(DiagKind, Callee->getLocation(), in CheckCall()
947 // Check the wrong-sided reference capture of lambda for CUDA/HIP.
956 // if the lambda structure is populated by a device function or kernel then in CheckLambdaCapture()
958 // since a device function or kernel can only call a device function, also a in CheckLambdaCapture()
965 // File-scope lambda can only do init captures for global variables, which in CheckLambdaCapture()
971 // In device compilation, we only need to check lambda functions which are in CheckLambdaCapture()
972 // emitted on device side. For such lambdas, a reference capture is invalid in CheckLambdaCapture()
974 // to and called in a device function or kernel. in CheckLambdaCapture()
975 bool CalleeIsDevice = Callee->hasAttr<CUDADeviceAttr>(); in CheckLambdaCapture()
977 !Caller->hasAttr<CUDAGlobalAttr>() && !Caller->hasAttr<CUDADeviceAttr>(); in CheckLambdaCapture()
988 // managed memory which is accessible on both device and host sides. It only in CheckLambdaCapture()
990 // accessible on device side. in CheckLambdaCapture()
999 if (Method->hasAttr<CUDAHostAttr>() || Method->hasAttr<CUDADeviceAttr>()) in SetLambdaAttrs()
1001 Method->addAttr(CUDADeviceAttr::CreateImplicit(getASTContext())); in SetLambdaAttrs()
1002 Method->addAttr(CUDAHostAttr::CreateImplicit(getASTContext())); in SetLambdaAttrs()
1010 FunctionDecl *OldFD = OldND->getAsFunction(); in checkTargetOverload()
1017 // functions can have different implementations on the host and device, but in checkTargetOverload()
1018 // HD/global functions "exist" in some sense on both the host and device, so in checkTargetOverload()
1026 OldTarget == CUDAFunctionTarget::Device)) || in checkTargetOverload()
1030 NewTarget == CUDAFunctionTarget::Device)) || in checkTargetOverload()
1033 Diag(NewFD->getLocation(), diag::err_cuda_ovl_target) in checkTargetOverload()
1034 << llvm::to_underlying(NewTarget) << NewFD->getDeclName() in checkTargetOverload()
1036 Diag(OldFD->getLocation(), diag::note_previous_declaration); in checkTargetOverload()
1037 NewFD->setInvalidDecl(); in checkTargetOverload()
1041 OldTarget == CUDAFunctionTarget::Device) || in checkTargetOverload()
1042 (NewTarget == CUDAFunctionTarget::Device && in checkTargetOverload()
1044 Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare) in checkTargetOverload()
1046 Diag(OldFD->getLocation(), diag::note_previous_declaration); in checkTargetOverload()
1056 AttrTy *Clone = Attribute->clone(S.Context); in copyAttrIfPresent()
1057 Clone->setInherited(true); in copyAttrIfPresent()
1058 FD->addAttr(Clone); in copyAttrIfPresent()