clang: lib/Sema/SemaCUDA.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

25#include "llvm/ADT/SmallVector.h"

26#include

27using namespace clang;

28

30

32 if (!D)

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

55 bool IsDeviceKernelCall = false;

59 IsDeviceKernelCall = true;

60 break;

63 IsDeviceKernelCall = true;

65 SemaRef.getCurFunctionDecl(true);

67

68

69

70 if (getLangOpts().GPURelocatableDeviceCode)

71 IsDeviceKernelCall = false;

72

73

75 IsDeviceKernelCall = false;

76 }

77 }

78 break;

79 default:

80 break;

81 }

82

85 Diag(LLLLoc, diag::err_cuda_device_kernel_launch_not_supported));

86

87 if (IsDeviceKernelCall && getLangOpts().GPURelocatableDeviceCode)

89 Diag(LLLLoc, diag::err_cuda_device_kernel_launch_require_rdc));

90

94 if (!ConfigDecl)

95 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)

98

99 if (IsDeviceKernelCall) {

101 if (!GetParamBuf)

102 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use)

104 }

105

107

110 SemaRef.MarkFunctionReferenced(LLLLoc, ConfigDecl);

111

112 if (IsDeviceKernelCall) {

114

115

116

117 llvm::APInt Zero(SemaRef.Context.getTypeSize(SemaRef.Context.IntTy), 0);

119 SemaRef.Context.IntTy, LLLLoc));

120

121

123 SemaRef.Context.IntTy, LLLLoc));

124

125 llvm::append_range(Args, ExecConfig);

126

127 if (Args.size() < 4) {

128 llvm::APInt One(SemaRef.Context.getTypeSize(SemaRef.Context.IntTy), 1);

130 SemaRef.Context.IntTy, LLLLoc));

131 }

132

133 if (Args.size() < 5)

135 SemaRef.Context.IntTy, LLLLoc));

136

137 if (Args.size() < 6)

139 SemaRef.Context.NullPtrTy, LLLLoc));

140 return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, Args, GGGLoc, nullptr,

141 true);

142 }

143 return SemaRef.BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr,

144 true);

145}

146

148 bool HasHostAttr = false;

149 bool HasDeviceAttr = false;

150 bool HasGlobalAttr = false;

151 bool HasInvalidTargetAttr = false;

153 switch (AL.getKind()) {

154 case ParsedAttr::AT_CUDAGlobal:

155 HasGlobalAttr = true;

156 break;

157 case ParsedAttr::AT_CUDAHost:

158 HasHostAttr = true;

159 break;

160 case ParsedAttr::AT_CUDADevice:

161 HasDeviceAttr = true;

162 break;

163 case ParsedAttr::AT_CUDAInvalidTarget:

164 HasInvalidTargetAttr = true;

165 break;

166 default:

167 break;

168 }

169 }

170

171 if (HasInvalidTargetAttr)

173

174 if (HasGlobalAttr)

176

177 if (HasHostAttr && HasDeviceAttr)

179

180 if (HasDeviceAttr)

182

184}

185

186template

187static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr) {

189 return isa(Attribute) &&

190 !(IgnoreImplicitAttr && Attribute->isImplicit());

191 });

192}

193

196 : S(S_) {

199 auto *VD = dyn_cast_or_null(D);

200 if (VD && VD->hasGlobalStorage() && !VD->isStaticLocal()) {

207 S.CurCUDATargetCtx = {Target, K, VD};

208 }

209}

210

211

213 bool IgnoreImplicitHDAttr) {

214

215 if (D == nullptr)

217

218

219

220

223

224 if (D->hasAttr())

226

227 if (D->hasAttr())

229

232

240 !IgnoreImplicitHDAttr) {

241

242

244 }

245

247}

248

249

251 if (Var->hasAttr())

253

254

255

257 Var->hasAttr() &&

260 if (Var->hasAttr() || Var->hasAttr() ||

261 Var->hasAttr() ||

265

266

267

268

269 if (auto *FD = dyn_cast(Var->getDeclContext())) {

276 default:

278 }

279 }

281}

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

314 assert(Callee && "Callee must be valid.");

315

316

317

318

323

326

327

328

332

333

334

339

340

343

344

345 if (CalleeTarget == CallerTarget ||

351

352

353

354

361

362

364

372

373

374

375

376

378 }

379

380

388

389 llvm_unreachable("All cases should've been handled by now.");

390}

391

393 if (!D)

394 return false;

395 if (auto *A = D->getAttr())

