Skip to content

Commit 0c7b92a

Browse files
authored
[OpenACC] Implement Default clause for Compute Constructs (#88135)
As a followup to my previous commits, this is an implementation of a single clause, in this case the 'default' clause. This implements all semantic analysis for it on compute clauses, and continues to leave it rejected for all others (some as 'doesnt appertain', others as 'not implemented' as appropriate). This also implements and tests the TreeTransform as requested in the previous patch.
1 parent 6b35cbe commit 0c7b92a

17 files changed

+417
-33
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,36 @@ class OpenACCClauseWithParams : public OpenACCClause {
5151
SourceLocation getLParenLoc() const { return LParenLoc; }
5252
};
5353

54+
/// A 'default' clause, has the optional 'none' or 'present' argument.
55+
class OpenACCDefaultClause : public OpenACCClauseWithParams {
56+
friend class ASTReaderStmt;
57+
friend class ASTWriterStmt;
58+
59+
OpenACCDefaultClauseKind DefaultClauseKind;
60+
61+
protected:
62+
OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
63+
SourceLocation LParenLoc, SourceLocation EndLoc)
64+
: OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
65+
EndLoc),
66+
DefaultClauseKind(K) {
67+
assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
68+
DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
69+
"Invalid Clause Kind");
70+
}
71+
72+
public:
73+
OpenACCDefaultClauseKind getDefaultClauseKind() const {
74+
return DefaultClauseKind;
75+
}
76+
77+
static OpenACCDefaultClause *Create(const ASTContext &C,
78+
OpenACCDefaultClauseKind K,
79+
SourceLocation BeginLoc,
80+
SourceLocation LParenLoc,
81+
SourceLocation EndLoc);
82+
};
83+
5484
template <class Impl> class OpenACCClauseVisitor {
5585
Impl &getDerived() { return static_cast<Impl &>(*this); }
5686

@@ -66,6 +96,8 @@ template <class Impl> class OpenACCClauseVisitor {
6696

6797
switch (C->getClauseKind()) {
6898
case OpenACCClauseKind::Default:
99+
VisitOpenACCDefaultClause(*cast<OpenACCDefaultClause>(C));
100+
return;
69101
case OpenACCClauseKind::Finalize:
70102
case OpenACCClauseKind::IfPresent:
71103
case OpenACCClauseKind::Seq:
@@ -112,6 +144,10 @@ template <class Impl> class OpenACCClauseVisitor {
112144
}
113145
llvm_unreachable("Invalid Clause kind");
114146
}
147+
148+
void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause) {
149+
return getDerived().VisitOpenACCDefaultClause(Clause);
150+
}
115151
};
116152

117153
class OpenACCClausePrinter final
@@ -128,6 +164,8 @@ class OpenACCClausePrinter final
128164
}
129165
}
130166
OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}
167+
168+
void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause);
131169
};
132170

133171
} // namespace clang

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12265,6 +12265,10 @@ def err_acc_construct_appertainment
1226512265
"be used in a statement context">;
1226612266
def err_acc_clause_appertainment
1226712267
: Error<"OpenACC '%1' clause is not valid on '%0' directive">;
12268+
def err_acc_duplicate_clause_disallowed
12269+
: Error<"OpenACC '%1' clause cannot appear more than once on a '%0' "
12270+
"directive">;
12271+
def note_acc_previous_clause_here : Note<"previous clause is here">;
1226812272
def err_acc_branch_in_out_compute_construct
1226912273
: Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
1227012274
"OpenACC Compute Construct">;

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,29 @@ enum class OpenACCDefaultClauseKind {
419419
Invalid,
420420
};
421421

