@@ -343,6 +343,18 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
343343 return false ;
344344 }
345345
346+ case OpenACCClauseKind::Collapse: {
347+ switch (DirectiveKind) {
348+ case OpenACCDirectiveKind::Loop:
349+ case OpenACCDirectiveKind::ParallelLoop:
350+ case OpenACCDirectiveKind::SerialLoop:
351+ case OpenACCDirectiveKind::KernelsLoop:
352+ return true ;
353+ default :
354+ return false ;
355+ }
356+ }
357+
346358 default :
347359 // Do nothing so we can go to the 'unimplemented' diagnostic instead.
348360 return true ;
@@ -1037,6 +1049,26 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
10371049 ValidVars, Clause.getEndLoc ());
10381050}
10391051
1052+ OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause (
1053+ SemaOpenACC::OpenACCParsedClause &Clause) {
1054+ // Duplicates here are not really sensible. We could possible permit
1055+ // multiples if they all had the same value, but there isn't really a good
1056+ // reason to do so. Also, this simplifies the suppression of duplicates, in
1057+ // that we know if we 'find' one after instantiation, that it is the same
1058+ // clause, which simplifies instantiation/checking/etc.
1059+ if (checkAlreadyHasClauseOfKind (SemaRef, ExistingClauses, Clause))
1060+ return nullptr ;
1061+
1062+ ExprResult LoopCount = SemaRef.CheckCollapseLoopCount (Clause.getLoopCount ());
1063+
1064+ if (!LoopCount.isUsable ())
1065+ return nullptr ;
1066+
1067+ return OpenACCCollapseClause::Create (Ctx, Clause.getBeginLoc (),
1068+ Clause.getLParenLoc (), Clause.isForce (),
1069+ LoopCount.get (), Clause.getEndLoc ());
1070+ }
1071+
10401072} // namespace
10411073
10421074SemaOpenACC::SemaOpenACC (Sema &S) : SemaBase(S) {}
@@ -1273,6 +1305,9 @@ ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
12731305 }
12741306 } IntExprDiagnoser(DK, CK, IntExpr);
12751307
1308+ if (!IntExpr)
1309+ return ExprError();
1310+
12761311 ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(
12771312 Loc, IntExpr, IntExprDiagnoser);
12781313 if (IntExprResult.isInvalid())
@@ -1583,6 +1618,34 @@ ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
15831618 OK_Ordinary, ColonLoc, RBLoc);
15841619}
15851620
1621+ ExprResult SemaOpenACC::CheckCollapseLoopCount (Expr *LoopCount) {
1622+ if (!LoopCount)
1623+ return ExprError ();
1624+
1625+ assert ((LoopCount->isInstantiationDependent () ||
1626+ LoopCount->getType ()->isIntegerType ()) &&
1627+ " Loop argument non integer?" );
1628+
1629+ // If this is dependent, there really isn't anything we can check.
1630+ if (LoopCount->isInstantiationDependent ())
1631+ return ExprResult{LoopCount};
1632+
1633+ std::optional<llvm::APSInt> ICE =
1634+ LoopCount->getIntegerConstantExpr (getASTContext ());
1635+
1636+ // OpenACC 3.3: 2.9.1
1637+ // The argument to the collapse clause must be a constant positive integer
1638+ // expression.
1639+ if (!ICE || *ICE <= 0 ) {
1640+ Diag (LoopCount->getBeginLoc (), diag::err_acc_collapse_loop_count)
1641+ << ICE.has_value () << ICE.value_or (llvm::APSInt{}).getExtValue ();
1642+ return ExprError ();
1643+ }
1644+
1645+ return ExprResult{
1646+ ConstantExpr::Create (getASTContext (), LoopCount, APValue{*ICE})};
1647+ }
1648+
15861649bool SemaOpenACC::ActOnStartStmtDirective (OpenACCDirectiveKind K,
15871650 SourceLocation StartLoc) {
15881651 SemaRef.DiscardCleanupsInEvaluationContext ();
0 commit comments