396 return A->isImplicit();

398}

399

403 return IsImplicitDevAttr && IsImplicitHostAttr;

404}

405

408 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {

409 if (Matches.size() <= 1)

410 return;

411

412 using Pair = std::pair<DeclAccessPair, FunctionDecl *>;

413

414

415 auto GetCFP = [&](const Pair &Match) {

417 };

418

419

421 GetCFP(*llvm::max_element(Matches, [&](const Pair &M1, const Pair &M2) {

422 return GetCFP(M1) < GetCFP(M2);

423 }));

424

425

426 llvm::erase_if(Matches,

427 [&](const Pair &Match) { return GetCFP(Match) < BestCFP; });

428}

429

430

431

432

433

434

435

436

437

438static bool

442

445

447 *ResolvedTarget = Target2;

449 *ResolvedTarget = Target1;

450 } else if (Target1 != Target2) {

451 return true;

452 } else {

453 *ResolvedTarget = Target1;

454 }

455

456 return false;

457}

458

462 bool ConstRHS,

463 bool Diagnose) {

464

465

466

467

468 bool IsExpVDtor = false;

470 if (auto *Spec = dyn_cast(ClassDecl)) {

474 }

475 }

476 if (IsExpVDtor)

477 SemaRef.DeclsToCheckForDeferredDiags.insert(MemberDecl);

478

479

480

481

483 bool HasH = MemberDecl->hasAttr();

484 bool HasD = MemberDecl->hasAttr();

485 bool HasExplicitAttr =

486 (HasD && !MemberDecl->getAttr()->isImplicit()) ||

487 (HasH && !MemberDecl->getAttr()->isImplicit());

488 if (!InClass || HasExplicitAttr)

489 return false;

490

491 std::optional InferredTarget;

492

493

494

496

497

498

499

501 for (const auto &B : ClassDecl->bases()) {

502 if (!B.isVirtual()) {

503 Bases.push_back(&B);

504 }

505 }

506

508 llvm::append_range(Bases, llvm::make_pointer_range(ClassDecl->vbases()));

509 }

510

511 for (const auto *B : Bases) {

512 auto *BaseClassDecl = B->getType()->getAsCXXRecordDecl();

513 if (!BaseClassDecl)

514 continue;

515

517 SemaRef.LookupSpecialMember(BaseClassDecl, CSM,

518 ConstRHS,

519 false,

520 false,

521 false,

522 false);

523

525 continue;

526

529

530 if (!InferredTarget) {

531 InferredTarget = BaseMethodTarget;

532 } else {

534 *InferredTarget, BaseMethodTarget, &*InferredTarget);

535 if (ResolutionError) {

536 if (Diagnose) {

538 diag::note_implicit_member_target_infer_collision)

539 << (unsigned)CSM << *InferredTarget << BaseMethodTarget;

540 }

542 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));

543 return true;

544 }

545 }

546 }

547

548

549 for (const auto *F : ClassDecl->fields()) {

550 if (F->isInvalidDecl()) {

551 continue;

552 }

553

554 auto *FieldRecDecl =

556 if (!FieldRecDecl)

557 continue;

558

560 SemaRef.LookupSpecialMember(FieldRecDecl, CSM,

561 ConstRHS && !F->isMutable(),

562 false,

563 false,

564 false,

565 false);

566

568 continue;

569

572

573 if (!InferredTarget) {

574 InferredTarget = FieldMethodTarget;

575 } else {

577 *InferredTarget, FieldMethodTarget, &*InferredTarget);

578 if (ResolutionError) {

579 if (Diagnose) {

581 diag::note_implicit_member_target_infer_collision)

582 << (unsigned)CSM << *InferredTarget << FieldMethodTarget;

583 }

585 CUDAInvalidTargetAttr::CreateImplicit(getASTContext()));

586 return true;

587 }

588 }

589 }

590

591

592

593 bool NeedsH = true, NeedsD = true;

594 if (InferredTarget) {

596 NeedsH = false;

598 NeedsD = false;

599 }

600

601

602

603 if (NeedsD && !HasD)

605 if (NeedsH && !HasH)

607

608 return false;

609}

610

614

615

616

617

619 return true;

620

621

622

623

624

626 return false;

627

628

630 return false;

631

632

634 return true;

635

636

637

639 if (const CXXConstructExpr *CE =

640 dyn_cast(CI->getInit()))

641 return isEmptyConstructor(Loc, CE->getConstructor());

642 return false;

643 }))

644 return false;

645

646 return true;

647}

648

650