422+
template <typename StreamTy>
423+
inline StreamTy &printOpenACCDefaultClauseKind(StreamTy &Out,
424+
OpenACCDefaultClauseKind K) {
425+
switch (K) {
426+
case OpenACCDefaultClauseKind::None:
427+
return Out << "none";
428+
case OpenACCDefaultClauseKind::Present:
429+
return Out << "present";
430+
case OpenACCDefaultClauseKind::Invalid:
431+
return Out << "<invalid>";
432+
}
433+
}
434+
435+
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
436+
OpenACCDefaultClauseKind K) {
437+
return printOpenACCDefaultClauseKind(Out, K);
438+
}
439+
440+
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
441+
OpenACCDefaultClauseKind K) {
442+
return printOpenACCDefaultClauseKind(Out, K);
443+
}
444+
422445
enum class OpenACCReductionOperator {
423446
/// '+'.
424447
Addition,

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/Basic/SourceLocation.h"
2020
#include "clang/Sema/Ownership.h"
2121
#include "clang/Sema/SemaBase.h"
22+
#include <variant>
2223

2324
namespace clang {
2425
class OpenACCClause;
@@ -35,7 +36,11 @@ class SemaOpenACC : public SemaBase {
3536
SourceRange ClauseRange;
3637
SourceLocation LParenLoc;
3738

38-
// TODO OpenACC: Add variant here to store details of individual clauses.
39+
struct DefaultDetails {
40+
OpenACCDefaultClauseKind DefaultClauseKind;
41+
};
42+
43+
std::variant<DefaultDetails> Details;
3944

4045
public:
4146
OpenACCParsedClause(OpenACCDirectiveKind DirKind,
@@ -52,8 +57,20 @@ class SemaOpenACC : public SemaBase {
5257

5358
SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
5459

60+
OpenACCDefaultClauseKind getDefaultClauseKind() const {
61+
assert(ClauseKind == OpenACCClauseKind::Default &&
62+
"Parsed clause is not a default clause");
63+
return std::get<DefaultDetails>(Details).DefaultClauseKind;
64+
}
65+
5566
void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
5667
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
68+
69+
void setDefaultDetails(OpenACCDefaultClauseKind DefKind) {
70+
assert(ClauseKind == OpenACCClauseKind::Default &&
71+
"Parsed clause is not a default clause");
72+
Details = DefaultDetails{DefKind};
73+
}
5774
};
5875

5976
SemaOpenACC(Sema &S);

clang/lib/AST/OpenACCClause.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,22 @@
1515
#include "clang/AST/ASTContext.h"
1616

1717
using namespace clang;
18+
19+
OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C,
20+
OpenACCDefaultClauseKind K,
21+
SourceLocation BeginLoc,
22+
SourceLocation LParenLoc,
23+
SourceLocation EndLoc) {
24+
void *Mem =
25+
C.Allocate(sizeof(OpenACCDefaultClause), alignof(OpenACCDefaultClause));
26+
27+
return new (Mem) OpenACCDefaultClause(K, BeginLoc, LParenLoc, EndLoc);
28+
}
29+
30+
//===----------------------------------------------------------------------===//
31+
// OpenACC clauses printing methods
32+
//===----------------------------------------------------------------------===//
33+
void OpenACCClausePrinter::VisitOpenACCDefaultClause(
34+
const OpenACCDefaultClause &C) {
35+
OS << "default(" << C.getDefaultClauseKind() << ")";
36+
}

clang/lib/AST/StmtProfile.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,7 +2456,12 @@ class OpenACCClauseProfiler
24562456
Visit(Clause);
24572457
}
24582458
}
2459+
void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause);
24592460
};
2461+
2462+
/// Nothing to do here, there are no sub-statements.
2463+
void OpenACCClauseProfiler::VisitOpenACCDefaultClause(
2464+
const OpenACCDefaultClause &Clause) {}
24602465
} // namespace
24612466

24622467
void StmtProfiler::VisitOpenACCComputeConstruct(

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,17 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
390390
{
391391
ColorScope Color(OS, ShowColors, AttrColor);
392392
OS << C->getClauseKind();
393+
394+
// Handle clauses with parens for types that have no children, likely
395+
// because there is no sub expression.
396+
switch (C->getClauseKind()) {
397+
case OpenACCClauseKind::Default:
398+
OS << '(' << cast<OpenACCDefaultClause>(C)->getDefaultClauseKind() << ')';
399+
break;
400+
default:
401+
// Nothing to do here.
402+
break;
403+
}
393404
}
394405
dumpPointer(C);
395406
dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -831,9 +831,13 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
831831

832832
ConsumeToken();
833833

834-
if (getOpenACCDefaultClauseKind(DefKindTok) ==
835-
OpenACCDefaultClauseKind::Invalid)
834+
OpenACCDefaultClauseKind DefKind =
835+
getOpenACCDefaultClauseKind(DefKindTok);
836+
837+
if (DefKind == OpenACCDefaultClauseKind::Invalid)
836838
Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
839+
else
840+
ParsedClause.setDefaultDetails(DefKind);
837841

838842
break;
839843
}

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,27 @@ bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
3939

