[clang] [OpenACC] Implement loop 'gang' clause. (PR #112006)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 11 07:50:33 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
The 'gang' clause is used to specify parallel execution of loops, thus has some complicated rules depending on the 'loop's associated compute construct. This patch implements all of those.
---
Patch is 75.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/112006.diff
22 Files Affected:
- (modified) clang/include/clang/AST/OpenACCClause.h (+33-27)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+19)
- (modified) clang/include/clang/Basic/OpenACCClauses.def (+1)
- (modified) clang/include/clang/Basic/OpenACCKinds.h (+29)
- (modified) clang/include/clang/Parse/Parser.h (+9-3)
- (modified) clang/include/clang/Sema/SemaOpenACC.h (+73-7)
- (modified) clang/lib/AST/OpenACCClause.cpp (+44-6)
- (modified) clang/lib/AST/StmtProfile.cpp (+6)
- (modified) clang/lib/AST/TextNodeDumper.cpp (+11)
- (modified) clang/lib/Parse/ParseOpenACC.cpp (+35-15)
- (modified) clang/lib/Sema/SemaOpenACC.cpp (+252-24)
- (modified) clang/lib/Sema/TreeTransform.h (+23)
- (modified) clang/lib/Serialization/ASTReader.cpp (+12-1)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+10-1)
- (modified) clang/test/AST/ast-print-openacc-loop-construct.cpp (+82)
- (modified) clang/test/ParserOpenACC/parse-clauses.c (+22-28)
- (modified) clang/test/SemaOpenACC/compute-construct-device_type-clause.c (+1-2)
- (modified) clang/test/SemaOpenACC/loop-construct-auto_seq_independent-clauses.c (+4-11)
- (modified) clang/test/SemaOpenACC/loop-construct-device_type-clause.c (-1)
- (added) clang/test/SemaOpenACC/loop-construct-gang-ast.cpp (+330)
- (added) clang/test/SemaOpenACC/loop-construct-gang-clause.cpp (+335)
- (modified) clang/tools/libclang/CIndex.cpp (+5)
``````````diff
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index b500acc768e55a..f3a09eb651458d 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -119,32 +119,6 @@ class OpenACCSeqClause : public OpenACCClause {
}
};
-// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
-// this provides a basic, do-nothing implementation. We still need to add this
-// type to the visitors/etc, as well as get it to take its proper arguments.
-class OpenACCGangClause : public OpenACCClause {
-protected:
- OpenACCGangClause(SourceLocation BeginLoc, SourceLocation EndLoc)
- : OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
- llvm_unreachable("Not yet implemented");
- }
-
-public:
- static bool classof(const OpenACCClause *C) {
- return C->getClauseKind() == OpenACCClauseKind::Gang;
- }
-
- static OpenACCGangClause *
- Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
-
- child_range children() {
- return child_range(child_iterator(), child_iterator());
- }
- const_child_range children() const {
- return const_child_range(const_child_iterator(), const_child_iterator());
- }
-};
-
// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
// this provides a basic, do-nothing implementation. We still need to add this
// type to the visitors/etc, as well as get it to take its proper arguments.
@@ -177,7 +151,7 @@ class OpenACCVectorClause : public OpenACCClause {
class OpenACCWorkerClause : public OpenACCClause {
protected:
OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation EndLoc)
- : OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
+ : OpenACCClause(OpenACCClauseKind::Worker, BeginLoc, EndLoc) {
llvm_unreachable("Not yet implemented");
}
@@ -535,6 +509,38 @@ class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
};
+class OpenACCGangClause final
+ : public OpenACCClauseWithExprs,
+ public llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {
+protected:
+ OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<OpenACCGangKind> GangKinds,
+ ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
+
+ OpenACCGangKind getGangKind(unsigned I) const {
+ return getTrailingObjects<OpenACCGangKind>()[I];
+ }
+
+public:
+ static bool classof(const OpenACCClause *C) {
+ return C->getClauseKind() == OpenACCClauseKind::Gang;
+ }
+
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return getNumExprs();
+ }
+
+ unsigned getNumExprs() const { return getExprs().size(); }
+ std::pair<OpenACCGangKind, const Expr *> getExpr(unsigned I) const {
+ return {getGangKind(I), getExprs()[I]};
+ }
+
+ static OpenACCGangClause *
+ Create(const ASTContext &Ctx, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds,
+ ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
+};
+
class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc);
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 41cdd09e971651..3c62a017005e59 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12576,6 +12576,7 @@ def err_acc_duplicate_clause_disallowed
: Error<"OpenACC '%1' clause cannot appear more than once on a '%0' "
"directive">;
def note_acc_previous_clause_here : Note<"previous clause is here">;
+def note_acc_previous_expr_here : Note<"previous expression is here">;
def err_acc_branch_in_out_compute_construct
: Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
"OpenACC Compute Construct">;
@@ -12682,6 +12683,24 @@ def err_acc_insufficient_loops
def err_acc_intervening_code
: Error<"inner loops must be tightly nested inside a '%0' clause on "
"a 'loop' construct">;
+def err_acc_gang_multiple_elt
+ : Error<"OpenACC 'gang' clause may have at most one %select{unnamed or "
+ "'num'|'dim'|'static'}0 argument">;
+def err_acc_gang_arg_invalid
+ : Error<"'%0' argument on 'gang' clause is not permitted on a%select{n "
+ "orphaned|||}1 'loop' construct %select{|associated with a "
+ "'parallel' compute construct|associated with a 'kernels' compute "
+ "construct|associated with a 'serial' compute construct}1">;
+def err_acc_gang_dim_value
+ : Error<"argument to 'gang' clause dimension must be %select{a constant "
+ "expression|1, 2, or 3: evaluated to %1}0">;
+def err_acc_gang_num_gangs_conflict
+ : Error<"'num' argument to 'gang' clause not allowed on a 'loop' construct "
+ "associated with a 'kernels' construct that has a 'num_gangs' "
+ "clause">;
+def err_acc_gang_inside_gang
+ : Error<"loop with a 'gang' clause may not exist in the region of a 'gang' "
+ "clause on a 'kernels' compute construct">;
// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
diff --git a/clang/include/clang/Basic/OpenACCClauses.def b/clang/include/clang/Basic/OpenACCClauses.def
index a380e5ae69c418..2a098de31eb618 100644
--- a/clang/include/clang/Basic/OpenACCClauses.def
+++ b/clang/include/clang/Basic/OpenACCClauses.def
@@ -42,6 +42,7 @@ VISIT_CLAUSE(DevicePtr)
VISIT_CLAUSE(DeviceType)
CLAUSE_ALIAS(DType, DeviceType, false)
VISIT_CLAUSE(FirstPrivate)
+VISIT_CLAUSE(Gang)
VISIT_CLAUSE(If)
VISIT_CLAUSE(Independent)
VISIT_CLAUSE(NoCreate)
diff --git a/clang/include/clang/Basic/OpenACCKinds.h b/clang/include/clang/Basic/OpenACCKinds.h
index c4dfe3bedc13a7..3f48ebca708a42 100644
--- a/clang/include/clang/Basic/OpenACCKinds.h
+++ b/clang/include/clang/Basic/OpenACCKinds.h
@@ -550,6 +550,35 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
OpenACCReductionOperator Op) {
return printOpenACCReductionOperator(Out, Op);
}
+
+enum class OpenACCGangKind : uint8_t {
+ /// num:
+ Num,
+ /// dim:
+ Dim,
+ /// static:
+ Static
+};
+
+template <typename StreamTy>
+inline StreamTy &printOpenACCGangKind(StreamTy &Out, OpenACCGangKind GK) {
+ switch (GK) {
+ case OpenACCGangKind::Num:
+ return Out << "num";
+ case OpenACCGangKind::Dim:
+ return Out << "dim";
+ case OpenACCGangKind::Static:
+ return Out << "static";
+ }
+}
+inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
+ OpenACCGangKind Op) {
+ return printOpenACCGangKind(Out, Op);
+}
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
+ OpenACCGangKind Op) {
+ return printOpenACCGangKind(Out, Op);
+}
} // namespace clang
#endif // LLVM_CLANG_BASIC_OPENACCKINDS_H
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index dbcb545058a026..045ee754a242b3 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3797,9 +3797,15 @@ class Parser : public CodeCompletionHandler {
bool ParseOpenACCSizeExprList(OpenACCClauseKind CK,
llvm::SmallVectorImpl<Expr *> &SizeExprs);
/// Parses a 'gang-arg-list', used for the 'gang' clause.
- bool ParseOpenACCGangArgList(SourceLocation GangLoc);
- /// Parses a 'gang-arg', used for the 'gang' clause.
- bool ParseOpenACCGangArg(SourceLocation GangLoc);
+ bool ParseOpenACCGangArgList(SourceLocation GangLoc,
+ llvm::SmallVectorImpl<OpenACCGangKind> &GKs,
+ llvm::SmallVectorImpl<Expr *> &IntExprs);
+
+ using OpenACCGangArgRes = std::pair<OpenACCGangKind, ExprResult>;
+ /// Parses a 'gang-arg', used for the 'gang' clause. Returns a pair of the
+ /// ExprResult (which contains the validity of the expression), plus the gang
+ /// kind for the current argument.
+ OpenACCGangArgRes ParseOpenACCGangArg(SourceLocation GangLoc);
/// Parses a 'condition' expr, ensuring it results in a
ExprResult ParseOpenACCConditionExpr();
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index 97386d2378b758..59a9648d5f9380 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -38,9 +38,20 @@ class SemaOpenACC : public SemaBase {
/// haven't had their 'parent' compute construct set yet. Entires will only be
/// made to this list in the case where we know the loop isn't an orphan.
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
- /// Whether we are inside of a compute construct, and should add loops to the
- /// above collection.
- bool InsideComputeConstruct = false;
+
+ struct ComputeConstructInfo {
+ /// Which type of compute construct we are inside of, which we can use to
+ /// determine whether we should add loops to the above collection. We can
+ /// also use it to diagnose loop construct clauses.
+ OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
+ // If we have an active compute construct, stores the list of clauses we've
+ // prepared for it, so that we can diagnose limitations on child constructs.
+ ArrayRef<OpenACCClause *> Clauses;
+ } ActiveComputeConstructInfo;
+
+ bool isInComputeConstruct() const {
+ return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
+ }
/// Certain clauses care about the same things that aren't specific to the
/// individual clause, but can be shared by a few, so store them here. All
@@ -99,6 +110,15 @@ class SemaOpenACC : public SemaBase {
} TileInfo;
public:
+ ComputeConstructInfo &getActiveComputeConstructInfo() {
+ return ActiveComputeConstructInfo;
+ }
+
+ /// If there is a current 'active' loop construct with a 'gang' clause on a
+ /// 'kernel' construct, this will have the source location for it. This
+ /// permits us to implement the restriction of no further 'gang' clauses.
+ SourceLocation LoopGangClauseOnKernelLoc;
+
// Redeclaration of the version in OpenACCClause.h.
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
@@ -149,9 +169,14 @@ class SemaOpenACC : public SemaBase {
Expr *LoopCount;
};
+ struct GangDetails {
+ SmallVector<OpenACCGangKind> GangKinds;
+ SmallVector<Expr *> IntExprs;
+ };
+
std::variant<std::monostate, DefaultDetails, ConditionDetails,
IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
- ReductionDetails, CollapseDetails>
+ ReductionDetails, CollapseDetails, GangDetails>
Details = std::monostate{};
public:
@@ -245,9 +270,18 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Tile ||
+ ClauseKind == OpenACCClauseKind::Gang ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
+ if (ClauseKind == OpenACCClauseKind::Gang) {
+ // There might not be any gang int exprs, as this is an optional
+ // argument.
+ if (std::holds_alternative<std::monostate>(Details))
+ return {};
+ return std::get<GangDetails>(Details).IntExprs;
+ }
+
return std::get<IntExprDetails>(Details).IntExprs;
}
@@ -259,6 +293,16 @@ class SemaOpenACC : public SemaBase {
return std::get<ReductionDetails>(Details).Op;
}
+ ArrayRef<OpenACCGangKind> getGangKinds() const {
+ assert(ClauseKind == OpenACCClauseKind::Gang &&
+ "Parsed clause kind does not have gang kind");
+ // The args on gang are optional, so this might not actually hold
+ // anything.
+ if (std::holds_alternative<std::monostate>(Details))
+ return {};
+ return std::get<GangDetails>(Details).GangKinds;
+ }
+
ArrayRef<Expr *> getVarList() {
assert((ClauseKind == OpenACCClauseKind::Private ||
ClauseKind == OpenACCClauseKind::NoCreate ||
@@ -371,6 +415,25 @@ class SemaOpenACC : public SemaBase {
Details = IntExprDetails{std::move(IntExprs)};
}
+ void setGangDetails(ArrayRef<OpenACCGangKind> GKs,
+ ArrayRef<Expr *> IntExprs) {
+ assert(ClauseKind == OpenACCClauseKind::Gang &&
+ "Parsed Clause kind does not have gang details");
+ assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
+
+ Details = GangDetails{{GKs.begin(), GKs.end()},
+ {IntExprs.begin(), IntExprs.end()}};
+ }
+
+ void setGangDetails(llvm::SmallVector<OpenACCGangKind> &&GKs,
+ llvm::SmallVector<Expr *> &&IntExprs) {
+ assert(ClauseKind == OpenACCClauseKind::Gang &&
+ "Parsed Clause kind does not have gang details");
+ assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
+
+ Details = GangDetails{std::move(GKs), std::move(IntExprs)};
+ }
+
void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
bool IsZero) {
assert((ClauseKind == OpenACCClauseKind::Private ||
@@ -545,10 +608,12 @@ class SemaOpenACC : public SemaBase {
SourceLocation RBLoc);
/// Checks the loop depth value for a collapse clause.
ExprResult CheckCollapseLoopCount(Expr *LoopCount);
- /// Checks a single size expr for a tile clause. 'gang' could possibly call
- /// this, but has slightly stricter rules as to valid values.
+ /// Checks a single size expr for a tile clause.
ExprResult CheckTileSizeExpr(Expr *SizeExpr);
+ // Check a single expression on a gang clause.
+ ExprResult CheckGangExpr(OpenACCGangKind GK, Expr *E);
+
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
@@ -595,8 +660,9 @@ class SemaOpenACC : public SemaBase {
/// Loop needing its parent construct.
class AssociatedStmtRAII {
SemaOpenACC &SemaRef;
- bool WasInsideComputeConstruct;
+ ComputeConstructInfo OldActiveComputeConstructInfo;
OpenACCDirectiveKind DirKind;
+ SourceLocation OldLoopGangClauseOnKernelLoc;
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
LoopInConstructRAII LoopRAII;
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 0b34ed6189593e..6fb8fe0b8cfeef 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -26,7 +26,7 @@ bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
OpenACCTileClause::classof(C) ||
OpenACCClauseWithSingleIntExpr::classof(C) ||
- OpenACCClauseWithVarList::classof(C);
+ OpenACCGangClause::classof(C) || OpenACCClauseWithVarList::classof(C);
}
bool OpenACCClauseWithVarList::classof(const OpenACCClause *C) {
return OpenACCPrivateClause::classof(C) ||
@@ -125,6 +125,21 @@ OpenACCNumWorkersClause::OpenACCNumWorkersClause(SourceLocation BeginLoc,
"Condition expression type not scalar/dependent");
}
+OpenACCGangClause::OpenACCGangClause(SourceLocation BeginLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<OpenACCGangKind> GangKinds,
+ ArrayRef<Expr *> IntExprs,
+ SourceLocation EndLoc)
+ : OpenACCClauseWithExprs(OpenACCClauseKind::Gang, BeginLoc, LParenLoc,
+ EndLoc) {
+ assert(GangKinds.size() == IntExprs.size() && "Mismatch exprs/kind?");
+ std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
+ getTrailingObjects<Expr *>());
+ setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
+ std::uninitialized_copy(GangKinds.begin(), GangKinds.end(),
+ getTrailingObjects<OpenACCGangKind>());
+}
+
OpenACCNumWorkersClause *
OpenACCNumWorkersClause::Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
@@ -376,11 +391,16 @@ OpenACCSeqClause *OpenACCSeqClause::Create(const ASTContext &C,
return new (Mem) OpenACCSeqClause(BeginLoc, EndLoc);
}
-OpenACCGangClause *OpenACCGangClause::Create(const ASTContext &C,
- SourceLocation BeginLoc,
- SourceLocation EndLoc) {
- void *Mem = C.Allocate(sizeof(OpenACCGangClause));
- return new (Mem) OpenACCGangClause(BeginLoc, EndLoc);
+OpenACCGangClause *
+OpenACCGangClause::Create(const ASTContext &C, SourceLocation BeginLoc,
+ SourceLocation LParenLoc,
+ ArrayRef<OpenACCGangKind> GangKinds,
+ ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
+ void *Mem =
+ C.Allocate(OpenACCGangClause::totalSizeToAlloc<Expr *, OpenACCGangKind>(
+ IntExprs.size(), GangKinds.size()));
+ return new (Mem)
+ OpenACCGangClause(BeginLoc, LParenLoc, GangKinds, IntExprs, EndLoc);
}
OpenACCWorkerClause *OpenACCWorkerClause::Create(const ASTContext &C,
@@ -600,3 +620,21 @@ void OpenACCClausePrinter::VisitCollapseClause(const OpenACCCollapseClause &C) {
printExpr(C.getLoopCount());
OS << ")";
}
+
+void OpenACCClausePrinter::VisitGangClause(const OpenACCGangClause &C) {
+ OS << "gang";
+
+ if (C.getNumExprs() > 0) {
+ OS << "(";
+ bool first = true;
+ for (unsigned I = 0; I < C.getNumExprs(); ++I) {
+ if (!first)
+ OS << ", ";
+ first = false;
+
+ OS << C.getExpr(I).first << ": ";
+ printExpr(C.getExpr(I).second);
+ }
+ OS << ")";
+ }
+}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 4d177fd6c5968c..6161b1403ed35d 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2646,6 +2646,12 @@ void OpenACCClauseProfiler::VisitIndependentClause(
void OpenACCClauseProfiler::VisitSeqClause(const OpenACCSeqClause &Clause) {}
+void OpenACCClauseProfiler::VisitGangClause(const OpenACCGangClause &Clause) {
+ for (unsigned I = 0; I < Clause.getNumExprs(); ++I) {
+ Profiler.VisitStmt(Clause.getExpr(I).second);
+ }
+}
+
void OpenACCClauseProfiler::VisitReductionClause(
const OpenACCReductionClause &Clause) {
for (auto *E : Clause.getVarList())
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 15b23d60c3ffab..ac8c196777f9b8 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -425,6 +425,17 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
// but print 'clause' here so it is clear what is happening from the dump.
OS << " clause";
break;
+ case OpenACCClauseKind::Gang: {
+ OS << " clause";
+ // print the list of all GangKinds, so that there is some sort of
+ // relationship to the expressions listed afterwards.
+ auto *GC = cast<OpenACCGangClause>(C);
+
+ for (unsigned I = 0; I < GC->getNumExprs(); ++I) {
+ OS << " " << GC->getExpr(I).first;
+ }
+ break;
+ }
case OpenACCClauseKind::Collapse:
OS << " clause";
if (cast<OpenACCCollapseClause>(C)->hasForce())
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index b27e50b147f4a8..635039b724e6a0 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -797,23 +797,26 @@ bool Parser::ParseOpenACCSizeExprList(
/// [num:]int-expr
/// dim:int-expr
/// static:size-expr
-bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
+Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceL...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/112006
More information about the cfe-commits
mailing list