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

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

140 if (D->hasAttr())

142

143 if (D->hasAttr())

145

146 if (hasAttr(D, IgnoreImplicitHDAttr)) {

147 if (hasAttr(D, IgnoreImplicitHDAttr))

150 } else if (hasAttr(D, IgnoreImplicitHDAttr)) {

152 } else if ((D->isImplicit() || D->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 (D)

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 getASTContext().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 SemaRef.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