651 if (!DD)

652 return true;

653

656

657

658

659

661 return true;

662

663

664

665

667 return false;

668

670

671

673 return false;

674

675

676

678 return true;

679

680

681

683 if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl())

684 return isEmptyDestructor(Loc, RD->getDestructor());

685 return true;

686 }))

687 return false;

688

689

690 if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) {

691 if (CXXRecordDecl *RD = Field->getType()

692 ->getBaseElementTypeUnsafe()

693 ->getAsCXXRecordDecl())

694 return isEmptyDestructor(Loc, RD->getDestructor());

695 return true;

696 }))

697 return false;

698

699 return true;

700}

701

702namespace {

703enum CUDAInitializerCheckKind {

704 CICK_DeviceOrConstant,

705 CICK_Shared,

706};

707

708bool IsDependentVar(VarDecl *VD) {

710 return true;

712 return Init->isValueDependent();

713 return false;

714}

715

716

717

718

719

720

721

722

723

724

725bool HasAllowedCUDADeviceStaticInitializer(SemaCUDA &S, VarDecl *VD,

726 CUDAInitializerCheckKind CheckKind) {

728 assert(!IsDependentVar(VD) && "do not check dependent var");

730 auto IsEmptyInit = [&](const Expr *Init) {

732 return true;

733 if (const auto *CE = dyn_cast(Init)) {

735 }

736 return false;

737 };

738 auto IsConstantInit = [&](const Expr *Init) {

739 assert(Init);

740 ASTContext::CUDAConstantEvalContextRAII EvalCtx(S.getASTContext(),

741 true);

744 };

745 auto HasEmptyDtor = [&](VarDecl *VD) {

748 return true;

749 };

750 if (CheckKind == CICK_Shared)

751 return IsEmptyInit(Init) && HasEmptyDtor(VD);

752 return S.getLangOpts().GPUAllowDeviceInit ||

753 ((IsEmptyInit(Init) || IsConstantInit(Init)) && HasEmptyDtor(VD));

754}

755}

756

758

759

761 dyn_cast_or_null(VD->getDeclContext());

763 return;

764

765 bool IsSharedVar = VD->hasAttr();

766 bool IsDeviceOrConstantVar =

767 !IsSharedVar &&

768 (VD->hasAttr() || VD->hasAttr());

769 if ((IsSharedVar || IsDeviceOrConstantVar) &&

771 Diag(VD->getLocation(), diag::err_cuda_address_space_gpuvar);

773 return;

774 }

775

776

778 IsDependentVar(VD))

779 return;

781 if (IsDeviceOrConstantVar || IsSharedVar) {

782 if (HasAllowedCUDADeviceStaticInitializer(

783 *this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))

784 return;

786 IsSharedVar ? diag::err_shared_var_init : diag::err_dynamic_var_init)

787 << Init->getSourceRange();

789 } else {

790

791

794 InitFn = CE->getConstructor();

795 } else if (const CallExpr *CE = dyn_cast(Init)) {

796 InitFn = CE->getDirectCallee();

797 }

798 if (InitFn) {

802 Diag(VD->getLocation(), diag::err_ref_bad_target_global_initializer)

803 << InitFnTarget << InitFn;

804 Diag(InitFn->getLocation(), diag::note_previous_decl) << InitFn;

806 }

807 }

808 }

809}

810

814 if (!Caller)

815 return;

816

818 return;

819

821

822

827 getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(Caller))))

828 return;

829

831}

832

833

834

835

836

837

838

839

840

841

842

843

844

847 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

848

849 if (ForceHostDeviceDepth > 0) {

850 if (!NewD->hasAttr())

852 if (!NewD->hasAttr())

854 return;

855 }

856

857

858

859 if (getLangOpts().OffloadImplicitHostDeviceTemplates &&

860 !NewD->hasAttr() && !NewD->hasAttr() &&

861 !NewD->hasAttr() &&

866 return;

867 }

868

871 NewD->hasAttr() || NewD->hasAttr())

872 return;

873

874

875

876 auto IsMatchingDeviceFn = [&](NamedDecl *D) {

877 if (UsingShadowDecl *Using = dyn_cast(D))

878 D = Using->getTargetDecl();

880 return OldD && OldD->hasAttr() &&

881 !OldD->hasAttr() &&

882 SemaRef.IsOverload(NewD, OldD,

883 false,

884 false);

885 };

886 auto It = llvm::find_if(Previous, IsMatchingDeviceFn);

888

889

890

891