4040
bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
4141
OpenACCClauseKind ClauseKind) {
42-
// FIXME: For each clause as we implement them, we can add the
43-
// 'legalization' list here.
44-
45-
// Do nothing so we can go to the 'unimplemented' diagnostic instead.
46-
return true;
42+
switch (ClauseKind) {
43+
// FIXME: For each clause as we implement them, we can add the
44+
// 'legalization' list here.
45+
case OpenACCClauseKind::Default:
46+
switch (DirectiveKind) {
47+
case OpenACCDirectiveKind::Parallel:
48+
case OpenACCDirectiveKind::Serial:
49+
case OpenACCDirectiveKind::Kernels:
50+
case OpenACCDirectiveKind::ParallelLoop:
51+
case OpenACCDirectiveKind::SerialLoop:
52+
case OpenACCDirectiveKind::KernelsLoop:
53+
case OpenACCDirectiveKind::Data:
54+
return true;
55+
default:
56+
return false;
57+
}
58+
default:
59+
// Do nothing so we can go to the 'unimplemented' diagnostic instead.
60+
return true;
61+
}
62+
llvm_unreachable("Invalid clause kind");
4763
}
4864
} // namespace
4965

@@ -63,8 +79,43 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
6379
return nullptr;
6480
}
6581

66-
// TODO OpenACC: Switch over the clauses we implement here and 'create'
67-
// them.
82+
switch (Clause.getClauseKind()) {
83+
case OpenACCClauseKind::Default: {
84+
// Restrictions only properly implemented on 'compute' constructs, and
85+
// 'compute' constructs are the only construct that can do anything with
86+
// this yet, so skip/treat as unimplemented in this case.
87+
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Parallel &&
88+
Clause.getDirectiveKind() != OpenACCDirectiveKind::Serial &&
89+
Clause.getDirectiveKind() != OpenACCDirectiveKind::Kernels)
90+
break;
91+
92+
// Don't add an invalid clause to the AST.
93+
if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
94+
return nullptr;
95+
96+
// OpenACC 3.3, Section 2.5.4:
97+
// At most one 'default' clause may appear, and it must have a value of
98+
// either 'none' or 'present'.
99+
// Second half of the sentence is diagnosed during parsing.
100+
auto Itr = llvm::find_if(ExistingClauses, [](const OpenACCClause *C) {
101+
return C->getClauseKind() == OpenACCClauseKind::Default;
102+
});
103+
104+
if (Itr != ExistingClauses.end()) {
105+
SemaRef.Diag(Clause.getBeginLoc(),
106+
diag::err_acc_duplicate_clause_disallowed)
107+
<< Clause.getDirectiveKind() << Clause.getClauseKind();
108+
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
109+
return nullptr;
110+
}
111+
112+
return OpenACCDefaultClause::Create(
113+
getASTContext(), Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
114+
Clause.getLParenLoc(), Clause.getEndLoc());
115+
}
116+
default:
117+
break;
118+
}
68119

69120
Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
70121
<< Clause.getClauseKind();

clang/lib/Sema/TreeTransform.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4035,6 +4035,11 @@ class TreeTransform {
40354035
llvm::SmallVector<OpenACCClause *>
40364036
TransformOpenACCClauseList(OpenACCDirectiveKind DirKind,
40374037
ArrayRef<const OpenACCClause *> OldClauses);
4038+
4039+
OpenACCClause *
4040+
TransformOpenACCClause(ArrayRef<const OpenACCClause *> ExistingClauses,
4041+
OpenACCDirectiveKind DirKind,
4042+
const OpenACCClause *OldClause);
40384043
};
40394044

