1 //===--- SemaCUDA.cpp - Semantic Analysis for CUDA constructs -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// \brief This file implements semantic analysis for CUDA constructs. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/ExprCXX.h" 17 #include "clang/Lex/Preprocessor.h" 18 #include "clang/Sema/Lookup.h" 19 #include "clang/Sema/Sema.h" 20 #include "clang/Sema/SemaDiagnostic.h" 21 #include "clang/Sema/Template.h" 22 #include "llvm/ADT/Optional.h" 23 #include "llvm/ADT/SmallVector.h" 24 using namespace clang; 25 26 void Sema::PushForceCUDAHostDevice() { 27 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 28 ForceCUDAHostDeviceDepth++; 29 } 30 31 bool Sema::PopForceCUDAHostDevice() { 32 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 33 if (ForceCUDAHostDeviceDepth == 0) 34 return false; 35 ForceCUDAHostDeviceDepth--; 36 return true; 37 } 38 39 ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, 40 MultiExprArg ExecConfig, 41 SourceLocation GGGLoc) { 42 FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); 43 if (!ConfigDecl) 44 return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) 45 << "cudaConfigureCall"); 46 QualType ConfigQTy = ConfigDecl->getType(); 47 48 DeclRefExpr *ConfigDR = new (Context) 49 DeclRefExpr(ConfigDecl, false, ConfigQTy, VK_LValue, LLLLoc); 50 MarkFunctionReferenced(LLLLoc, ConfigDecl); 51 52 return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, nullptr, 53 /*IsExecConfig=*/true); 54 } 55 56 /// IdentifyCUDATarget - Determine the CUDA compilation target for this function 57 Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) { 58 if (D->hasAttr<CUDAInvalidTargetAttr>()) 59 return CFT_InvalidTarget; 60 61 if (D->hasAttr<CUDAGlobalAttr>()) 62 return CFT_Global; 63 64 if (D->hasAttr<CUDADeviceAttr>()) { 65 if (D->hasAttr<CUDAHostAttr>()) 66 return CFT_HostDevice; 67 return CFT_Device; 68 } else if (D->hasAttr<CUDAHostAttr>()) { 69 return CFT_Host; 70 } else if (D->isImplicit()) { 71 // Some implicit declarations (like intrinsic functions) are not marked. 72 // Set the most lenient target on them for maximal flexibility. 73 return CFT_HostDevice; 74 } 75 76 return CFT_Host; 77 } 78 79 // * CUDA Call preference table 80 // 81 // F - from, 82 // T - to 83 // Ph - preference in host mode 84 // Pd - preference in device mode 85 // H - handled in (x) 86 // Preferences: N:native, SS:same side, HD:host-device, WS:wrong side, --:never. 87 // 88 // | F | T | Ph | Pd | H | 89 // |----+----+-----+-----+-----+ 90 // | d | d | N | N | (c) | 91 // | d | g | -- | -- | (a) | 92 // | d | h | -- | -- | (e) | 93 // | d | hd | HD | HD | (b) | 94 // | g | d | N | N | (c) | 95 // | g | g | -- | -- | (a) | 96 // | g | h | -- | -- | (e) | 97 // | g | hd | HD | HD | (b) | 98 // | h | d | -- | -- | (e) | 99 // | h | g | N | N | (c) | 100 // | h | h | N | N | (c) | 101 // | h | hd | HD | HD | (b) | 102 // | hd | d | WS | SS | (d) | 103 // | hd | g | SS | -- |(d/a)| 104 // | hd | h | SS | WS | (d) | 105 // | hd | hd | HD | HD | (b) | 106 107 Sema::CUDAFunctionPreference 108 Sema::IdentifyCUDAPreference(const FunctionDecl *Caller, 109 const FunctionDecl *Callee) { 110 assert(Callee && "Callee must be valid."); 111 CUDAFunctionTarget CalleeTarget = IdentifyCUDATarget(Callee); 112 CUDAFunctionTarget CallerTarget = 113 (Caller != nullptr) ? IdentifyCUDATarget(Caller) : Sema::CFT_Host; 114 115 // If one of the targets is invalid, the check always fails, no matter what 116 // the other target is. 117 if (CallerTarget == CFT_InvalidTarget || CalleeTarget == CFT_InvalidTarget) 118 return CFP_Never; 119 120 // (a) Can't call global from some contexts until we support CUDA's 121 // dynamic parallelism. 122 if (CalleeTarget == CFT_Global && 123 (CallerTarget == CFT_Global || CallerTarget == CFT_Device || 124 (CallerTarget == CFT_HostDevice && getLangOpts().CUDAIsDevice))) 125 return CFP_Never; 126 127 // (b) Calling HostDevice is OK for everyone. 128 if (CalleeTarget == CFT_HostDevice) 129 return CFP_HostDevice; 130 131 // (c) Best case scenarios 132 if (CalleeTarget == CallerTarget || 133 (CallerTarget == CFT_Host && CalleeTarget == CFT_Global) || 134 (CallerTarget == CFT_Global && CalleeTarget == CFT_Device)) 135 return CFP_Native; 136 137 // (d) HostDevice behavior depends on compilation mode. 138 if (CallerTarget == CFT_HostDevice) { 139 // It's OK to call a compilation-mode matching function from an HD one. 140 if ((getLangOpts().CUDAIsDevice && CalleeTarget == CFT_Device) || 141 (!getLangOpts().CUDAIsDevice && 142 (CalleeTarget == CFT_Host || CalleeTarget == CFT_Global))) 143 return CFP_SameSide; 144 145 // Calls from HD to non-mode-matching functions (i.e., to host functions 146 // when compiling in device mode or to device functions when compiling in 147 // host mode) are allowed at the sema level, but eventually rejected if 148 // they're ever codegened. TODO: Reject said calls earlier. 149 return CFP_WrongSide; 150 } 151 152 // (e) Calling across device/host boundary is not something you should do. 153 if ((CallerTarget == CFT_Host && CalleeTarget == CFT_Device) || 154 (CallerTarget == CFT_Device && CalleeTarget == CFT_Host) || 155 (CallerTarget == CFT_Global && CalleeTarget == CFT_Host)) 156 return CFP_Never; 157 158 llvm_unreachable("All cases should've been handled by now."); 159 } 160 161 void Sema::EraseUnwantedCUDAMatches( 162 const FunctionDecl *Caller, 163 SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) { 164 if (Matches.size() <= 1) 165 return; 166 167 using Pair = std::pair<DeclAccessPair, FunctionDecl*>; 168 169 // Gets the CUDA function preference for a call from Caller to Match. 170 auto GetCFP = [&](const Pair &Match) { 171 return IdentifyCUDAPreference(Caller, Match.second); 172 }; 173 174 // Find the best call preference among the functions in Matches. 175 CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( 176 Matches.begin(), Matches.end(), 177 [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); })); 178 179 // Erase all functions with lower priority. 180 Matches.erase( 181 llvm::remove_if( 182 Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }), 183 Matches.end()); 184 } 185 186 /// When an implicitly-declared special member has to invoke more than one 187 /// base/field special member, conflicts may occur in the targets of these 188 /// members. For example, if one base's member __host__ and another's is 189 /// __device__, it's a conflict. 190 /// This function figures out if the given targets \param Target1 and 191 /// \param Target2 conflict, and if they do not it fills in 192 /// \param ResolvedTarget with a target that resolves for both calls. 193 /// \return true if there's a conflict, false otherwise. 194 static bool 195 resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, 196 Sema::CUDAFunctionTarget Target2, 197 Sema::CUDAFunctionTarget *ResolvedTarget) { 198 // Only free functions and static member functions may be global. 199 assert(Target1 != Sema::CFT_Global); 200 assert(Target2 != Sema::CFT_Global); 201 202 if (Target1 == Sema::CFT_HostDevice) { 203 *ResolvedTarget = Target2; 204 } else if (Target2 == Sema::CFT_HostDevice) { 205 *ResolvedTarget = Target1; 206 } else if (Target1 != Target2) { 207 return true; 208 } else { 209 *ResolvedTarget = Target1; 210 } 211 212 return false; 213 } 214 215 bool Sema::inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, 216 CXXSpecialMember CSM, 217 CXXMethodDecl *MemberDecl, 218 bool ConstRHS, 219 bool Diagnose) { 220 llvm::Optional<CUDAFunctionTarget> InferredTarget; 221 222 // We're going to invoke special member lookup; mark that these special 223 // members are called from this one, and not from its caller. 224 ContextRAII MethodContext(*this, MemberDecl); 225 226 // Look for special members in base classes that should be invoked from here. 227 // Infer the target of this member base on the ones it should call. 228 // Skip direct and indirect virtual bases for abstract classes. 229 llvm::SmallVector<const CXXBaseSpecifier *, 16> Bases; 230 for (const auto &B : ClassDecl->bases()) { 231 if (!B.isVirtual()) { 232 Bases.push_back(&B); 233 } 234 } 235 236 if (!ClassDecl->isAbstract()) { 237 for (const auto &VB : ClassDecl->vbases()) { 238 Bases.push_back(&VB); 239 } 240 } 241 242 for (const auto *B : Bases) { 243 const RecordType *BaseType = B->getType()->getAs<RecordType>(); 244 if (!BaseType) { 245 continue; 246 } 247 248 CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); 249 Sema::SpecialMemberOverloadResult *SMOR = 250 LookupSpecialMember(BaseClassDecl, CSM, 251 /* ConstArg */ ConstRHS, 252 /* VolatileArg */ false, 253 /* RValueThis */ false, 254 /* ConstThis */ false, 255 /* VolatileThis */ false); 256 257 if (!SMOR || !SMOR->getMethod()) { 258 continue; 259 } 260 261 CUDAFunctionTarget BaseMethodTarget = IdentifyCUDATarget(SMOR->getMethod()); 262 if (!InferredTarget.hasValue()) { 263 InferredTarget = BaseMethodTarget; 264 } else { 265 bool ResolutionError = resolveCalleeCUDATargetConflict( 266 InferredTarget.getValue(), BaseMethodTarget, 267 InferredTarget.getPointer()); 268 if (ResolutionError) { 269 if (Diagnose) { 270 Diag(ClassDecl->getLocation(), 271 diag::note_implicit_member_target_infer_collision) 272 << (unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget; 273 } 274 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); 275 return true; 276 } 277 } 278 } 279 280 // Same as for bases, but now for special members of fields. 281 for (const auto *F : ClassDecl->fields()) { 282 if (F->isInvalidDecl()) { 283 continue; 284 } 285 286 const RecordType *FieldType = 287 Context.getBaseElementType(F->getType())->getAs<RecordType>(); 288 if (!FieldType) { 289 continue; 290 } 291 292 CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(FieldType->getDecl()); 293 Sema::SpecialMemberOverloadResult *SMOR = 294 LookupSpecialMember(FieldRecDecl, CSM, 295 /* ConstArg */ ConstRHS && !F->isMutable(), 296 /* VolatileArg */ false, 297 /* RValueThis */ false, 298 /* ConstThis */ false, 299 /* VolatileThis */ false); 300 301 if (!SMOR || !SMOR->getMethod()) { 302 continue; 303 } 304 305 CUDAFunctionTarget FieldMethodTarget = 306 IdentifyCUDATarget(SMOR->getMethod()); 307 if (!InferredTarget.hasValue()) { 308 InferredTarget = FieldMethodTarget; 309 } else { 310 bool ResolutionError = resolveCalleeCUDATargetConflict( 311 InferredTarget.getValue(), FieldMethodTarget, 312 InferredTarget.getPointer()); 313 if (ResolutionError) { 314 if (Diagnose) { 315 Diag(ClassDecl->getLocation(), 316 diag::note_implicit_member_target_infer_collision) 317 << (unsigned)CSM << InferredTarget.getValue() 318 << FieldMethodTarget; 319 } 320 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(Context)); 321 return true; 322 } 323 } 324 } 325 326 if (InferredTarget.hasValue()) { 327 if (InferredTarget.getValue() == CFT_Device) { 328 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 329 } else if (InferredTarget.getValue() == CFT_Host) { 330 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context)); 331 } else { 332 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 333 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context)); 334 } 335 } else { 336 // If no target was inferred, mark this member as __host__ __device__; 337 // it's the least restrictive option that can be invoked from any target. 338 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 339 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(Context)); 340 } 341 342 return false; 343 } 344 345 bool Sema::isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD) { 346 if (!CD->isDefined() && CD->isTemplateInstantiation()) 347 InstantiateFunctionDefinition(Loc, CD->getFirstDecl()); 348 349 // (E.2.3.1, CUDA 7.5) A constructor for a class type is considered 350 // empty at a point in the translation unit, if it is either a 351 // trivial constructor 352 if (CD->isTrivial()) 353 return true; 354 355 // ... or it satisfies all of the following conditions: 356 // The constructor function has been defined. 357 // The constructor function has no parameters, 358 // and the function body is an empty compound statement. 359 if (!(CD->hasTrivialBody() && CD->getNumParams() == 0)) 360 return false; 361 362 // Its class has no virtual functions and no virtual base classes. 363 if (CD->getParent()->isDynamicClass()) 364 return false; 365 366 // The only form of initializer allowed is an empty constructor. 367 // This will recursively check all base classes and member initializers 368 if (!llvm::all_of(CD->inits(), [&](const CXXCtorInitializer *CI) { 369 if (const CXXConstructExpr *CE = 370 dyn_cast<CXXConstructExpr>(CI->getInit())) 371 return isEmptyCudaConstructor(Loc, CE->getConstructor()); 372 return false; 373 })) 374 return false; 375 376 return true; 377 } 378 379 bool Sema::isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *DD) { 380 // No destructor -> no problem. 381 if (!DD) 382 return true; 383 384 if (!DD->isDefined() && DD->isTemplateInstantiation()) 385 InstantiateFunctionDefinition(Loc, DD->getFirstDecl()); 386 387 // (E.2.3.1, CUDA 7.5) A destructor for a class type is considered 388 // empty at a point in the translation unit, if it is either a 389 // trivial constructor 390 if (DD->isTrivial()) 391 return true; 392 393 // ... or it satisfies all of the following conditions: 394 // The destructor function has been defined. 395 // and the function body is an empty compound statement. 396 if (!DD->hasTrivialBody()) 397 return false; 398 399 const CXXRecordDecl *ClassDecl = DD->getParent(); 400 401 // Its class has no virtual functions and no virtual base classes. 402 if (ClassDecl->isDynamicClass()) 403 return false; 404 405 // Only empty destructors are allowed. This will recursively check 406 // destructors for all base classes... 407 if (!llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &BS) { 408 if (CXXRecordDecl *RD = BS.getType()->getAsCXXRecordDecl()) 409 return isEmptyCudaDestructor(Loc, RD->getDestructor()); 410 return true; 411 })) 412 return false; 413 414 // ... and member fields. 415 if (!llvm::all_of(ClassDecl->fields(), [&](const FieldDecl *Field) { 416 if (CXXRecordDecl *RD = Field->getType() 417 ->getBaseElementTypeUnsafe() 418 ->getAsCXXRecordDecl()) 419 return isEmptyCudaDestructor(Loc, RD->getDestructor()); 420 return true; 421 })) 422 return false; 423 424 return true; 425 } 426 427 // With -fcuda-host-device-constexpr, an unattributed constexpr function is 428 // treated as implicitly __host__ __device__, unless: 429 // * it is a variadic function (device-side variadic functions are not 430 // allowed), or 431 // * a __device__ function with this signature was already declared, in which 432 // case in which case we output an error, unless the __device__ decl is in a 433 // system header, in which case we leave the constexpr function unattributed. 434 // 435 // In addition, all function decls are treated as __host__ __device__ when 436 // ForceCUDAHostDeviceDepth > 0 (corresponding to code within a 437 // #pragma clang force_cuda_host_device_begin/end 438 // pair). 439 void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD, 440 const LookupResult &Previous) { 441 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 442 443 if (ForceCUDAHostDeviceDepth > 0) { 444 if (!NewD->hasAttr<CUDAHostAttr>()) 445 NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); 446 if (!NewD->hasAttr<CUDADeviceAttr>()) 447 NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 448 return; 449 } 450 451 if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() || 452 NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() || 453 NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>()) 454 return; 455 456 // Is D a __device__ function with the same signature as NewD, ignoring CUDA 457 // attributes? 458 auto IsMatchingDeviceFn = [&](NamedDecl *D) { 459 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(D)) 460 D = Using->getTargetDecl(); 461 FunctionDecl *OldD = D->getAsFunction(); 462 return OldD && OldD->hasAttr<CUDADeviceAttr>() && 463 !OldD->hasAttr<CUDAHostAttr>() && 464 !IsOverload(NewD, OldD, /* UseMemberUsingDeclRules = */ false, 465 /* ConsiderCudaAttrs = */ false); 466 }; 467 auto It = llvm::find_if(Previous, IsMatchingDeviceFn); 468 if (It != Previous.end()) { 469 // We found a __device__ function with the same name and signature as NewD 470 // (ignoring CUDA attrs). This is an error unless that function is defined 471 // in a system header, in which case we simply return without making NewD 472 // host+device. 473 NamedDecl *Match = *It; 474 if (!getSourceManager().isInSystemHeader(Match->getLocation())) { 475 Diag(NewD->getLocation(), 476 diag::err_cuda_unattributed_constexpr_cannot_overload_device) 477 << NewD->getName(); 478 Diag(Match->getLocation(), 479 diag::note_cuda_conflicting_device_function_declared_here); 480 } 481 return; 482 } 483 484 NewD->addAttr(CUDAHostAttr::CreateImplicit(Context)); 485 NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 486 } 487 488 bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) { 489 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 490 assert(Callee && "Callee may not be null."); 491 FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); 492 if (!Caller) 493 return true; 494 495 Sema::CUDAFunctionPreference Pref = IdentifyCUDAPreference(Caller, Callee); 496 if (Pref == Sema::CFP_Never) { 497 Diag(Loc, diag::err_ref_bad_target) << IdentifyCUDATarget(Callee) << Callee 498 << IdentifyCUDATarget(Caller); 499 Diag(Callee->getLocation(), diag::note_previous_decl) << Callee; 500 return false; 501 } 502 503 // Insert into LocsWithCUDADeferredDiags to avoid emitting duplicate deferred 504 // diagnostics for the same location. Duplicate deferred diags are otherwise 505 // tricky to avoid, because, unlike with regular errors, sema checking 506 // proceeds unhindered when we omit a deferred diagnostic. 507 if (Pref == Sema::CFP_WrongSide && 508 LocsWithCUDACallDeferredDiags.insert(Loc.getRawEncoding()).second) { 509 // We have to do this odd dance to create our PartialDiagnostic because we 510 // want its storage to be allocated with operator new, not in an arena. 511 PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()}; 512 ErrPD.Reset(diag::err_ref_bad_target); 513 ErrPD << IdentifyCUDATarget(Callee) << Callee << IdentifyCUDATarget(Caller); 514 Caller->addDeferredDiag({Loc, std::move(ErrPD)}); 515 516 PartialDiagnostic NotePD{PartialDiagnostic::NullDiagnostic()}; 517 NotePD.Reset(diag::note_previous_decl); 518 NotePD << Callee; 519 Caller->addDeferredDiag({Callee->getLocation(), std::move(NotePD)}); 520 521 // This is not immediately an error, so return true. The deferred errors 522 // will be emitted if and when Caller is codegen'ed. 523 return true; 524 } 525 return true; 526 } 527 528 bool Sema::CheckCUDAExceptionExpr(SourceLocation Loc, StringRef ExprTy) { 529 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 530 FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext); 531 if (!CurFn) 532 return true; 533 CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn); 534 535 // Raise an error immediately if this is a __global__ or __device__ function. 536 // If it's a __host__ __device__ function, enqueue a deferred error which will 537 // be emitted if the function is codegen'ed for device. 538 if (Target == CFT_Global || Target == CFT_Device) { 539 Diag(Loc, diag::err_cuda_device_exceptions) << ExprTy << Target << CurFn; 540 return false; 541 } 542 if (Target == CFT_HostDevice && getLangOpts().CUDAIsDevice) { 543 PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()}; 544 ErrPD.Reset(diag::err_cuda_device_exceptions); 545 ErrPD << ExprTy << Target << CurFn; 546 CurFn->addDeferredDiag({Loc, std::move(ErrPD)}); 547 return false; 548 } 549 return true; 550 } 551 552 bool Sema::CheckCUDAVLA(SourceLocation Loc) { 553 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 554 FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext); 555 if (!CurFn) 556 return true; 557 CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn); 558 if (Target == CFT_Global || Target == CFT_Device) { 559 Diag(Loc, diag::err_cuda_vla) << Target; 560 return false; 561 } 562 if (Target == CFT_HostDevice && getLangOpts().CUDAIsDevice) { 563 PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()}; 564 ErrPD.Reset(diag::err_cuda_vla); 565 ErrPD << Target; 566 CurFn->addDeferredDiag({Loc, std::move(ErrPD)}); 567 return false; 568 } 569 return true; 570 } 571 572 void Sema::CUDASetLambdaAttrs(CXXMethodDecl *Method) { 573 assert(getLangOpts().CUDA && "Should only be called during CUDA compilation"); 574 if (Method->hasAttr<CUDAHostAttr>() || Method->hasAttr<CUDADeviceAttr>()) 575 return; 576 FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext); 577 if (!CurFn) 578 return; 579 CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn); 580 if (Target == CFT_Global || Target == CFT_Device) { 581 Method->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 582 } else if (Target == CFT_HostDevice) { 583 Method->addAttr(CUDADeviceAttr::CreateImplicit(Context)); 584 Method->addAttr(CUDAHostAttr::CreateImplicit(Context)); 585 } 586 } 587