893 if (SemaRef.getSourceManager().isInSystemHeader(Match->getLocation())) {

895 diag::err_cuda_unattributed_constexpr_cannot_overload_device)

896 << NewD;

898 diag::note_cuda_conflicting_device_function_declared_here);

899 }

900 return;

901 }

902

905}

906

907

908

909

911

912

913 if (getLangOpts().CUDAIsDevice && !VD->hasAttr() &&

914 !VD->hasAttr() &&

916 !IsDependentVar(VD) &&

918 HasAllowedCUDADeviceStaticInitializer(*this, VD,

919 CICK_DeviceOrConstant))) {

921 }

922}

923

925 unsigned DiagID) {

926 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

928 SemaRef.getCurFunctionDecl(true);

929 SemaDiagnosticBuilder::Kind DiagKind = [&] {

930 if (!CurFunContext)

931 return SemaDiagnosticBuilder::K_Nop;

935 return SemaDiagnosticBuilder::K_Immediate;

937

938

939

941 return SemaDiagnosticBuilder::K_Nop;

942 if (SemaRef.IsLastErrorImmediate &&

944 return SemaDiagnosticBuilder::K_Immediate;

945 return (SemaRef.getEmissionStatus(CurFunContext) ==

947 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack

948 : SemaDiagnosticBuilder::K_Deferred;

949 default:

950 return SemaDiagnosticBuilder::K_Nop;

951 }

952 }();

954}

955

957 unsigned DiagID) {

958 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

960 SemaRef.getCurFunctionDecl(true);

961 SemaDiagnosticBuilder::Kind DiagKind = [&] {

962 if (!CurFunContext)

963 return SemaDiagnosticBuilder::K_Nop;

966 return SemaDiagnosticBuilder::K_Immediate;

968

969

970

972 return SemaDiagnosticBuilder::K_Nop;

973 if (SemaRef.IsLastErrorImmediate &&

975 return SemaDiagnosticBuilder::K_Immediate;

976 return (SemaRef.getEmissionStatus(CurFunContext) ==

978 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack

979 : SemaDiagnosticBuilder::K_Deferred;

980 default:

981 return SemaDiagnosticBuilder::K_Nop;

982 }

983 }();

985}

986

988 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

989 assert(Callee && "Callee may not be null.");

990

991 const auto &ExprEvalCtx = SemaRef.currentEvaluationContext();

992 if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated())

993 return true;

994

995

996

997

999 return true;

1000

1001

1002

1003 FunctionDecl *Caller = SemaRef.getCurFunctionDecl(true);

1004 if (!Caller)

1005 return true;

1006

1007

1008

1009 bool CallerKnownEmitted = SemaRef.getEmissionStatus(Caller) ==

1011 SemaDiagnosticBuilder::Kind DiagKind = [this, Caller, Callee,

1012 CallerKnownEmitted] {

1016 assert(Caller && "Never/wrongSide calls require a non-null caller");

1017

1018

1019

1020 return CallerKnownEmitted

1021 ? SemaDiagnosticBuilder::K_ImmediateWithCallStack

1022 : SemaDiagnosticBuilder::K_Deferred;

1023 default:

1024 return SemaDiagnosticBuilder::K_Nop;

1025 }

1026 }();

1027

1028 if (DiagKind == SemaDiagnosticBuilder::K_Nop) {

1029

1031 Callee->hasAttr() && !Callee->isDefined() &&

1033 getASTContext().GetGVALinkageForFunction(Caller) ==

1036 return true;

1037 }

1038

1039

1040

1041

1042

1044 return true;

1045

1048 << IdentifyTarget(Callee) << 0 << Callee

1050 if (!Callee->getBuiltinID())

1052 diag::note_previous_decl, Caller, SemaRef)

1053 << Callee;

1054 return DiagKind != SemaDiagnosticBuilder::K_Immediate &&

1055 DiagKind != SemaDiagnosticBuilder::K_ImmediateWithCallStack;

1056}

1057

1058

1059

1060

1061

1062

1065

1066

1067

1068

1069

1070

1071

1072

1074 return;

1075

1076

1077

1078 FunctionDecl *Caller = SemaRef.getCurFunctionDecl(true);

1079 if (!Caller)

1080 return;

1081

1082

1083

1084

1085

1086 bool CalleeIsDevice = Callee->hasAttr();

1087 bool CallerIsHost =

1088 !Caller->hasAttr() && !Caller->hasAttr();

1089 bool ShouldCheck = CalleeIsDevice && CallerIsHost;