40404045
template <typename Derived>
@@ -11075,13 +11080,44 @@ OMPClause *TreeTransform<Derived>::TransformOMPXBareClause(OMPXBareClause *C) {
1107511080
//===----------------------------------------------------------------------===//
1107611081
// OpenACC transformation
1107711082
//===----------------------------------------------------------------------===//
11083+
template <typename Derived>
11084+
OpenACCClause *TreeTransform<Derived>::TransformOpenACCClause(
11085+
ArrayRef<const OpenACCClause *> ExistingClauses,
11086+
OpenACCDirectiveKind DirKind, const OpenACCClause *OldClause) {
11087+
11088+
SemaOpenACC::OpenACCParsedClause ParsedClause(
11089+
DirKind, OldClause->getClauseKind(), OldClause->getBeginLoc());
11090+
ParsedClause.setEndLoc(OldClause->getEndLoc());
11091+
11092+
if (const auto *WithParms = dyn_cast<OpenACCClauseWithParams>(OldClause))
11093+
ParsedClause.setLParenLoc(WithParms->getLParenLoc());
11094+
11095+
switch (OldClause->getClauseKind()) {
11096+
case OpenACCClauseKind::Default:
11097+
// There is nothing to do here as nothing dependent can appear in this
11098+
// clause. So just set the values so Sema can set the right value.
11099+
ParsedClause.setDefaultDetails(
11100+
cast<OpenACCDefaultClause>(OldClause)->getDefaultClauseKind());
11101+
break;
11102+
default:
11103+
assert(false && "Unhandled OpenACC clause in TreeTransform");
11104+
return nullptr;
11105+
}
11106+
11107+
return getSema().OpenACC().ActOnClause(ExistingClauses, ParsedClause);
11108+
}
11109+
1107811110
template <typename Derived>
1107911111
llvm::SmallVector<OpenACCClause *>
1108011112
TreeTransform<Derived>::TransformOpenACCClauseList(
1108111113
OpenACCDirectiveKind DirKind, ArrayRef<const OpenACCClause *> OldClauses) {
11082-
// TODO OpenACC: Ensure we loop through the list and transform the individual
11083-
// clauses.
11084-
return {};
11114+
llvm::SmallVector<OpenACCClause *> TransformedClauses;
11115+
for (const auto *Clause : OldClauses) {
11116+
if (OpenACCClause *TransformedClause = getDerived().TransformOpenACCClause(
11117+
TransformedClauses, DirKind, Clause))
11118+
TransformedClauses.push_back(TransformedClause);
11119+
}
11120+
return TransformedClauses;
1108511121
}
1108611122

1108711123
template <typename Derived>

clang/lib/Serialization/ASTReader.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11763,7 +11763,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
1176311763
[[maybe_unused]] SourceLocation EndLoc = readSourceLocation();
1176411764

1176511765
switch (ClauseKind) {
11766-
case OpenACCClauseKind::Default:
11766+
case OpenACCClauseKind::Default: {
11767+
SourceLocation LParenLoc = readSourceLocation();
11768+
OpenACCDefaultClauseKind DCK = readEnum<OpenACCDefaultClauseKind>();
11769+
return OpenACCDefaultClause::Create(getContext(), DCK, BeginLoc, LParenLoc,
11770+
EndLoc);
11771+
}
1176711772
case OpenACCClauseKind::Finalize:
1176811773
case OpenACCClauseKind::IfPresent:
1176911774
case OpenACCClauseKind::Seq:

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7406,7 +7406,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
74067406
writeSourceLocation(C->getEndLoc());
74077407

74087408
switch (C->getClauseKind()) {
7409-
case OpenACCClauseKind::Default:
7409+
case OpenACCClauseKind::Default: {
7410+
const auto *DC = cast<OpenACCDefaultClause>(C);
7411+
writeSourceLocation(DC->getLParenLoc());
7412+
writeEnum(DC->getDefaultClauseKind());
7413+
return;
7414+
}
74107415
case OpenACCClauseKind::Finalize:
74117416
case OpenACCClauseKind::IfPresent:
74127417
case OpenACCClauseKind::Seq:

0 commit comments

Comments
 (0)