[OpenACC] Implement 'cache' construct AST/Sema
This statement level construct takes no clauses and has no associated statement, and simply labels a number of array elements as valid for caching. The implementation here is pretty simple, but it is a touch of a special case for parsing, so the parsing code reflects that.
This commit is contained in:
@@ -2214,7 +2214,11 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_OpenACCAtomicConstruct = 332,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OpenACCAtomicConstruct,
|
||||
/** OpenACC cache Construct.
|
||||
*/
|
||||
CXCursor_OpenACCCacheConstruct = 333,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OpenACCCacheConstruct,
|
||||
|
||||
/**
|
||||
* Cursor that represents the translation unit itself.
|
||||
|
||||
@@ -4113,6 +4113,10 @@ DEF_TRAVERSE_STMT(OpenACCUpdateConstruct,
|
||||
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
|
||||
DEF_TRAVERSE_STMT(OpenACCAtomicConstruct,
|
||||
{ TRY_TO(TraverseOpenACCAssociatedStmtConstruct(S)); })
|
||||
DEF_TRAVERSE_STMT(OpenACCCacheConstruct, {
|
||||
for (auto *E : S->getVarList())
|
||||
TRY_TO(TraverseStmt(E));
|
||||
})
|
||||
|
||||
// Traverse HLSL: Out argument expression
|
||||
DEF_TRAVERSE_STMT(HLSLOutArgExpr, {})
|
||||
|
||||
@@ -593,6 +593,81 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class OpenACCCacheConstruct final
|
||||
: public OpenACCConstructStmt,
|
||||
private llvm::TrailingObjects<OpenACCCacheConstruct, Expr *> {
|
||||
friend TrailingObjects;
|
||||
friend class ASTStmtWriter;
|
||||
friend class ASTStmtReader;
|
||||
// Locations of the left and right parens of the 'var-list'
|
||||
// expression-list.
|
||||
SourceRange ParensLoc;
|
||||
SourceLocation ReadOnlyLoc;
|
||||
|
||||
unsigned NumVars = 0;
|
||||
|
||||
OpenACCCacheConstruct(unsigned NumVars)
|
||||
: OpenACCConstructStmt(OpenACCCacheConstructClass,
|
||||
OpenACCDirectiveKind::Cache, SourceLocation{},
|
||||
SourceLocation{}, SourceLocation{}),
|
||||
NumVars(NumVars) {
|
||||
std::uninitialized_value_construct(getVarListPtr(),
|
||||
getVarListPtr() + NumVars);
|
||||
}
|
||||
OpenACCCacheConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation RParenLoc,
|
||||
SourceLocation End)
|
||||
: OpenACCConstructStmt(OpenACCCacheConstructClass,
|
||||
OpenACCDirectiveKind::Cache, Start, DirectiveLoc,
|
||||
End),
|
||||
ParensLoc(LParenLoc, RParenLoc), ReadOnlyLoc(ReadOnlyLoc),
|
||||
NumVars(VarList.size()) {
|
||||
|
||||
std::uninitialized_copy(VarList.begin(), VarList.end(), getVarListPtr());
|
||||
}
|
||||
|
||||
Expr **getVarListPtr() const {
|
||||
return const_cast<Expr **>(getTrailingObjects<Expr *>());
|
||||
}
|
||||
|
||||
public:
|
||||
llvm::ArrayRef<Expr *> getVarList() const {
|
||||
return llvm::ArrayRef<Expr *>(getVarListPtr(), NumVars);
|
||||
}
|
||||
|
||||
llvm::ArrayRef<Expr *> getVarList() {
|
||||
return llvm::ArrayRef<Expr *>(getVarListPtr(), NumVars);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OpenACCCacheConstructClass;
|
||||
}
|
||||
|
||||
static OpenACCCacheConstruct *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumVars);
|
||||
static OpenACCCacheConstruct *
|
||||
Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation RParenLoc,
|
||||
SourceLocation End);
|
||||
|
||||
SourceLocation getLParenLoc() const { return ParensLoc.getBegin(); }
|
||||
SourceLocation getRParenLoc() const { return ParensLoc.getEnd(); }
|
||||
bool hasReadOnly() const { return !ReadOnlyLoc.isInvalid(); }
|
||||
SourceLocation getReadOnlyLoc() const { return ReadOnlyLoc; }
|
||||
|
||||
child_range children() {
|
||||
Stmt **Begin = reinterpret_cast<Stmt **>(getVarListPtr());
|
||||
return child_range(Begin, Begin + NumVars);
|
||||
}
|
||||
|
||||
const_child_range children() const {
|
||||
Stmt *const *Begin = reinterpret_cast<Stmt *const *>(getVarListPtr());
|
||||
return const_child_range(Begin, Begin + NumVars);
|
||||
}
|
||||
};
|
||||
|
||||
// This class represents an 'init' construct, which has just a clause list.
|
||||
class OpenACCInitConstruct final
|
||||
: public OpenACCConstructStmt,
|
||||
|
||||
@@ -422,6 +422,7 @@ public:
|
||||
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S);
|
||||
void VisitOpenACCUpdateConstruct(const OpenACCUpdateConstruct *S);
|
||||
void VisitOpenACCAtomicConstruct(const OpenACCAtomicConstruct *S);
|
||||
void VisitOpenACCCacheConstruct(const OpenACCCacheConstruct *S);
|
||||
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
|
||||
void VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D);
|
||||
void VisitEmbedExpr(const EmbedExpr *S);
|
||||
|
||||
@@ -12848,6 +12848,9 @@ def err_acc_not_a_var_ref
|
||||
def err_acc_not_a_var_ref_use_device_declare
|
||||
: Error<"OpenACC variable %select{in 'use_device' clause|on 'declare' "
|
||||
"construct}0 is not a valid variable name or array name">;
|
||||
def err_acc_not_a_var_ref_cache
|
||||
: Error<"OpenACC variable in cache directive is not a valid sub-array or "
|
||||
"array element">;
|
||||
def err_acc_typecheck_subarray_value
|
||||
: Error<"OpenACC sub-array subscripted value is not an array or pointer">;
|
||||
def err_acc_subarray_function_type
|
||||
|
||||
@@ -320,6 +320,7 @@ def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>;
|
||||
def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>;
|
||||
def OpenACCUpdateConstruct : StmtNode<OpenACCConstructStmt>;
|
||||
def OpenACCAtomicConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
|
||||
def OpenACCCacheConstruct : StmtNode<OpenACCConstructStmt>;
|
||||
|
||||
// OpenACC Additional Expressions.
|
||||
def OpenACCAsteriskSizeExpr : StmtNode<Expr>;
|
||||
|
||||
@@ -3730,6 +3730,11 @@ private:
|
||||
return Out;
|
||||
}
|
||||
};
|
||||
struct OpenACCCacheParseInfo {
|
||||
bool Failed = false;
|
||||
SourceLocation ReadOnlyLoc;
|
||||
SmallVector<Expr *> Vars;
|
||||
};
|
||||
|
||||
/// Represents the 'error' state of parsing an OpenACC Clause, and stores
|
||||
/// whether we can continue parsing, or should give up on the directive.
|
||||
@@ -3752,7 +3757,7 @@ private:
|
||||
/// Helper that parses an ID Expression based on the language options.
|
||||
ExprResult ParseOpenACCIDExpression();
|
||||
/// Parses the variable list for the `cache` construct.
|
||||
void ParseOpenACCCacheVarList();
|
||||
OpenACCCacheParseInfo ParseOpenACCCacheVarList();
|
||||
|
||||
using OpenACCVarParseResult = std::pair<ExprResult, OpenACCParseCanContinue>;
|
||||
/// Parses a single variable in a variable list for OpenACC.
|
||||
|
||||
@@ -762,6 +762,8 @@ public:
|
||||
/// declaration reference to a variable of the correct type.
|
||||
ExprResult ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
|
||||
Expr *VarExpr);
|
||||
/// Helper function called by ActonVar that is used to check a 'cache' var.
|
||||
ExprResult ActOnCacheVar(Expr *VarExpr);
|
||||
|
||||
// Called after 'ActOnVar' specifically for a 'link' clause, which has to do
|
||||
// some minor additional checks.
|
||||
|
||||
@@ -2049,6 +2049,7 @@ enum StmtCode {
|
||||
STMT_OPENACC_SET_CONSTRUCT,
|
||||
STMT_OPENACC_UPDATE_CONSTRUCT,
|
||||
STMT_OPENACC_ATOMIC_CONSTRUCT,
|
||||
STMT_OPENACC_CACHE_CONSTRUCT,
|
||||
|
||||
// HLSL Constructs
|
||||
EXPR_HLSL_OUT_ARG,
|
||||
|
||||
@@ -321,3 +321,21 @@ OpenACCAtomicConstruct *OpenACCAtomicConstruct::Create(
|
||||
OpenACCAtomicConstruct(Start, DirectiveLoc, AtKind, End, AssociatedStmt);
|
||||
return Inst;
|
||||
}
|
||||
OpenACCCacheConstruct *OpenACCCacheConstruct::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumVars) {
|
||||
void *Mem =
|
||||
C.Allocate(OpenACCCacheConstruct::totalSizeToAlloc<Expr *>(NumVars));
|
||||
auto *Inst = new (Mem) OpenACCCacheConstruct(NumVars);
|
||||
return Inst;
|
||||
}
|
||||
|
||||
OpenACCCacheConstruct *OpenACCCacheConstruct::Create(
|
||||
const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
|
||||
SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
|
||||
ArrayRef<Expr *> VarList, SourceLocation RParenLoc, SourceLocation End) {
|
||||
void *Mem = C.Allocate(
|
||||
OpenACCCacheConstruct::totalSizeToAlloc<Expr *>(VarList.size()));
|
||||
auto *Inst = new (Mem) OpenACCCacheConstruct(
|
||||
Start, DirectiveLoc, LParenLoc, ReadOnlyLoc, VarList, RParenLoc, End);
|
||||
return Inst;
|
||||
}
|
||||
|
||||
@@ -1261,6 +1261,18 @@ void StmtPrinter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
PrintStmt(S->getAssociatedStmt());
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
|
||||
Indent() << "#pragma acc cache(";
|
||||
if (S->hasReadOnly())
|
||||
OS << "readonly: ";
|
||||
|
||||
llvm::interleaveComma(S->getVarList(), OS, [&](const Expr *E) {
|
||||
E->printPretty(OS, nullptr, Policy);
|
||||
});
|
||||
|
||||
OS << ")\n";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expr printing methods.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -2708,6 +2708,7 @@ void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
|
||||
for (auto *E : Clause.getQueueIdExprs())
|
||||
Profiler.VisitStmt(E);
|
||||
}
|
||||
|
||||
/// Nothing to do here, there are no sub-statements.
|
||||
void OpenACCClauseProfiler::VisitDeviceTypeClause(
|
||||
const OpenACCDeviceTypeClause &Clause) {}
|
||||
@@ -2796,6 +2797,11 @@ void StmtProfiler::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) {
|
||||
P.VisitOpenACCClauseList(S->clauses());
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOpenACCCacheConstruct(const OpenACCCacheConstruct *S) {
|
||||
// VisitStmt covers 'children', so the exprs inside of it are covered.
|
||||
VisitStmt(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) {
|
||||
VisitStmt(S);
|
||||
OpenACCClauseProfiler P{*this};
|
||||
|
||||
@@ -3042,6 +3042,12 @@ void TextNodeDumper::VisitOpenACCHostDataConstruct(
|
||||
void TextNodeDumper::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) {
|
||||
VisitOpenACCConstructStmt(S);
|
||||
}
|
||||
void TextNodeDumper::VisitOpenACCCacheConstruct(
|
||||
const OpenACCCacheConstruct *S) {
|
||||
VisitOpenACCConstructStmt(S);
|
||||
if (S->hasReadOnly())
|
||||
OS <<" readonly";
|
||||
}
|
||||
void TextNodeDumper::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) {
|
||||
VisitOpenACCConstructStmt(S);
|
||||
}
|
||||
|
||||
@@ -494,6 +494,10 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
|
||||
break;
|
||||
case Stmt::OpenACCAtomicConstructClass:
|
||||
EmitOpenACCAtomicConstruct(cast<OpenACCAtomicConstruct>(*S));
|
||||
break;
|
||||
case Stmt::OpenACCCacheConstructClass:
|
||||
EmitOpenACCCacheConstruct(cast<OpenACCCacheConstruct>(*S));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4192,6 +4192,10 @@ public:
|
||||
// some sort of IR.
|
||||
EmitStmt(S.getAssociatedStmt());
|
||||
}
|
||||
void EmitOpenACCCacheConstruct(const OpenACCCacheConstruct &S) {
|
||||
// TODO OpenACC: Implement this. It is currently implemented as a 'no-op',
|
||||
// but in the future we will implement some sort of IR.
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// LValue Expression Emission
|
||||
|
||||
@@ -617,13 +617,18 @@ unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
|
||||
case OpenACCDirectiveKind::Wait:
|
||||
case OpenACCDirectiveKind::Init:
|
||||
case OpenACCDirectiveKind::Shutdown:
|
||||
case OpenACCDirectiveKind::Cache:
|
||||
case OpenACCDirectiveKind::Loop:
|
||||
case OpenACCDirectiveKind::Atomic:
|
||||
case OpenACCDirectiveKind::Declare:
|
||||
case OpenACCDirectiveKind::Routine:
|
||||
case OpenACCDirectiveKind::Set:
|
||||
case OpenACCDirectiveKind::Update:
|
||||
return 0;
|
||||
case OpenACCDirectiveKind::Invalid:
|
||||
llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1403,25 +1408,29 @@ llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList(OpenACCDirectiveKind DK,
|
||||
/// In C and C++, the syntax of the cache directive is:
|
||||
///
|
||||
/// #pragma acc cache ([readonly:]var-list) new-line
|
||||
void Parser::ParseOpenACCCacheVarList() {
|
||||
Parser::OpenACCCacheParseInfo Parser::ParseOpenACCCacheVarList() {
|
||||
// If this is the end of the line, just return 'false' and count on the close
|
||||
// paren diagnostic to catch the issue.
|
||||
if (getCurToken().isAnnotation())
|
||||
return;
|
||||
return {};
|
||||
|
||||
OpenACCCacheParseInfo CacheInfo;
|
||||
|
||||
SourceLocation ReadOnlyLoc = getCurToken().getLocation();
|
||||
// The VarList is an optional `readonly:` followed by a list of a variable
|
||||
// specifications. Consume something that looks like a 'tag', and diagnose if
|
||||
// it isn't 'readonly'.
|
||||
if (tryParseAndConsumeSpecialTokenKind(*this,
|
||||
OpenACCSpecialTokenKind::ReadOnly,
|
||||
OpenACCDirectiveKind::Cache)) {
|
||||
// FIXME: Record that this is a 'readonly' so that we can use that during
|
||||
// Sema/AST generation.
|
||||
}
|
||||
OpenACCDirectiveKind::Cache))
|
||||
CacheInfo.ReadOnlyLoc = ReadOnlyLoc;
|
||||
|
||||
// ParseOpenACCVarList should leave us before a r-paren, so no need to skip
|
||||
// anything here.
|
||||
ParseOpenACCVarList(OpenACCDirectiveKind::Cache, OpenACCClauseKind::Invalid);
|
||||
CacheInfo.Vars = ParseOpenACCVarList(OpenACCDirectiveKind::Cache,
|
||||
OpenACCClauseKind::Invalid);
|
||||
|
||||
return CacheInfo;
|
||||
}
|
||||
|
||||
Parser::OpenACCDirectiveParseInfo
|
||||
@@ -1430,6 +1439,7 @@ Parser::ParseOpenACCDirective() {
|
||||
SourceLocation DirLoc = getCurToken().getLocation();
|
||||
OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this);
|
||||
Parser::OpenACCWaitParseInfo WaitInfo;
|
||||
Parser::OpenACCCacheParseInfo CacheInfo;
|
||||
OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
|
||||
|
||||
getActions().OpenACC().ActOnConstruct(DirKind, DirLoc);
|
||||
@@ -1464,7 +1474,7 @@ Parser::ParseOpenACCDirective() {
|
||||
break;
|
||||
}
|
||||
case OpenACCDirectiveKind::Cache:
|
||||
ParseOpenACCCacheVarList();
|
||||
CacheInfo = ParseOpenACCCacheVarList();
|
||||
// The ParseOpenACCCacheVarList function manages to recover from failures,
|
||||
// so we can always consume the close.
|
||||
T.consumeClose();
|
||||
@@ -1486,16 +1496,19 @@ Parser::ParseOpenACCDirective() {
|
||||
}
|
||||
|
||||
// Parses the list of clauses, if present, plus set up return value.
|
||||
OpenACCDirectiveParseInfo ParseInfo{DirKind,
|
||||
StartLoc,
|
||||
DirLoc,
|
||||
T.getOpenLocation(),
|
||||
T.getCloseLocation(),
|
||||
/*EndLoc=*/SourceLocation{},
|
||||
WaitInfo.QueuesLoc,
|
||||
AtomicKind,
|
||||
WaitInfo.getAllExprs(),
|
||||
ParseOpenACCClauseList(DirKind)};
|
||||
OpenACCDirectiveParseInfo ParseInfo{
|
||||
DirKind,
|
||||
StartLoc,
|
||||
DirLoc,
|
||||
T.getOpenLocation(),
|
||||
T.getCloseLocation(),
|
||||
/*EndLoc=*/SourceLocation{},
|
||||
(DirKind == OpenACCDirectiveKind::Wait ? WaitInfo.QueuesLoc
|
||||
: CacheInfo.ReadOnlyLoc),
|
||||
AtomicKind,
|
||||
(DirKind == OpenACCDirectiveKind::Wait ? WaitInfo.getAllExprs()
|
||||
: CacheInfo.Vars),
|
||||
ParseOpenACCClauseList(DirKind)};
|
||||
|
||||
assert(Tok.is(tok::annot_pragma_openacc_end) &&
|
||||
"Didn't parse all OpenACC Clauses");
|
||||
|
||||
@@ -1407,6 +1407,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
|
||||
case Stmt::OpenACCEnterDataConstructClass:
|
||||
case Stmt::OpenACCExitDataConstructClass:
|
||||
case Stmt::OpenACCWaitConstructClass:
|
||||
case Stmt::OpenACCCacheConstructClass:
|
||||
case Stmt::OpenACCInitConstructClass:
|
||||
case Stmt::OpenACCShutdownConstructClass:
|
||||
case Stmt::OpenACCSetConstructClass:
|
||||
|
||||
@@ -81,6 +81,9 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
|
||||
case OpenACCDirectiveKind::HostData:
|
||||
case OpenACCDirectiveKind::Atomic:
|
||||
return true;
|
||||
case OpenACCDirectiveKind::Cache:
|
||||
case OpenACCDirectiveKind::Routine:
|
||||
case OpenACCDirectiveKind::Declare:
|
||||
case OpenACCDirectiveKind::EnterData:
|
||||
case OpenACCDirectiveKind::ExitData:
|
||||
case OpenACCDirectiveKind::Wait:
|
||||
@@ -89,7 +92,6 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
|
||||
case OpenACCDirectiveKind::Set:
|
||||
case OpenACCDirectiveKind::Update:
|
||||
llvm_unreachable("Doesn't have an associated stmt");
|
||||
default:
|
||||
case OpenACCDirectiveKind::Invalid:
|
||||
llvm_unreachable("Unhandled directive kind?");
|
||||
}
|
||||
@@ -334,6 +336,7 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
|
||||
case OpenACCDirectiveKind::Shutdown:
|
||||
case OpenACCDirectiveKind::Set:
|
||||
case OpenACCDirectiveKind::Update:
|
||||
case OpenACCDirectiveKind::Cache:
|
||||
case OpenACCDirectiveKind::Atomic:
|
||||
case OpenACCDirectiveKind::Declare:
|
||||
// Nothing to do here, there is no real legalization that needs to happen
|
||||
@@ -480,8 +483,56 @@ bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprResult SemaOpenACC::ActOnCacheVar(Expr *VarExpr) {
|
||||
Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
|
||||
if (!isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
|
||||
Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// It isn't clear what 'simple array element or simple subarray' means, so we
|
||||
// will just allow arbitrary depth.
|
||||
while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
|
||||
if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
|
||||
CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
|
||||
else
|
||||
CurVarExpr =
|
||||
cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
|
||||
}
|
||||
|
||||
// References to a VarDecl are fine.
|
||||
if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
|
||||
if (isa<VarDecl, NonTypeTemplateParmDecl>(
|
||||
DRE->getFoundDecl()->getCanonicalDecl()))
|
||||
return VarExpr;
|
||||
}
|
||||
|
||||
if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
|
||||
if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
|
||||
return VarExpr;
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing really we can do here, as these are dependent. So just return they
|
||||
// are valid.
|
||||
if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(CurVarExpr))
|
||||
return VarExpr;
|
||||
|
||||
// There isn't really anything we can do in the case of a recovery expr, so
|
||||
// skip the diagnostic rather than produce a confusing diagnostic.
|
||||
if (isa<RecoveryExpr>(CurVarExpr))
|
||||
return ExprError();
|
||||
|
||||
Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
|
||||
return ExprError();
|
||||
}
|
||||
ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
|
||||
Expr *VarExpr) {
|
||||
// This has unique enough restrictions that we should split it to a separate
|
||||
// function.
|
||||
if (DK == OpenACCDirectiveKind::Cache)
|
||||
return ActOnCacheVar(VarExpr);
|
||||
|
||||
Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
|
||||
|
||||
// 'use_device' doesn't allow array subscript or array sections.
|
||||
@@ -1624,6 +1675,12 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(
|
||||
getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc,
|
||||
AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
|
||||
}
|
||||
case OpenACCDirectiveKind::Cache: {
|
||||
assert(Clauses.empty() && "Cache doesn't allow clauses");
|
||||
return OpenACCCacheConstruct::Create(getASTContext(), StartLoc, DirLoc,
|
||||
LParenLoc, MiscLoc, Exprs, RParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
case OpenACCDirectiveKind::Declare: {
|
||||
// Declare is a declaration directive, but can be used here as long as we
|
||||
// wrap it in a DeclStmt. So make sure we do that here.
|
||||
@@ -1649,6 +1706,7 @@ StmtResult SemaOpenACC::ActOnAssociatedStmt(
|
||||
case OpenACCDirectiveKind::Init:
|
||||
case OpenACCDirectiveKind::Shutdown:
|
||||
case OpenACCDirectiveKind::Set:
|
||||
case OpenACCDirectiveKind::Cache:
|
||||
llvm_unreachable(
|
||||
"these don't have associated statements, so shouldn't get here");
|
||||
case OpenACCDirectiveKind::Atomic:
|
||||
|
||||
@@ -4204,6 +4204,15 @@ public:
|
||||
Exprs, RParenLoc, EndLoc, Clauses, {});
|
||||
}
|
||||
|
||||
StmtResult RebuildOpenACCCacheConstruct(
|
||||
SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ReadOnlyLoc, ArrayRef<Expr *> VarList,
|
||||
SourceLocation RParenLoc, SourceLocation EndLoc) {
|
||||
return getSema().OpenACC().ActOnEndStmtDirective(
|
||||
OpenACCDirectiveKind::Cache, BeginLoc, DirLoc, LParenLoc, ReadOnlyLoc,
|
||||
VarList, RParenLoc, EndLoc, {}, {});
|
||||
}
|
||||
|
||||
StmtResult RebuildOpenACCAtomicConstruct(SourceLocation BeginLoc,
|
||||
SourceLocation DirLoc,
|
||||
OpenACCAtomicKind AtKind,
|
||||
@@ -12646,6 +12655,37 @@ TreeTransform<Derived>::TransformOpenACCWaitConstruct(OpenACCWaitConstruct *C) {
|
||||
DevNumExpr.isUsable() ? DevNumExpr.get() : nullptr, C->getQueuesLoc(),
|
||||
QueueIdExprs, C->getRParenLoc(), C->getEndLoc(), TransformedClauses);
|
||||
}
|
||||
template <typename Derived>
|
||||
StmtResult TreeTransform<Derived>::TransformOpenACCCacheConstruct(
|
||||
OpenACCCacheConstruct *C) {
|
||||
getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc());
|
||||
|
||||
llvm::SmallVector<Expr *> TransformedVarList;
|
||||
for (Expr *Var : C->getVarList()) {
|
||||
assert(Var && "Null var listexpr?");
|
||||
|
||||
ExprResult NewVar = getDerived().TransformExpr(Var);
|
||||
|
||||
if (!NewVar.isUsable())
|
||||
break;
|
||||
|
||||
NewVar = getSema().OpenACC().ActOnVar(
|
||||
C->getDirectiveKind(), OpenACCClauseKind::Invalid, NewVar.get());
|
||||
if (!NewVar.isUsable())
|
||||
break;
|
||||
|
||||
TransformedVarList.push_back(NewVar.get());
|
||||
}
|
||||
|
||||
if (getSema().OpenACC().ActOnStartStmtDirective(C->getDirectiveKind(),
|
||||
C->getBeginLoc(), {}))
|
||||
return StmtError();
|
||||
|
||||
return getDerived().RebuildOpenACCCacheConstruct(
|
||||
C->getBeginLoc(), C->getDirectiveLoc(), C->getLParenLoc(),
|
||||
C->getReadOnlyLoc(), TransformedVarList, C->getRParenLoc(),
|
||||
C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult TreeTransform<Derived>::TransformOpenACCAtomicConstruct(
|
||||
|
||||
@@ -2922,6 +2922,16 @@ void ASTStmtReader::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
|
||||
}
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
|
||||
VisitStmt(S);
|
||||
(void)Record.readInt();
|
||||
VisitOpenACCConstructStmt(S);
|
||||
S->ParensLoc = Record.readSourceRange();
|
||||
S->ReadOnlyLoc = Record.readSourceLocation();
|
||||
for (unsigned I = 0; I < S->NumVars; ++I)
|
||||
S->getVarListPtr()[I] = cast<Expr>(Record.readSubStmt());
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
VisitStmt(S);
|
||||
S->Kind = Record.readEnum<OpenACCDirectiveKind>();
|
||||
@@ -4447,6 +4457,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
S = OpenACCWaitConstruct::CreateEmpty(Context, NumExprs, NumClauses);
|
||||
break;
|
||||
}
|
||||
case STMT_OPENACC_CACHE_CONSTRUCT: {
|
||||
unsigned NumVars = Record[ASTStmtReader::NumStmtFields];
|
||||
S = OpenACCCacheConstruct::CreateEmpty(Context, NumVars);
|
||||
break;
|
||||
}
|
||||
case STMT_OPENACC_INIT_CONSTRUCT: {
|
||||
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
|
||||
S = OpenACCInitConstruct::CreateEmpty(Context, NumClauses);
|
||||
|
||||
@@ -3017,6 +3017,18 @@ void ASTStmtWriter::VisitOpenACCAtomicConstruct(OpenACCAtomicConstruct *S) {
|
||||
Code = serialization::STMT_OPENACC_ATOMIC_CONSTRUCT;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOpenACCCacheConstruct(OpenACCCacheConstruct *S) {
|
||||
VisitStmt(S);
|
||||
Record.push_back(S->getVarList().size());
|
||||
VisitOpenACCConstructStmt(S);
|
||||
Record.AddSourceRange(S->ParensLoc);
|
||||
Record.AddSourceLocation(S->ReadOnlyLoc);
|
||||
|
||||
for (Expr *E : S->getVarList())
|
||||
Record.AddStmt(E);
|
||||
Code = serialization::STMT_OPENACC_CACHE_CONSTRUCT;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// HLSL Constructs/Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -1834,6 +1834,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||
case Stmt::OpenACCExitDataConstructClass:
|
||||
case Stmt::OpenACCHostDataConstructClass:
|
||||
case Stmt::OpenACCWaitConstructClass:
|
||||
case Stmt::OpenACCCacheConstructClass:
|
||||
case Stmt::OpenACCInitConstructClass:
|
||||
case Stmt::OpenACCShutdownConstructClass:
|
||||
case Stmt::OpenACCSetConstructClass:
|
||||
|
||||
9
clang/test/AST/ast-print-openacc-cache-construct.cpp
Normal file
9
clang/test/AST/ast-print-openacc-cache-construct.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// RUN: %clang_cc1 -fopenacc -ast-print %s -o - | FileCheck %s
|
||||
|
||||
void foo() {
|
||||
int Array[5];
|
||||
// CHECK: #pragma acc cache(readonly: Array[1], Array[1:2])
|
||||
#pragma acc cache(readonly:Array[1], Array[1:2])
|
||||
// CHECK: #pragma acc cache(Array[1], Array[1:2])
|
||||
#pragma acc cache(Array[1], Array[1:2])
|
||||
}
|
||||
@@ -12,186 +12,165 @@ void func() {
|
||||
struct S s;
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{expected '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{expected '('}}
|
||||
#pragma acc cache
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+3{{expected '('}}
|
||||
// expected-error@+2{{invalid OpenACC clause 'clause'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+2{{expected '('}}
|
||||
// expected-error@+1{{invalid OpenACC clause 'clause'}}
|
||||
#pragma acc cache clause list
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{expected expression}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{expected expression}}
|
||||
#pragma acc cache()
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+3{{expected expression}}
|
||||
// expected-error@+2{{invalid OpenACC clause 'clause'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+2{{expected expression}}
|
||||
// expected-error@+1{{invalid OpenACC clause 'clause'}}
|
||||
#pragma acc cache() clause-list
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+2{{expected ')'}}
|
||||
// expected-note@+1{{to match this '('}}
|
||||
#pragma acc cache(
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+4{{use of undeclared identifier 'invalid'}}
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+3{{use of undeclared identifier 'invalid'}}
|
||||
// expected-error@+2{{expected ')'}}
|
||||
// expected-note@+1{{to match this '('}}
|
||||
#pragma acc cache(invalid
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(ArrayPtr
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{use of undeclared identifier 'invalid'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{use of undeclared identifier 'invalid'}}
|
||||
#pragma acc cache(invalid)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(ArrayPtr)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+6{{expected expression}}
|
||||
// expected-error@+5{{expected ']'}}
|
||||
// expected-note@+4{{to match this '['}}
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+5{{expected expression}}
|
||||
// expected-error@+4{{expected ']'}}
|
||||
// expected-note@+3{{to match this '['}}
|
||||
// expected-error@+2{{expected ')'}}
|
||||
// expected-note@+1{{to match this '('}}
|
||||
#pragma acc cache(ArrayPtr[
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+4{{expected expression}}
|
||||
// expected-error@+3{{expected ']'}}
|
||||
// expected-note@+2{{to match this '['}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+3{{expected expression}}
|
||||
// expected-error@+2{{expected ']'}}
|
||||
// expected-note@+1{{to match this '['}}
|
||||
#pragma acc cache(ArrayPtr[, 5)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+4{{expected expression}}
|
||||
// expected-error@+3{{expected ']'}}
|
||||
// expected-note@+2{{to match this '['}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+3{{expected expression}}
|
||||
// expected-error@+2{{expected ']'}}
|
||||
// expected-note@+1{{to match this '['}}
|
||||
#pragma acc cache(Array[)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(Array[*readonly])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+6{{expected expression}}
|
||||
// expected-error@+5{{expected ']'}}
|
||||
// expected-note@+4{{to match this '['}}
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+5{{expected expression}}
|
||||
// expected-error@+4{{expected ']'}}
|
||||
// expected-note@+3{{to match this '['}}
|
||||
// expected-error@+2{{expected ')'}}
|
||||
// expected-note@+1{{to match this '('}}
|
||||
#pragma acc cache(Array[*readonly:
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(readonly)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{invalid tag 'devnum' on 'cache' directive}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(devnum:ArrayPtr)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{invalid tag 'invalid' on 'cache' directive}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(invalid:ArrayPtr)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(readonly:ArrayPtr)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:1])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:*readonly])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:*readonly], Array)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:*readonly], Array[*readonly:3])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5 + i:*readonly], Array[*readonly + i:3])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+4{{expected expression}}
|
||||
// expected-error@+3{{expected ')'}}
|
||||
// expected-note@+2{{to match this '('}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+3{{expected expression}}
|
||||
// expected-error@+2{{expected ')'}}
|
||||
// expected-note@+1{{to match this '('}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:*readonly],
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{expected expression}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{expected expression}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:*readonly],)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+2{{left operand of comma operator has no effect}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-warning@+1{{left operand of comma operator has no effect}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5,6:*readonly])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+2{{left operand of comma operator has no effect}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-warning@+1{{left operand of comma operator has no effect}}
|
||||
#pragma acc cache(readonly:ArrayPtr[5:3, *readonly], ArrayPtr[0])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(readonly:s.foo)
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+2{{left operand of comma operator has no effect}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-warning@+1{{left operand of comma operator has no effect}}
|
||||
#pragma acc cache(readonly:s.Array[1,2])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,34 +9,29 @@ template<typename T, int I>
|
||||
void func() {
|
||||
char *ArrayPtr = getArrayPtr();
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(ArrayPtr[T::value + I:I + 5], T::array[(i + T::value, 5): 6])
|
||||
// expected-warning@+1{{left operand of comma operator has no effect}}
|
||||
#pragma acc cache(ArrayPtr[T::value + I:I + 3], T::array[(i + T::value, 2): 4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(NS::NSArray[NS::NSInt])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(NS::NSArray[NS::NSInt : NS::NSInt])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{use of undeclared identifier 'NSArray'; did you mean 'NS::NSArray'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{use of undeclared identifier 'NSArray'; did you mean 'NS::NSArray'}}
|
||||
#pragma acc cache(NSArray[NS::NSInt : NS::NSInt])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
|
||||
#pragma acc cache(NS::NSArray[NSInt : NS::NSInt])
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{use of undeclared identifier 'NSInt'; did you mean 'NS::NSInt'}}
|
||||
#pragma acc cache(NS::NSArray[NS::NSInt : NSInt])
|
||||
}
|
||||
}
|
||||
@@ -59,56 +54,46 @@ void use() {
|
||||
|
||||
Members s;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(s.array[s.value])
|
||||
}
|
||||
HasMembersArray Arrs;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(Arrs.MemArr[3].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
#pragma acc cache(Arrs.MemArr[3].array[1:4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{OpenACC sub-array is not allowed here}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc cache(Arrs.MemArr[2:1].array[1:4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{OpenACC sub-array is not allowed here}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc cache(Arrs.MemArr[2:1].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+3{{expected ']'}}
|
||||
// expected-note@+2{{to match this '['}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+2{{expected ']'}}
|
||||
// expected-note@+1{{to match this '['}}
|
||||
#pragma acc cache(Arrs.MemArr[3:4:].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{OpenACC sub-array is not allowed here}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc cache(Arrs.MemArr[:].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{expected unqualified-id}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{expected unqualified-id}}
|
||||
#pragma acc cache(Arrs.MemArr[::].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+4{{expected expression}}
|
||||
// expected-error@+3{{expected ']'}}
|
||||
// expected-note@+2{{to match this '['}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+3{{expected expression}}
|
||||
// expected-error@+2{{expected ']'}}
|
||||
// expected-note@+1{{to match this '['}}
|
||||
#pragma acc cache(Arrs.MemArr[: :].array[4])
|
||||
}
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
// expected-error@+2{{OpenACC sub-array is not allowed here}}
|
||||
// expected-warning@+1{{OpenACC construct 'cache' not yet implemented, pragma ignored}}
|
||||
// expected-error@+1{{OpenACC sub-array is not allowed here}}
|
||||
#pragma acc cache(Arrs.MemArr[3:].array[4])
|
||||
}
|
||||
func<S, 5>();
|
||||
func<S, 5>(); // expected-note{{in instantiation of function template specialization}}
|
||||
}
|
||||
|
||||
|
||||
121
clang/test/SemaOpenACC/cache-construct-ast.cpp
Normal file
121
clang/test/SemaOpenACC/cache-construct-ast.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s
|
||||
|
||||
// Test this with PCH.
|
||||
// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s
|
||||
|
||||
#ifndef PCH_HELPER
|
||||
#define PCH_HELPER
|
||||
|
||||
void use() {
|
||||
// CHECK: FunctionDecl{{.*}} use 'void ()'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
int Array[5];
|
||||
// CHECK-NEXT: DeclStmt
|
||||
// CHECK-NEXT: VarDecl{{.*}}Array 'int[5]'
|
||||
|
||||
#pragma acc cache(Array[1])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'int[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
#pragma acc cache(Array[1:2])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySectionExpr{{.*}}'<array section type>' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'int[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2
|
||||
}
|
||||
|
||||
struct S {
|
||||
int Array[5];
|
||||
int Array2D[5][5];
|
||||
|
||||
void StructUse() {
|
||||
// CHECK: CXXMethodDecl{{.*}}StructUse 'void ()'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
#pragma acc cache(Array[1])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: MemberExpr{{.*}} 'int[5]' lvalue ->Array
|
||||
// CHECK-NEXT: CXXThisExpr{{.*}} 'S *'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
#pragma acc cache(Array[1:2])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySectionExpr{{.*}}'<array section type>' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: MemberExpr{{.*}} 'int[5]' lvalue ->Array
|
||||
// CHECK-NEXT: CXXThisExpr{{.*}} 'S *'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2
|
||||
#pragma acc cache(Array2D[1][1])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int[5]' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)[5]' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: MemberExpr{{.*}} 'int[5][5]' lvalue ->Array2D
|
||||
// CHECK-NEXT: CXXThisExpr{{.*}} 'S *'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
#pragma acc cache(Array2D[1][1:2])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySectionExpr{{.*}}'<array section type>' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int[5]' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int (*)[5]' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: MemberExpr{{.*}} 'int[5][5]' lvalue ->Array2D
|
||||
// CHECK-NEXT: CXXThisExpr{{.*}} 'S *'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void templ_use() {
|
||||
// CHECK: FunctionDecl{{.*}} templ_use 'void ()'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
T Array[5];
|
||||
// CHECK-NEXT: DeclStmt
|
||||
// CHECK-NEXT: VarDecl{{.*}}Array 'T[5]'
|
||||
|
||||
#pragma acc cache(Array[1])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'T' lvalue
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'T[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
#pragma acc cache(Array[1:2])
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySectionExpr{{.*}}'<dependent type>' lvalue
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'T[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2
|
||||
|
||||
// Instantiation:
|
||||
// CHECK: FunctionDecl{{.*}} templ_use 'void ()' implicit_instantiation
|
||||
// CHECK-NEXT: TemplateArgument type 'int'
|
||||
// CHECK-NEXT: BuiltinType{{.*}} 'int'
|
||||
// CHECK-NEXT: CompoundStmt
|
||||
// CHECK-NEXT: DeclStmt
|
||||
// CHECK-NEXT: VarDecl{{.*}}Array 'int[5]'
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySubscriptExpr{{.*}}'int' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'int[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: OpenACCCacheConstruct{{.*}} cache
|
||||
// CHECK-NEXT: ArraySectionExpr{{.*}}'<array section type>' lvalue
|
||||
// CHECK-NEXT: ImplicitCastExpr{{.*}}'int *' <ArrayToPointerDecay>
|
||||
// CHECK-NEXT: DeclRefExpr{{.*}}'Array' 'int[5]'
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
|
||||
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 2
|
||||
}
|
||||
|
||||
void foo() {
|
||||
templ_use<int>();
|
||||
}
|
||||
#endif
|
||||
51
clang/test/SemaOpenACC/cache-construct.cpp
Normal file
51
clang/test/SemaOpenACC/cache-construct.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// RUN: %clang_cc1 %s -fopenacc -verify
|
||||
|
||||
|
||||
void use() {
|
||||
int Array[5];
|
||||
int NotArray;
|
||||
|
||||
#pragma acc cache(Array[1])
|
||||
#pragma acc cache(Array[1:2])
|
||||
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(Array)
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(NotArray)
|
||||
}
|
||||
|
||||
struct S {
|
||||
int Array[5];
|
||||
int NotArray;
|
||||
int Array2D[5][5];
|
||||
|
||||
void use() {
|
||||
#pragma acc cache(Array[1])
|
||||
#pragma acc cache(Array[1:2])
|
||||
#pragma acc cache(Array2D[1][1])
|
||||
#pragma acc cache(Array2D[1][1:2])
|
||||
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(Array)
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(NotArray)
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void templ_use() {
|
||||
T Array[5];
|
||||
T NotArray;
|
||||
|
||||
#pragma acc cache(Array[1])
|
||||
#pragma acc cache(Array[1:2])
|
||||
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(Array)
|
||||
// expected-error@+1{{OpenACC variable in cache directive is not a valid sub-array or array element}}
|
||||
#pragma acc cache(NotArray)
|
||||
}
|
||||
|
||||
void foo() {
|
||||
templ_use<int>();
|
||||
}
|
||||
@@ -2190,6 +2190,7 @@ public:
|
||||
void VisitOpenACCExitDataConstruct(const OpenACCExitDataConstruct *D);
|
||||
void VisitOpenACCHostDataConstruct(const OpenACCHostDataConstruct *D);
|
||||
void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *D);
|
||||
void VisitOpenACCCacheConstruct(const OpenACCCacheConstruct *D);
|
||||
void VisitOpenACCInitConstruct(const OpenACCInitConstruct *D);
|
||||
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *D);
|
||||
void VisitOpenACCSetConstruct(const OpenACCSetConstruct *D);
|
||||
@@ -3680,6 +3681,11 @@ void EnqueueVisitor::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *C) {
|
||||
EnqueueChildren(Clause);
|
||||
}
|
||||
|
||||
void EnqueueVisitor::VisitOpenACCCacheConstruct(
|
||||
const OpenACCCacheConstruct *C) {
|
||||
EnqueueChildren(C);
|
||||
}
|
||||
|
||||
void EnqueueVisitor::VisitOpenACCInitConstruct(const OpenACCInitConstruct *C) {
|
||||
EnqueueChildren(C);
|
||||
for (auto *Clause : C->clauses())
|
||||
@@ -6477,6 +6483,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||
return cxstring::createRef("OpenACCHostDataConstruct");
|
||||
case CXCursor_OpenACCWaitConstruct:
|
||||
return cxstring::createRef("OpenACCWaitConstruct");
|
||||
case CXCursor_OpenACCCacheConstruct:
|
||||
return cxstring::createRef("OpenACCCacheConstruct");
|
||||
case CXCursor_OpenACCInitConstruct:
|
||||
return cxstring::createRef("OpenACCInitConstruct");
|
||||
case CXCursor_OpenACCShutdownConstruct:
|
||||
|
||||
@@ -910,6 +910,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||
case Stmt::OpenACCWaitConstructClass:
|
||||
K = CXCursor_OpenACCWaitConstruct;
|
||||
break;
|
||||
case Stmt::OpenACCCacheConstructClass:
|
||||
K = CXCursor_OpenACCCacheConstruct;
|
||||
break;
|
||||
case Stmt::OpenACCInitConstructClass:
|
||||
K = CXCursor_OpenACCInitConstruct;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user