1091 return;

1092 auto DiagKind = SemaDiagnosticBuilder::K_Deferred;

1095 diag::err_capture_bad_target, Callee, SemaRef)

1098

1099

1100

1101

1103 diag::warn_maybe_capture_bad_target_this_ptr, Callee,

1105 }

1106}

1107

1109 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

1110 if (Method->hasAttr() || Method->hasAttr())

1111 return;

1114}

1115

1118 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

1122 if (!OldFD)

1123 continue;

1124

1126

1127

1128

1129

1130

1131 if (NewTarget != OldTarget &&

1132 SemaRef.IsOverload(NewFD, OldFD, false,

1133 false)) {

1135 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&

1139 !(getLangOpts().OffloadImplicitHostDeviceTemplates &&

1145 << NewTarget << NewFD->getDeclName() << OldTarget << OldFD;

1146 Diag(OldFD->getLocation(), diag::note_previous_declaration);

1148 break;

1149 }

1154 Diag(NewFD->getLocation(), diag::warn_offload_incompatible_redeclare)

1155 << NewTarget << OldTarget;

1156 Diag(OldFD->getLocation(), diag::note_previous_declaration);

1157 }

1158 }

1159 }

1160}

1161

1162template

1165 if (AttrTy *Attribute = TemplateFD.getAttr()) {

1166 AttrTy *Clone = Attribute->clone(S.Context);

1167 Clone->setInherited(true);

1169 }

1170}

1171

1179

1182 return "__llvmPushCallConfiguration";

1183

1185 return getLangOpts().HIPUseNewLaunchAPI ? "__hipPushCallConfiguration"

1186 : "hipConfigureCall";

1187

1188

1191 return "__cudaPushCallConfiguration";

1192

1193

1194 return "cudaConfigureCall";

1195}

1196

1198 return "cudaGetParameterBuffer";

1199}

1200

1202 return "cudaLaunchDevice";

1203}

1204

1205

1206

1210 if (!LambdaInfo)

1211 return;

1212

1213 for (unsigned I = 0; I < Arguments.size(); ++I) {

1214 auto *DeclRef = dyn_cast(Arguments[I]);

1215 if (!DeclRef)

1216 continue;

1217 auto *Variable = dyn_cast(DeclRef->getDecl());

1218 if (!Variable || !Variable->isLocalVarDecl() || !Variable->isConstexpr())

1219 continue;

1220

1221 bool HostByValue = false, HostByRef = false;

1222 bool DeviceByValue = false, DeviceByRef = false;

1223

1226 if (!Callee || I >= Callee->getNumParams())

1227 continue;

1228

1232 continue;

1233

1238

1239 bool IsRef = Callee->getParamDecl(I)->getType()->isReferenceType();

1240 HostByValue |= CoversHost && !IsRef;

1241 HostByRef |= CoversHost && IsRef;

1242 DeviceByValue |= CoversDevice && !IsRef;

1243 DeviceByRef |= CoversDevice && IsRef;

1244 }

1245

1246 if ((HostByValue && DeviceByRef) || (HostByRef && DeviceByValue))

1248 }

1249}

Defines the clang::ASTContext interface.

static bool hasImplicitAttr(const ValueDecl *D)

Defines the clang::Expr interface and subclasses for C++ expressions.

FormatToken * Previous

The previous token in the unwrapped line.

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,...

Definition SemaCUDA.cpp:439

static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)

Definition SemaCUDA.cpp:187

static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, const FunctionDecl &TemplateFD)

Definition SemaCUDA.cpp:1163

static bool hasExplicitAttr(const VarDecl *D)

Definition SemaCUDA.cpp:31

This file declares semantic analysis for CUDA constructs.

FunctionDecl * getcudaGetParameterBufferDecl()

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.

llvm::DenseSet< const FunctionDecl * > CUDAImplicitHostDeviceFunUsedByDevice

Keep track of CUDA/HIP implicit host device functions used on device side in device compilation.

FunctionDecl * getcudaConfigureCallDecl()

FunctionDecl * getcudaLaunchDeviceDecl()

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.

The null pointer literal (C++11 [lex.nullptr])

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.

bool isUserProvided() const

True if this method is user-declared and was not deleted or defaulted on its first declaration.

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.

static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)

Returns a new integer literal with value 'V' and type 'type'.

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.

