22 #include "llvm/ADT/Optional.h"
23 #include "llvm/ADT/SmallVector.h"
24 using namespace clang;
32 <<
"cudaConfigureCall");
39 return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc,
nullptr,
45 if (D->hasAttr<CUDAInvalidTargetAttr>())
48 if (D->hasAttr<CUDAGlobalAttr>())
51 if (D->hasAttr<CUDADeviceAttr>()) {
52 if (D->hasAttr<CUDAHostAttr>())
55 }
else if (D->hasAttr<CUDAHostAttr>()) {
57 }
else if (D->isImplicit()) {
97 assert(Callee &&
"Callee must be valid.");
119 if (CalleeTarget == CallerTarget ||
145 llvm_unreachable(
"All cases should've been handled by now.");
148 template <
typename T>
151 std::function<
const FunctionDecl *(
const T &)> FetchDecl) {
152 if (Matches.size() <= 1)
156 auto GetCFP = [&](
const T &Match) {
162 Matches.begin(), Matches.end(),
163 [&](
const T &M1,
const T &M2) {
return GetCFP(M1) < GetCFP(M2); }));
167 llvm::remove_if(Matches,
168 [&](
const T &Match) {
return GetCFP(Match) < BestCFP; }),
174 EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
180 EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
189 EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
191 [](
const std::pair<DeclAccessPair, FunctionDecl *> &item) {
213 *ResolvedTarget = Target2;
215 *ResolvedTarget = Target1;
216 }
else if (Target1 != Target2) {
219 *ResolvedTarget = Target1;
240 for (
const auto &B : ClassDecl->
bases()) {
241 if (!B.isVirtual()) {
247 for (
const auto &VB : ClassDecl->
vbases()) {
248 Bases.push_back(&VB);
252 for (
const auto *B : Bases) {
267 if (!SMOR || !SMOR->getMethod()) {
272 if (!InferredTarget.hasValue()) {
273 InferredTarget = BaseMethodTarget;
276 InferredTarget.getValue(), BaseMethodTarget,
277 InferredTarget.getPointer());
278 if (ResolutionError) {
280 Diag(ClassDecl->getLocation(),
281 diag::note_implicit_member_target_infer_collision)
282 << (
unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
284 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
291 for (
const auto *F : ClassDecl->
fields()) {
292 if (F->isInvalidDecl()) {
305 ConstRHS && !F->isMutable(),
311 if (!SMOR || !SMOR->getMethod()) {
317 if (!InferredTarget.hasValue()) {
318 InferredTarget = FieldMethodTarget;
321 InferredTarget.getValue(), FieldMethodTarget,
322 InferredTarget.getPointer());
323 if (ResolutionError) {
325 Diag(ClassDecl->getLocation(),
326 diag::note_implicit_member_target_infer_collision)
327 << (
unsigned)CSM << InferredTarget.getValue()
328 << FieldMethodTarget;
330 MemberDecl->addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
336 if (InferredTarget.hasValue()) {
337 if (InferredTarget.getValue() ==
CFT_Device) {
338 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(
Context));
339 }
else if (InferredTarget.getValue() ==
CFT_Host) {
340 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(
Context));
342 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(
Context));
343 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(
Context));
348 MemberDecl->addAttr(CUDADeviceAttr::CreateImplicit(
Context));
349 MemberDecl->addAttr(CUDAHostAttr::CreateImplicit(
Context));
380 dyn_cast<CXXConstructExpr>(CI->getInit()))
427 ->getBaseElementTypeUnsafe()
428 ->getAsCXXRecordDecl())
446 assert(
getLangOpts().CUDA &&
"May be called only for CUDA compilations.");
448 NewD->
isVariadic() || NewD->hasAttr<CUDAHostAttr>() ||
449 NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>())
454 auto IsMatchingDeviceFn = [&](
NamedDecl *D) {
456 D = Using->getTargetDecl();
458 return OldD && OldD->hasAttr<CUDADeviceAttr>() &&
459 !OldD->hasAttr<CUDAHostAttr>() &&
463 auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
464 if (It != Previous.
end()) {
471 Diag(NewD->getLocation(),
472 diag::err_cuda_unattributed_constexpr_cannot_overload_device)
474 Diag(Match->getLocation(),
475 diag::note_cuda_conflicting_device_function_declared_here);
480 NewD->addAttr(CUDAHostAttr::CreateImplicit(
Context));
481 NewD->addAttr(CUDADeviceAttr::CreateImplicit(
Context));
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl< T > &Matches, std::function< const FunctionDecl *(const T &)> FetchDecl)
A (possibly-)qualified type.
void EraseUnwantedCUDAMatches(const FunctionDecl *Caller, SmallVectorImpl< FunctionDecl * > &Matches)
Finds a function in Matches with highest calling priority from Caller context and erases all function...
const LangOptions & getLangOpts() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, bool ConsiderCudaAttrs=true)
Represents a call to a C++ constructor.
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 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)
SpecialMemberOverloadResult * LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
Defines the clang::Expr interface and subclasses for C++ expressions.
ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false)
ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
SpecialMemberOverloadResult - The overloading result for a special member function.
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
Represents the results of name lookup.
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
field_range fields() const
RecordDecl * getDecl() const
bool isVariadic() const
Whether this function is variadic.
Scope - A scope is a transient data structure that is used while parsing the program.
bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD)
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
bool isDefined(const FunctionDecl *&Definition) const
isDefined - Returns true if the function is defined at all, including a deleted definition.
bool isAbstract() const
Determine whether this class has a pure virtual function.
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.
Represents a C++ destructor within a class.
Defines the clang::Preprocessor interface.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD)
void maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *FD, const LookupResult &Previous)
May add implicit CUDAHostAttr and CUDADeviceAttr attributes to FD, depending on FD and the current co...
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
Encodes a location in the source.
unsigned getNumParams() const
getNumParams - Return the number of parameters this function must have based on its FunctionType...
CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D)
IdentifyCUDATarget - Determine the CUDA compilation target for this function.
Represents a static or instance method of a struct/union/class.
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...
FunctionDecl * getcudaConfigureCallDecl()
bool isDynamicClass() const
A POD class for pairing a NamedDecl* with an access specifier.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
SourceManager & getSourceManager() const
const T * getAs() const
Member-template getAs<specific type>'.
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 isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
A reference to a declared variable, function, enum, etc.
An l-value expression is a reference to an object with independent storage.
NamedDecl - This represents a decl with a name.
bool hasTrivialBody() const
hasTrivialBody - Returns whether the function has a trivial body that does not require any specific c...
base_class_range vbases()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
Represents a shadow declaration introduced into a scope by a (resolved) using declaration.