clang: lib/Sema/SemaCUDA.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include "llvm/ADT/STLForwardCompat.h"
25#include "llvm/ADT/SmallVector.h"
26#include
27using namespace clang;
28
30
32 if ()
33 return false;
34 if (auto *A = D->getAttr())
35 return !A->isImplicit();
36 return false;
37}
38
40 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
41 ForceHostDeviceDepth++;
42}
43
45 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
46 if (ForceHostDeviceDepth == 0)
47 return false;
48 ForceHostDeviceDepth--;
49 return true;
50}
51
56 if (!ConfigDecl)
57 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)
60
64
65 return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,
66 true);
67}
68
70 bool HasHostAttr = false;
71 bool HasDeviceAttr = false;
72 bool HasGlobalAttr = false;
73 bool HasInvalidTargetAttr = false;
75 switch (AL.getKind()) {
76 case ParsedAttr::AT_CUDAGlobal:
77 HasGlobalAttr = true;
78 break;
79 case ParsedAttr::AT_CUDAHost:
80 HasHostAttr = true;
81 break;
82 case ParsedAttr::AT_CUDADevice:
83 HasDeviceAttr = true;
84 break;
85 case ParsedAttr::AT_CUDAInvalidTarget:
86 HasInvalidTargetAttr = true;
87 break;
88 default:
89 break;
90 }
91 }
92
93 if (HasInvalidTargetAttr)
95
96 if (HasGlobalAttr)
98
99 if (HasHostAttr && HasDeviceAttr)
101
102 if (HasDeviceAttr)
104
106}
107
108template
109static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) {
111 return isa(Attribute) &&
112 !(IgnoreImplicitAttr && Attribute->isImplicit());
113 });
114}
115
118 : S(S_) {
121 auto *VD = dyn_cast_or_null(D);
122 if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) {
124 if ((hasAttr(VD, true) &&
125 !hasAttr(VD, true)) ||
126 hasAttr(VD, true) ||
127 hasAttr(VD, true))
130 }
131}
132
133
135 bool IgnoreImplicitHDAttr) {
136
137 if (D == nullptr)
139
142
145
146 if (hasAttr(D, IgnoreImplicitHDAttr)) {
147 if (hasAttr(D, IgnoreImplicitHDAttr))
150 } else if (hasAttr(D, IgnoreImplicitHDAttr)) {
152 } else if ((D->isImplicit() || ->isUserProvided()) &&
153 !IgnoreImplicitHDAttr) {
154
155
157 }
158
160}
161
162
164 if (Var->hasAttr())
166
167
168
170 Var->hasAttr() &&
171 !hasExplicitAttr(Var))
173 if (Var->hasAttr() || Var->hasAttr() ||
174 Var->hasAttr() ||
178
179
180
181
182 if (auto *FD = dyn_cast(Var->getDeclContext())) {
189 default:
191 }
192 }
194}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
227 assert(Callee && "Callee must be valid.");
228
229
230
231
234 (isa(Callee) || isa(Callee)))
236
239
240
241
245
246
247
252
253
256
257
258 if (CalleeTarget == CallerTarget ||
264
265
266
267
274
275
277
284
285
286
287
288
290 }
291
292
300
301 llvm_unreachable("All cases should've been handled by now.");
302}
303
305 if ()
306 return false;
307 if (auto *A = D->getAttr())
308 return A->isImplicit();
310}
311
313 bool IsImplicitDevAttr = hasImplicitAttr(D);
314 bool IsImplicitHostAttr = hasImplicitAttr(D);
315 return IsImplicitDevAttr && IsImplicitHostAttr;
316}
317
320 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
321 if (Matches.size() <= 1)
322 return;
323
324 using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
325
326
327 auto GetCFP = [&](const Pair &Match) {
329 };
330
331
333 Matches.begin(), Matches.end(),
334 [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
335
336
337 llvm::erase_if(Matches,
338 [&](const Pair &Match) { return GetCFP(Match) < BestCFP; });
339}
340
341
342
343
344
345
346
347
348
349static bool
353
356
358 *ResolvedTarget = Target2;
360 *ResolvedTarget = Target1;
361 } else if (Target1 != Target2) {
362 return true;
363 } else {
364 *ResolvedTarget = Target1;
365 }
366
367 return false;
368}
369
373 bool ConstRHS,
374 bool Diagnose) {
375
376
377
379 bool HasH = MemberDecl->hasAttr();
380 bool HasD = MemberDecl->hasAttr();
381 bool HasExplicitAttr =
382 (HasD && !MemberDecl->getAttr()->isImplicit()) ||
383 (HasH && !MemberDecl->getAttr()->isImplicit());
384 if (!InClass || HasExplicitAttr)
385 return false;
386
387 std::optional InferredTarget;
388
389
390
392
393
394
395
397 for (const auto &B : ClassDecl->bases()) {
398 if (!B.isVirtual()) {
399 Bases.push_back(&B);
400 }
401 }
402
404 llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases()));
405 }
406
407 for (const auto *B : Bases) {
409 if (!BaseType) {
410 continue;
411 }
412
416 ConstRHS,
417 false,
418 false,
419 false,
420 false);
421
423 continue;
424
426 if (!InferredTarget) {
427 InferredTarget = BaseMethodTarget;
428 } else {
430 *InferredTarget, BaseMethodTarget, &*InferredTarget);
431 if (ResolutionError) {
432 if (Diagnose) {
434 diag::note_implicit_member_target_infer_collision)
435 << (unsigned)CSM << llvm::to_underlying(*InferredTarget)
436 << llvm::to_underlying(BaseMethodTarget);
437 }
439 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
440 return true;
441 }
442 }
443 }
444
445
446 for (const auto *F : ClassDecl->fields()) {
447 if (F->isInvalidDecl()) {
448 continue;
449 }
450
453 if (!FieldType) {
454 continue;
455 }
456
460 ConstRHS && !F->isMutable(),
461 false,
462 false,
463 false,
464 false);
465
467 continue;
468
470 if (!InferredTarget) {
471 InferredTarget = FieldMethodTarget;
472 } else {
474 *InferredTarget, FieldMethodTarget, &*InferredTarget);
475 if (ResolutionError) {
476 if (Diagnose) {
478 diag::note_implicit_member_target_infer_collision)
479 << (unsigned)CSM << llvm::to_underlying(*InferredTarget)
480 << llvm::to_underlying(FieldMethodTarget);
481 }
483 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));
484 return true;
485 }
486 }
487 }
488
489
490
491
492 bool NeedsH = true, NeedsD = true;
493 if (InferredTarget) {
495 NeedsH = false;
497 NeedsD = false;
498 }
499
500
501
502 if (NeedsD && !HasD)
504 if (NeedsH && !HasH)
506
507 return false;
508}
509
513
514
515
516
518 return true;
519
520
521
522
523
525 return false;
526
527
529 return false;
530
531
533 return true;
534
535
536
538 if (const CXXConstructExpr *CE =
539 dyn_cast(CI->getInit()))
540 return isEmptyConstructor(Loc, CE->getConstructor());
541 return false;
542 }))
543 return false;
544
545 return true;
546}
547
549
550 if (!DD)
551 return true;
552
555
556
557
558
560 return true;
561
562
563
564
566 return false;
567
569
570
572 return false;
573
574
575
577 return true;
578
579
580
582 if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl())
583 return isEmptyDestructor(Loc, RD->getDestructor());
584 return true;
585 }))
586 return false;
587
588
589 if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) {
590 if (CXXRecordDecl *RD = Field->getType()
591 ->getBaseElementTypeUnsafe()
592 ->getAsCXXRecordDecl())
593 return isEmptyDestructor(Loc, RD->getDestructor());
594 return true;
595 }))
596 return false;
597
598 return true;
599}
600
601namespace {
602enum CUDAInitializerCheckKind {
603 CICK_DeviceOrConstant,
604 CICK_Shared,
605};
606
607bool IsDependentVar(VarDecl *VD) {
609 return true;
611 return Init->isValueDependent();
612 return false;
613}
614
615
616
617
618
619
620
621
622
623
624bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD,
625 CUDAInitializerCheckKind CheckKind) {
627 assert(!IsDependentVar(VD) && "do not check dependent var");
629 auto IsEmptyInit = [&](const Expr *Init) {
631 return true;
632 if (const auto *CE = dyn_cast(Init)) {
633 return S.isEmptyConstructor(VD->getLocation(), CE->getConstructor());
634 }
635 return false;
636 };
637 auto IsConstantInit = [&](const Expr *Init) {
638 assert(Init);
640 true);
643 };
644 auto HasEmptyDtor = [&](VarDecl *VD) {
646 return S.isEmptyDestructor(VD->getLocation(), RD->getDestructor());
647 return true;
648 };
649 if (CheckKind == CICK_Shared)
650 return IsEmptyInit(Init) && HasEmptyDtor(VD);
651 return S.getLangOpts().GPUAllowDeviceInit ||
652 ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD));
653}
654}
655
657
658
660 dyn_cast_or_null(VD->getDeclContext());
662 return;
663
664
665
667 IsDependentVar(VD))
668 return;
670 bool IsSharedVar = VD->hasAttr();
671 bool IsDeviceOrConstantVar =
672 !IsSharedVar &&
673 (VD->hasAttr() || VD->hasAttr());
674 if (IsDeviceOrConstantVar || IsSharedVar) {
675 if (HasAllowedCUDADeviceStaticInitializer(
676 *this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))
677 return;
679 IsSharedVar ? diag::err_shared_var_init : diag::err_dynamic_var_init)
680 << Init->getSourceRange();
682 } else {
683
684
687 InitFn = CE->getConstructor();
688 } else if (const CallExpr *CE = dyn_cast(Init)) {
689 InitFn = CE->getDirectCallee();
690 }
691 if (InitFn) {
695 Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)
696 << llvm::to_underlying(InitFnTarget) << InitFn;
697 Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;
699 }
700 }
701 }
702}
703
707 if (!Caller)
708 return;
709
711 return;
712
714
715
720 ().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller))))
721 return;
722
724}
725
726
727
728
729
730
731
732
733
734
735
736
737
740 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
741
742 if (ForceHostDeviceDepth > 0) {
743 if (!NewD->hasAttr())
745 if (!NewD->hasAttr())
747 return;
748 }
749
750
751
752 if (getLangOpts().OffloadImplicitHostDeviceTemplates &&
753 !NewD->hasAttr() && !NewD->hasAttr() &&
754 !NewD->hasAttr() &&
759 return;
760 }
761
764 NewD->hasAttr() || NewD->hasAttr())
765 return;
766
767
768
769 auto IsMatchingDeviceFn = [&](NamedDecl *D) {
771 D = Using->getTargetDecl();
773 return OldD && OldD->hasAttr() &&
774 !OldD->hasAttr() &&
776 false,
777 false);
778 };
779 auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
781
782
783
784
788 diag::err_cuda_unattributed_constexpr_cannot_overload_device)
789 << NewD;
791 diag::note_cuda_conflicting_device_function_declared_here);
792 }
793 return;
794 }
795
798}
799
800
801
802
804
805
806 if (getLangOpts().CUDAIsDevice && !VD->hasAttr() &&
807 !VD->hasAttr() &&
809 !IsDependentVar(VD) &&
811 HasAllowedCUDADeviceStaticInitializer(*this, VD,
812 CICK_DeviceOrConstant))) {
814 }
815}
816
818 unsigned DiagID) {
819 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
822 SemaDiagnosticBuilder::Kind DiagKind = [&] {
823 if (!CurFunContext)
824 return SemaDiagnosticBuilder::K_Nop;
828 return SemaDiagnosticBuilder::K_Immediate;
830
831
832
834 return SemaDiagnosticBuilder::K_Nop;
836 getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID))
837 return SemaDiagnosticBuilder::K_Immediate;
840 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
841 : SemaDiagnosticBuilder::K_Deferred;
842 default:
843 return SemaDiagnosticBuilder::K_Nop;
844 }
845 }();
847}
848
850 unsigned DiagID) {
851 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
854 SemaDiagnosticBuilder::Kind DiagKind = [&] {
855 if (!CurFunContext)
856 return SemaDiagnosticBuilder::K_Nop;
859 return SemaDiagnosticBuilder::K_Immediate;
861
862
863
865 return SemaDiagnosticBuilder::K_Nop;
867 getDiagnostics().getDiagnosticIDs()->isBuiltinNote(DiagID))
868 return SemaDiagnosticBuilder::K_Immediate;
871 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
872 : SemaDiagnosticBuilder::K_Deferred;
873 default:
874 return SemaDiagnosticBuilder::K_Nop;
875 }
876 }();
878}
879
881 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
882 assert(Callee && "Callee may not be null.");
883
885 if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated())
886 return true;
887
888
889
891 if (!Caller)
892 return true;
893
894
895
898 SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee,
899 CallerKnownEmitted] {
903 assert(Caller && "Never/wrongSide calls require a non-null caller");
904
905
906
907 return CallerKnownEmitted
908 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack
909 : SemaDiagnosticBuilder::K_Deferred;
910 default:
911 return SemaDiagnosticBuilder::K_Nop;
912 }
913 }();
914
915 if (DiagKind == SemaDiagnosticBuilder::K_Nop) {
916
918 Callee->hasAttr() && !Callee->isDefined() &&
923 return true;
924 }
925
926
927
928
929
931 return true;
932
933 SemaDiagnosticBuilder(DiagKind, Loc, diag::err_ref_bad_target, Caller,
935 << llvm::to_underlying(IdentifyTarget(Callee)) << 0 << Callee
937 if (!Callee->getBuiltinID())
938 SemaDiagnosticBuilder(DiagKind, Callee->getLocation(),
939 diag::note_previous_decl, Caller, SemaRef)
940 << Callee;
941 return DiagKind != SemaDiagnosticBuilder::K_Immediate &&
942 DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;
943}
944
945
946
947
948
949
952
953
954
955
956
957
958
959
961 return;
962
963
964
966 if (!Caller)
967 return;
968
969
970
971
972
973 bool CalleeIsDevice = Callee->hasAttr();
974 bool CallerIsHost =
975 !Caller->hasAttr() && !Caller->hasAttr();
976 bool ShouldCheck = CalleeIsDevice && CallerIsHost;
978 return;
979 auto DiagKind = SemaDiagnosticBuilder::K_Deferred;
982 diag::err_capture_bad_target, Callee, SemaRef)
985
986
987
988
990 diag::warn_maybe_capture_bad_target_this_ptr, Callee,
992 }
993}
994
996 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
997 if (Method->hasAttr() || Method->hasAttr())
998 return;
1001}
1002
1005 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
1009 if (!OldFD)
1010 continue;
1011
1013
1014
1015
1016
1017
1018 if (NewTarget != OldTarget &&
1019 .IsOverload(NewFD, OldFD, false,
1020 false)) {
1022 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1026 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&
1032 << llvm::to_underlying(NewTarget) << NewFD->getDeclName()
1033 << llvm::to_underlying(OldTarget) << OldFD;
1034 Diag(OldFD->getLocation(), diag::note_previous_declaration);
1036 break;
1037 }
1042 Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)
1043 << llvm::to_underlying(NewTarget) << llvm::to_underlying(OldTarget);
1044 Diag(OldFD->getLocation(), diag::note_previous_declaration);
1045 }
1046 }
1047 }
1048}
1049
1050template
1053 if (AttrTy *Attribute = TemplateFD.getAttr()) {
1054 AttrTy *Clone = Attribute->clone(S.Context);
1055 Clone->setInherited(true);
1057 }
1058}
1059
1063 copyAttrIfPresent(SemaRef, FD, TemplateFD);
1064 copyAttrIfPresent(SemaRef, FD, TemplateFD);
1065 copyAttrIfPresent(SemaRef, FD, TemplateFD);
1066}
1067
1070 return "__llvmPushCallConfiguration";
1071
1073 return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration"
1074 : "hipConfigureCall";
1075
1076
1079 return "__cudaPushCallConfiguration";
1080
1081
1082 return "cudaConfigureCall";
1083}
Defines the clang::ASTContext interface.
static bool hasImplicitAttr(const ValueDecl *D)
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::MachO::Target Target
Defines the clang::Preprocessor interface.
static bool resolveCalleeCUDATargetConflict(CUDAFunctionTarget Target1, CUDAFunctionTarget Target2, CUDAFunctionTarget *ResolvedTarget)
When an implicitly-declared special member has to invoke more than one base/field special member,...
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, const FunctionDecl &TemplateFD)
static bool hasExplicitAttr(const VarDecl *D)
This file declares semantic analysis for CUDA constructs.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
llvm::SetVector< const ValueDecl * > CUDAExternalDeviceDeclODRUsedByHost
Keep track of CUDA/HIP external kernels or device variables ODR-used by host code.
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
llvm::DenseSet< const FunctionDecl * > CUDAImplicitHostDeviceFunUsedByDevice
Keep track of CUDA/HIP implicit host device functions used on device side in device compilation.
FunctionDecl * getcudaConfigureCallDecl()
Attr - This represents one attribute.
Represents a base class of a C++ class.
Represents a call to a C++ constructor.
Represents a C++ constructor within a class.
Represents a C++ base or member initializer.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
base_class_range vbases()
bool isAbstract() const
Determine whether this class has a pure virtual function.
bool isDynamicClass() const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
bool isInvalidDecl() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
This represents one expression.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen.
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
bool isVariadic() const
Whether this function is variadic.
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Represents the results of name lookup.
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
ParsedAttr - Represents a syntactic attribute.
A (possibly-)qualified type.
bool isConstQualified() const
Determine whether this type is const-qualified.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Scope - A scope is a transient data structure that is used while parsing the program.
A generic diagnostic builder for errors which may or may not be deferred.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
void PushForceHostDevice()
Increments our count of the number of times we've seen a pragma forcing functions to be host device.
void checkAllowedInitializer(VarDecl *VD)
void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD)
Record FD if it is a CUDA/HIP implicit host device function used on device side in device compilation...
std::string getConfigureFuncName() const
Returns the name of the launch configuration function.
bool PopForceHostDevice()
Decrements our count of the number of times we've seen a pragma forcing functions to be host device.
CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr=false)
Determines whether the given function is a CUDA device/host/kernel/etc.
void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous)
May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, depending on FD and the current co...
ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD)
bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD)
void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous)
Check whether NewFD is a valid overload for CUDA.
CUDAFunctionTarget CurrentTarget()
Gets the CUDA target for the current context.
SemaDiagnosticBuilder DiagIfHostCode(SourceLocation Loc, unsigned DiagID)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
bool inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXSpecialMemberKind CSM, CXXMethodDecl *MemberDecl, bool ConstRHS, bool Diagnose)
Given a implicit special member, infer its CUDA target from the calls it needs to make to underlying ...
struct clang::SemaCUDA::CUDATargetContext CurCUDATargetCtx
CUDATargetContextKind
Defines kinds of CUDA global host/device context where a function may be called.
@ CTCK_InitGlobalVar
Unknown context.
SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
llvm::DenseSet< FunctionDeclAndLoc > LocsWithCUDACallDiags
FunctionDecls and SourceLocations for which CheckCall has emitted a (maybe deferred) "bad call" diagn...
bool CheckCall(SourceLocation Loc, FunctionDecl *Callee)
Check whether we're allowed to call Callee from the current context.
void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD)
Copies target attributes from the template TD to the function FD.
static bool isImplicitHostDeviceFunction(const FunctionDecl *D)
void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture)
void MaybeAddConstantAttr(VarDecl *VD)
May add implicit CUDAConstantAttr attribute to VD, depending on VD and current compilation settings.
void EraseUnwantedMatches(const FunctionDecl *Caller, llvm::SmallVectorImpl< std::pair< DeclAccessPair, FunctionDecl * > > &Matches)
Finds a function in Matches with highest calling priority from Caller context and erases all function...
void SetLambdaAttrs(CXXMethodDecl *Method)
Set device or host device attributes on the given lambda operator() method.
CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, const FunctionDecl *Callee)
Identifies relative preference of a given Caller/Callee combination, based on their host/device attri...
@ CVT_Host
Emitted on device side with a shadow variable on host side.
@ CVT_Both
Emitted on host side only.
@ CVT_Unified
Emitted on both sides with different addresses.
SpecialMemberOverloadResult - The overloading result for a special member function.
CXXMethodDecl * getMethod() const
Sema - This implements semantic analysis and AST building for C.
bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs=true)
bool IsLastErrorImmediate
Is the last error level diagnostic immediate.
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
ASTContext & getASTContext() const
const LangOptions & getLangOpts() const
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
SourceManager & getSourceManager() const
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive=false, bool DefinitionRequired=false, bool AtEndOfTU=false)
Instantiate the definition of the given function from its template.
SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...
Encodes a location in the source.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isReferenceType() const
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
const T * getAs() const
Member-template getAs'.
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
bool isStaticDataMember() const
Determines whether this is a static data member.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
const Expr * getInit() const
ValueDecl * getVariable() const
bool isVariableCapture() const
SourceLocation getLocation() const
Retrieve the location at which this variable was captured.
bool isThisCapture() const
bool isReferenceCapture() const
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature)
CXXSpecialMemberKind
Kinds of C++ special members.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
CUDATargetContextKind Kind
CUDAFunctionTarget Target