OverloadCandidateSet - A set of overload candidates, used in C++ overload resolution (C++ 13....

ParsedAttr - Represents a syntactic attribute.

A (possibly-)qualified type.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

bool isConstQualified() const

Determine whether this type is const-qualified.

LangAS getAddressSpace() const

field_range fields() 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.

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

DiagnosticsEngine & getDiagnostics() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

std::string getLaunchDeviceFuncName() const

Return the name of the device kernel launch function.

Definition SemaCUDA.cpp:1201

void PushForceHostDevice()

Increments our count of the number of times we've seen a pragma forcing functions to be host device.

Definition SemaCUDA.cpp:39

void checkAllowedInitializer(VarDecl *VD)

Definition SemaCUDA.cpp:757

void RecordImplicitHostDeviceFuncUsedByDevice(const FunctionDecl *FD)

Record FD if it is a CUDA/HIP implicit host device function used on device side in device compilation...

Definition SemaCUDA.cpp:811

std::string getConfigureFuncName() const

Returns the name of the launch configuration function.

Definition SemaCUDA.cpp:1180

bool PopForceHostDevice()

Decrements our count of the number of times we've seen a pragma forcing functions to be host device.

Definition SemaCUDA.cpp:44

CUDAFunctionTarget IdentifyTarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr=false)

Determines whether the given function is a CUDA device/host/kernel/etc.

Definition SemaCUDA.cpp:212

void maybeAddHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous)

May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, depending on FD and the current co...

Definition SemaCUDA.cpp:845

ExprResult ActOnExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)

Definition SemaCUDA.cpp:52

bool isEmptyConstructor(SourceLocation Loc, CXXConstructorDecl *CD)

Definition SemaCUDA.cpp:611

std::string getGetParameterBufferFuncName() const

Return the name of the parameter buffer allocation function for the device kernel launch.

Definition SemaCUDA.cpp:1197

bool isEmptyDestructor(SourceLocation Loc, CXXDestructorDecl *CD)

Definition SemaCUDA.cpp:649

void checkTargetOverload(FunctionDecl *NewFD, const LookupResult &Previous)

Check whether NewFD is a valid overload for CUDA.

Definition SemaCUDA.cpp:1116

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...

Definition SemaCUDA.cpp:956

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 ...

Definition SemaCUDA.cpp:459

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...

Definition SemaCUDA.cpp:924

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.

Definition SemaCUDA.cpp:987

void inheritTargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD)

Copies target attributes from the template TD to the function FD.

Definition SemaCUDA.cpp:1172

static bool isImplicitHostDeviceFunction(const FunctionDecl *D)

Definition SemaCUDA.cpp:400

void CheckLambdaCapture(CXXMethodDecl *D, const sema::Capture &Capture)

Definition SemaCUDA.cpp:1063

void MaybeAddConstantAttr(VarDecl *VD)

May add implicit CUDAConstantAttr attribute to VD, depending on VD and current compilation settings.

Definition SemaCUDA.cpp:910

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...

Definition SemaCUDA.cpp:406

SemaCUDA(Sema &S)

Definition SemaCUDA.cpp:29

void SetLambdaAttrs(CXXMethodDecl *Method)

Set device or host device attributes on the given lambda operator() method.

Definition SemaCUDA.cpp:1108

CUDAFunctionPreference IdentifyPreference(const FunctionDecl *Caller, const FunctionDecl *Callee)

Identifies relative preference of a given Caller/Callee combination, based on their host/device attri...

Definition SemaCUDA.cpp:312

void recordPotentialODRUsedVariable(MultiExprArg Args, OverloadCandidateSet &CandidateSet)

Record variables that are potentially ODR-used in CUDA/HIP.

Definition SemaCUDA.cpp:1207

@ 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.

Encodes a location in the source.

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.

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

llvm::SmallPtrSet< VarDecl *, 4 > CUDAPotentialODRUsedVars

Variables that are potentially ODR-used in CUDA/HIP.

Defines the clang::TargetInfo interface.

The JSON file list parser is used to communicate input to InstallAPI.

@ Match

This is not an overload because the signature exactly matches an existing declaration.

bool isa(CodeGen::Address addr)

MutableArrayRef< Expr * > MultiExprArg

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.

TemplateSpecializationKind

Describes the kind of template specialization that a particular template specialization declaration r...

@ TSK_ExplicitInstantiationDefinition

This template specialization was instantiated from a template due to an explicit instantiation defini...

@ TSK_ExplicitInstantiationDeclaration

This template specialization was instantiated from a template due to an explicit instantiation declar...

ActionResult< Expr * > ExprResult

OverloadCandidate - A single candidate in an overload set (C++ 13.3).