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