19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/SmallVector.h"
21 using namespace clang;
29 <<
"cudaConfigureCall");
36 return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc,
nullptr,
42 if (D->
hasAttr<CUDAInvalidTargetAttr>())
45 if (D->
hasAttr<CUDAGlobalAttr>())
48 if (D->
hasAttr<CUDADeviceAttr>()) {
52 }
else if (D->
hasAttr<CUDAHostAttr>()) {
95 "Should not be called w/o enabled target overloads.");
97 assert(Callee &&
"Callee must be valid.");
115 if (CalleeTarget == CallerTarget ||
139 : QuestionableResult;
146 return QuestionableResult;
148 llvm_unreachable(
"All cases should've been handled by now.");
193 if (!InDeviceMode && CalleeTarget !=
CFT_Host)
195 if (InDeviceMode && CalleeTarget !=
CFT_Device) {
201 diag::warn_host_calls_from_host_device)
213 template <
typename T,
typename FetchDeclFn>
216 FetchDeclFn FetchDecl) {
218 "Should not be called w/o enabled target overloads.");
219 if (Matches.size() <= 1)
224 for (
auto const &Match : Matches) {
231 for (
unsigned I = 0, N = Matches.size();
I != N;)
233 Matches[
I] = Matches[--N];
242 EraseUnwantedCUDAMatchesImpl<FunctionDecl *>(
248 EraseUnwantedCUDAMatchesImpl<DeclAccessPair>(
257 EraseUnwantedCUDAMatchesImpl<std::pair<DeclAccessPair, FunctionDecl *>>(
259 [](
const std::pair<DeclAccessPair, FunctionDecl *> &item) {
284 *ResolvedTarget = Target2;
286 *ResolvedTarget = Target1;
287 }
else if (Target1 != Target2) {
290 *ResolvedTarget = Target1;
311 for (
const auto &B : ClassDecl->
bases()) {
312 if (!B.isVirtual()) {
318 for (
const auto &VB : ClassDecl->
vbases()) {
319 Bases.push_back(&VB);
323 for (
const auto *B : Bases) {
338 if (!SMOR || !SMOR->getMethod()) {
343 if (!InferredTarget.hasValue()) {
344 InferredTarget = BaseMethodTarget;
347 InferredTarget.getValue(), BaseMethodTarget,
348 InferredTarget.getPointer());
349 if (ResolutionError) {
352 diag::note_implicit_member_target_infer_collision)
353 << (
unsigned)CSM << InferredTarget.getValue() << BaseMethodTarget;
355 MemberDecl->
addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
362 for (
const auto *F : ClassDecl->
fields()) {
363 if (F->isInvalidDecl()) {
376 ConstRHS && !F->isMutable(),
382 if (!SMOR || !SMOR->getMethod()) {
388 if (!InferredTarget.hasValue()) {
389 InferredTarget = FieldMethodTarget;
392 InferredTarget.getValue(), FieldMethodTarget,
393 InferredTarget.getPointer());
394 if (ResolutionError) {
397 diag::note_implicit_member_target_infer_collision)
398 << (
unsigned)CSM << InferredTarget.getValue()
399 << FieldMethodTarget;
401 MemberDecl->
addAttr(CUDAInvalidTargetAttr::CreateImplicit(
Context));
407 if (InferredTarget.hasValue()) {
408 if (InferredTarget.getValue() ==
CFT_Device) {
410 }
else if (InferredTarget.getValue() ==
CFT_Host) {
Defines the clang::ASTContext interface.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
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.
static void EraseUnwantedCUDAMatchesImpl(Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl< T > &Matches, FetchDeclFn FetchDecl)
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 ...
SpecialMemberOverloadResult * LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
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.
SpecialMemberOverloadResult - The overloading result for a special member function.
ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, MultiExprArg ExecConfig, SourceLocation GGGLoc)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
field_range fields() const
RecordDecl * getDecl() const
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
Scope - A scope is a transient data structure that is used while parsing the program.
detail::InMemoryDirectory::const_iterator I
bool isAbstract() const
Determine whether this class has a pure virtual function.
CXXSpecialMember
Kinds of C++ special members.
Sema - This implements semantic analysis and AST building for C.
bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee)
Defines the clang::Preprocessor interface.
Encodes a location in the source.
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()
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...
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++ struct/union/class.
A reference to a declared variable, function, enum, etc.
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool OdrUse=true)
Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2, C99 6.9p3)
An l-value expression is a reference to an object with independent storage.
SourceLocation getLocation() const
base_class_range vbases()
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.