23 #include "llvm/ADT/Optional.h" 24 #include "llvm/ADT/SmallVector.h" 25 using namespace clang;
28 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
29 ForceCUDAHostDeviceDepth++;
33 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
34 if (ForceCUDAHostDeviceDepth == 0)
36 ForceCUDAHostDeviceDepth--;
53 return BuildCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc,
nullptr,
59 bool HasHostAttr =
false;
60 bool HasDeviceAttr =
false;
61 bool HasGlobalAttr =
false;
62 bool HasInvalidTargetAttr =
false;
64 switch (AL.getKind()) {
65 case ParsedAttr::AT_CUDAGlobal:
68 case ParsedAttr::AT_CUDAHost:
71 case ParsedAttr::AT_CUDADevice:
74 case ParsedAttr::AT_CUDAInvalidTarget:
75 HasInvalidTargetAttr =
true;
82 if (HasInvalidTargetAttr)
88 if (HasHostAttr && HasDeviceAttr)
100 return isa<A>(Attribute) &&
101 !(IgnoreImplicitAttr && Attribute->isImplicit());
107 bool IgnoreImplicitHDAttr) {
112 if (D->
hasAttr<CUDAInvalidTargetAttr>())
115 if (D->
hasAttr<CUDAGlobalAttr>())
118 if (hasAttr<CUDADeviceAttr>(D, IgnoreImplicitHDAttr)) {
119 if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr))
122 }
else if (hasAttr<CUDAHostAttr>(D, IgnoreImplicitHDAttr)) {
124 }
else if (D->
isImplicit() && !IgnoreImplicitHDAttr) {
164 assert(Callee &&
"Callee must be valid.");
184 if (CalleeTarget == CallerTarget ||
210 llvm_unreachable(
"All cases should've been handled by now.");
216 if (Matches.size() <= 1)
219 using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
222 auto GetCFP = [&](
const Pair &Match) {
228 Matches.begin(), Matches.end(),
229 [&](
const Pair &M1,
const Pair &M2) {
return GetCFP(M1) < GetCFP(M2); }));
232 llvm::erase_if(Matches,
233 [&](
const Pair &Match) {
return GetCFP(Match) < BestCFP; });
253 *ResolvedTarget = Target2;
255 *ResolvedTarget = Target1;
256 }
else if (Target1 != Target2) {
259 *ResolvedTarget = Target1;
274 bool HasH = MemberDecl->
hasAttr<CUDAHostAttr>();
275 bool HasD = MemberDecl->
hasAttr<CUDADeviceAttr>();
276 bool HasExplicitAttr =
277 (HasD && !MemberDecl->
getAttr<CUDADeviceAttr>()->isImplicit()) ||
278 (HasH && !MemberDecl->
getAttr<CUDAHostAttr>()->isImplicit());
279 if (!InClass || HasExplicitAttr)
292 for (
const auto &B : ClassDecl->
bases()) {
293 if (!B.isVirtual()) {
299 for (
const auto &VB : ClassDecl->
vbases()) {
300 Bases.push_back(&VB);
304 for (
const auto *B : Bases) {
319 if (!SMOR.getMethod())
323 if (!InferredTarget.hasValue()) {
324 InferredTarget = BaseMethodTarget;
327 InferredTarget.getValue(), BaseMethodTarget,
328 InferredTarget.getPointer());
329 if (ResolutionError) {
332 diag::note_implicit_member_target_infer_collision)
333 << (
unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
335 MemberDecl->
addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
342 for (
const auto *F : ClassDecl->
fields()) {
343 if (F->isInvalidDecl()) {
356 ConstRHS && !F->isMutable(),
362 if (!SMOR.getMethod())
367 if (!InferredTarget.hasValue()) {
368 InferredTarget = FieldMethodTarget;
371 InferredTarget.getValue(), FieldMethodTarget,
372 InferredTarget.getPointer());
373 if (ResolutionError) {
376 diag::note_implicit_member_target_infer_collision)
377 << (
unsigned)CSM << InferredTarget.getValue()
378 << FieldMethodTarget;
380 MemberDecl->
addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
389 bool NeedsH =
true, NeedsD =
true;
390 if (InferredTarget.hasValue()) {
393 else if (InferredTarget.getValue() ==
CFT_Host)
432 dyn_cast<CXXConstructExpr>(CI->getInit()))
479 ->getBaseElementTypeUnsafe()
480 ->getAsCXXRecordDecl())
493 if (VD->
hasAttr<CUDADeviceAttr>() || VD->
hasAttr<CUDAConstantAttr>() ||
494 VD->
hasAttr<CUDASharedAttr>()) {
498 bool AllowedInit =
false;
506 (VD->
hasAttr<CUDADeviceAttr>() || VD->
hasAttr<CUDAConstantAttr>()))
518 ? diag::err_shared_var_init
519 : diag::err_dynamic_var_init)
528 InitFn = CE->getConstructor();
529 }
else if (
const CallExpr *CE = dyn_cast<CallExpr>(Init)) {
530 InitFn = CE->getDirectCallee();
536 << InitFnTarget << InitFn;
558 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
560 if (ForceCUDAHostDeviceDepth > 0) {
561 if (!NewD->
hasAttr<CUDAHostAttr>())
563 if (!NewD->
hasAttr<CUDADeviceAttr>())
570 NewD->
hasAttr<CUDADeviceAttr>() || NewD->
hasAttr<CUDAGlobalAttr>())
575 auto IsMatchingDeviceFn = [&](
NamedDecl *D) {
577 D = Using->getTargetDecl();
579 return OldD && OldD->
hasAttr<CUDADeviceAttr>() &&
580 !OldD->
hasAttr<CUDAHostAttr>() &&
584 auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
585 if (It != Previous.
end()) {
593 diag::err_cuda_unattributed_constexpr_cannot_overload_device)
596 diag::note_cuda_conflicting_device_function_declared_here);
607 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
635 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
660 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
661 assert(Callee &&
"Callee may not be null.");
664 if (ExprEvalCtx.isUnevaluated() || ExprEvalCtx.isConstantEvaluated())
675 bool CallerKnownEmitted =
677 if (CallerKnownEmitted) {
697 CallerKnownEmitted] {
702 assert(Caller &&
"WrongSide calls require a non-null caller");
733 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
734 if (Method->
hasAttr<CUDAHostAttr>() || Method->
hasAttr<CUDADeviceAttr>())
750 assert(
getLangOpts().
CUDA &&
"Should only be called during CUDA compilation");
763 if (NewTarget != OldTarget &&
769 << NewTarget << NewFD->
getDeclName() << OldTarget << OldFD;
770 Diag(OldFD->getLocation(), diag::note_previous_declaration);
777 template <
typename AttrTy>
780 if (AttrTy *Attribute = TemplateFD.
getAttr<AttrTy>()) {
781 AttrTy *Clone = Attribute->clone(S.
Context);
782 Clone->setInherited(
true);
790 copyAttrIfPresent<CUDAGlobalAttr>(*
this, FD, TemplateFD);
791 copyAttrIfPresent<CUDAHostAttr>(*
this, FD, TemplateFD);
792 copyAttrIfPresent<CUDADeviceAttr>(*
this, FD, TemplateFD);
797 return getLangOpts().HIPUseNewLaunchAPI ?
"__hipPushCallConfiguration" 798 :
"hipConfigureCall";
803 return "__cudaPushCallConfiguration";
806 return "cudaConfigureCall";
Defines the clang::ASTContext interface.
Represents a function declaration or definition.
A (possibly-)qualified type.
Emit the diagnostic immediately, and, if it's a warning or error, also emit a call stack showing how ...
bool CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee)
Check whether we're allowed to call Callee from the current context.
FunctionEmissionStatus getEmissionStatus(FunctionDecl *Decl)
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Represents a call to a C++ constructor.
const TargetInfo & getTargetInfo() const
bool isDefined(const FunctionDecl *&Definition) const
Returns true if the function has a definition that does not need to be instantiated.
bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, CXXSpecialMember 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 ...
Represents a C++ constructor within a class.
void maybeAddCUDAHostDeviceAttrs(FunctionDecl *FD, const LookupResult &Previous)
May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, depending on FD and the current co...
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, C99 6.9p3)
bool PopForceCUDAHostDevice()
Decrements our count of the number of times we've seen a pragma forcing functions to be host device...
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
bool isInvalidDecl() const
Defines the clang::Expr interface and subclasses for C++ expressions.
std::string getCudaConfigureFuncName() const
Returns the name of the launch configuration function.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
bool hasTrivialBody() const
Returns whether the function has a trivial body that does not require any specific codegen...
field_range fields() const
void CUDASetLambdaAttrs(CXXMethodDecl *Method)
Set device or host device attributes on the given lambda operator() method.
Represents a member of a struct/union/class.
bool isReferenceType() const
CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr=false)
Determines whether the given function is a CUDA device/host/kernel/etc.
SpecialMemberOverloadResult - The overloading result for a special member function.
DeviceDiagBuilder CUDADiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)
Creates a DeviceDiagBuilder that emits the diagnostic if the current context is "used as device code"...
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
Represents the results of name lookup.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD)
const LangOptions & getLangOpts() const
bool isAbstract() const
Determine whether this class has a pure virtual function.
const LangOptions & LangOpts
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.
CXXSpecialMember
Kinds of C++ special members.
Sema - This implements semantic analysis and AST building for C.
bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, bool ConsiderCudaAttrs=true, bool ConsiderRequiresClauses=true)
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isDynamicClass() const
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
llvm::DenseSet< FunctionDeclAndLoc > LocsWithCUDACallDiags
FunctionDecls and SourceLocations for which CheckCUDACall has emitted a (maybe deferred) "bad call" d...
This represents one expression.
void PushForceCUDAHostDevice()
Increments our count of the number of times we've seen a pragma forcing functions to be host device...
bool isVariadic() const
Whether this function is variadic.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee)
Represents a C++ destructor within a class.
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Defines the clang::Preprocessor interface.
bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD)
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
RecordDecl * getDecl() const
void EraseUnwantedCUDAMatches(const FunctionDecl *Caller, SmallVectorImpl< std::pair< DeclAccessPair, FunctionDecl *>> &Matches)
Finds a function in Matches with highest calling priority from Caller context and erases all function...
const llvm::VersionTuple & getSDKVersion() const
void checkAllowedCUDAInitializer(VarDecl *VD)
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Encodes a location in the source.
Diagnostic builder for CUDA/OpenMP devices errors which may or may not be deferred.
ParsedAttr - Represents a syntactic attribute.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
Represents a static or instance method of a struct/union/class.
static bool hasAttr(const FunctionDecl *D, bool IgnoreImplicitAttr)
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
static bool resolveCalleeCUDATargetConflict(Sema::CUDAFunctionTarget Target1, Sema::CUDAFunctionTarget Target2, Sema::CUDAFunctionTarget *ResolvedTarget)
When an implicitly-declared special member has to invoke more than one base/field special member...
void markKnownEmitted(Sema &S, FunctionDecl *OrigCaller, FunctionDecl *OrigCallee, SourceLocation OrigLoc, const llvm::function_ref< bool(Sema &, FunctionDecl *)> IsKnownEmitted)
Indicate that this function (and thus everything it transtively calls) will be codegen'ed, and emit any deferred diagnostics on this function and its (transitive) callees.
bool CudaFeatureEnabled(llvm::VersionTuple, CudaFeature)
FunctionDecl * getcudaConfigureCallDecl()
Create a deferred diagnostic, which is emitted only if the function it's attached to is codegen'ed...
CUDAFunctionTarget CurrentCUDATarget()
Gets the CUDA target for the current context.
Dataflow Directional Tag Classes.
const Expr * getInit() const
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined...
Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
void checkCUDATargetOverload(FunctionDecl *NewFD, const LookupResult &Previous)
Check whether NewFD is a valid overload for CUDA.
SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
CUDAFunctionPreference IdentifyCUDAPreference(const FunctionDecl *Caller, const FunctionDecl *Callee)
Identifies relative preference of a given Caller/Callee combination, based on their host/device attri...
Represents a C++ base or member initializer.
bool isConstantInitializer(ASTContext &Ctx, bool ForRef, const Expr **Culprit=nullptr) const
isConstantInitializer - Returns true if this expression can be emitted to IR as a constant...
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
SmallVector< ExpressionEvaluationContextRecord, 8 > ExprEvalContexts
A stack of expression evaluation contexts.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
SourceManager & getSourceManager() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A reference to a declared variable, function, enum, etc.
An l-value expression is a reference to an object with independent storage.
void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD)
Copies target attributes from the template TD to the function FD.
This represents a decl that may have a name.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
static void copyAttrIfPresent(Sema &S, FunctionDecl *FD, const FunctionDecl &TemplateFD)
base_class_range vbases()
Declaration of a template function.
Attr - This represents one attribute.
SourceLocation getLocation() const
llvm::DenseMap< CanonicalDeclPtr< FunctionDecl >, llvm::MapVector< CanonicalDeclPtr< FunctionDecl >, SourceLocation > > DeviceCallGraph
A partial call graph maintained during CUDA/OpenMP device code compilation to support deferred diagno...
Represents a shadow declaration introduced into a scope by a (resolved) using declaration.
DeviceDiagBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID)
Creates a DeviceDiagBuilder that emits the diagnostic if the current context is "used as host code"...