[clang] 21c785d - [OpenACC] Implement 'set' construct sema
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 6 11:03:24 PST 2025
Author: erichkeane
Date: 2025-01-06T11:03:18-08:00
New Revision: 21c785d7bd84df0b9176d48e7c3e74c914aae05a
URL: https://github.com/llvm/llvm-project/commit/21c785d7bd84df0b9176d48e7c3e74c914aae05a
DIFF: https://github.com/llvm/llvm-project/commit/21c785d7bd84df0b9176d48e7c3e74c914aae05a.diff
LOG: [OpenACC] Implement 'set' construct sema
The 'set' construct is another fairly simple one, it doesn't have an
associated statement and only a handful of allowed clauses. This patch
implements it and all the rules for it, allowing 3 of its for clauses.
The only exception is default_async, which will be implemented in a
future patch, because it isn't just being enabled, it needs a complete
new implementation.
Added:
clang/test/AST/ast-print-openacc-set-construct.cpp
clang/test/SemaOpenACC/set-construct-ast.cpp
clang/test/SemaOpenACC/set-construct.cpp
Modified:
clang/include/clang-c/Index.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/StmtOpenACC.h
clang/include/clang/AST/TextNodeDumper.h
clang/include/clang/Basic/StmtNodes.td
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/StmtOpenACC.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/SemaOpenACC.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/ParserOpenACC/parse-clauses.c
clang/test/ParserOpenACC/parse-constructs.c
clang/test/SemaOpenACC/unimplemented-construct.c
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/CXCursor.cpp
Removed:
################################################################################
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index dfc562da88afee..3f95f1db2fbe51 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2198,7 +2198,11 @@ enum CXCursorKind {
*/
CXCursor_OpenACCShutdownConstruct = 329,
- CXCursor_LastStmt = CXCursor_OpenACCShutdownConstruct,
+ /** OpenACC set Construct.
+ */
+ CXCursor_OpenACCSetConstruct = 330,
+
+ CXCursor_LastStmt = CXCursor_OpenACCSetConstruct,
/**
* Cursor that represents the translation unit itself.
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f5b32ed51698e0..92954cf566c832 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -4080,6 +4080,8 @@ DEF_TRAVERSE_STMT(OpenACCInitConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
DEF_TRAVERSE_STMT(OpenACCShutdownConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
+DEF_TRAVERSE_STMT(OpenACCSetConstruct,
+ { TRY_TO(VisitOpenACCClauseList(S->clauses())); })
// Traverse HLSL: Out argument expression
DEF_TRAVERSE_STMT(HLSLOutArgExpr, {})
diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h
index e311eded5599bb..d3cc106ff00812 100644
--- a/clang/include/clang/AST/StmtOpenACC.h
+++ b/clang/include/clang/AST/StmtOpenACC.h
@@ -672,5 +672,45 @@ class OpenACCShutdownConstruct final
SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
};
+// This class represents a 'set' construct, which has just a clause list.
+class OpenACCSetConstruct final
+ : public OpenACCConstructStmt,
+ private llvm::TrailingObjects<OpenACCSetConstruct,
+ const OpenACCClause *> {
+ friend TrailingObjects;
+ OpenACCSetConstruct(unsigned NumClauses)
+ : OpenACCConstructStmt(OpenACCSetConstructClass,
+ OpenACCDirectiveKind::Set, SourceLocation{},
+ SourceLocation{}, SourceLocation{}) {
+ std::uninitialized_value_construct(
+ getTrailingObjects<const OpenACCClause *>(),
+ getTrailingObjects<const OpenACCClause *>() + NumClauses);
+ setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
+ NumClauses));
+ }
+
+ OpenACCSetConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
+ SourceLocation End,
+ ArrayRef<const OpenACCClause *> Clauses)
+ : OpenACCConstructStmt(OpenACCSetConstructClass,
+ OpenACCDirectiveKind::Set, Start, DirectiveLoc,
+ End) {
+ std::uninitialized_copy(Clauses.begin(), Clauses.end(),
+ getTrailingObjects<const OpenACCClause *>());
+ setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
+ Clauses.size()));
+ }
+
+public:
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OpenACCSetConstructClass;
+ }
+ static OpenACCSetConstruct *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses);
+ static OpenACCSetConstruct *Create(const ASTContext &C, SourceLocation Start,
+ SourceLocation DirectiveLoc,
+ SourceLocation End,
+ ArrayRef<const OpenACCClause *> Clauses);
+};
} // namespace clang
#endif // LLVM_CLANG_AST_STMTOPENACC_H
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 5383b53fdc491b..59cd3ce5c8fbbc 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -417,6 +417,7 @@ class TextNodeDumper
void VisitOpenACCHostDataConstruct(const OpenACCHostDataConstruct *S);
void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S);
void VisitOpenACCInitConstruct(const OpenACCInitConstruct *S);
+ void VisitOpenACCSetConstruct(const OpenACCSetConstruct *S);
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S);
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
void VisitEmbedExpr(const EmbedExpr *S);
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 31280df93e4c6e..2ecf19ef6252d9 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -315,6 +315,7 @@ def OpenACCHostDataConstruct : StmtNode<OpenACCAssociatedStmtConstruct>;
def OpenACCWaitConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCInitConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>;
+def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>;
// OpenACC Additional Expressions.
def OpenACCAsteriskSizeExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index dfd82afad40070..a46a7e133f1b2b 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -2024,6 +2024,7 @@ enum StmtCode {
STMT_OPENACC_WAIT_CONSTRUCT,
STMT_OPENACC_INIT_CONSTRUCT,
STMT_OPENACC_SHUTDOWN_CONSTRUCT,
+ STMT_OPENACC_SET_CONSTRUCT,
// HLSL Constructs
EXPR_HLSL_OUT_ARG,
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index e6d76ea30f0294..889573f57b40a7 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -265,3 +265,22 @@ OpenACCShutdownConstruct *OpenACCShutdownConstruct::Create(
new (Mem) OpenACCShutdownConstruct(Start, DirectiveLoc, End, Clauses);
return Inst;
}
+
+OpenACCSetConstruct *OpenACCSetConstruct::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses) {
+ void *Mem = C.Allocate(
+ OpenACCSetConstruct::totalSizeToAlloc<const OpenACCClause *>(NumClauses));
+ auto *Inst = new (Mem) OpenACCSetConstruct(NumClauses);
+ return Inst;
+}
+
+OpenACCSetConstruct *
+OpenACCSetConstruct::Create(const ASTContext &C, SourceLocation Start,
+ SourceLocation DirectiveLoc, SourceLocation End,
+ ArrayRef<const OpenACCClause *> Clauses) {
+ void *Mem =
+ C.Allocate(OpenACCSetConstruct::totalSizeToAlloc<const OpenACCClause *>(
+ Clauses.size()));
+ auto *Inst = new (Mem) OpenACCSetConstruct(Start, DirectiveLoc, End, Clauses);
+ return Inst;
+}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index c5d19f70fc6ea0..52eead979b175a 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1205,6 +1205,10 @@ void StmtPrinter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
PrintOpenACCConstruct(S);
}
+void StmtPrinter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
+ PrintOpenACCConstruct(S);
+}
+
void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
Indent() << "#pragma acc wait";
if (!S->getLParenLoc().isInvalid()) {
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 27313f9ae12752..f516e67e4b8614 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2769,6 +2769,12 @@ void StmtProfiler::VisitOpenACCShutdownConstruct(
P.VisitOpenACCClauseList(S->clauses());
}
+void StmtProfiler::VisitOpenACCSetConstruct(const OpenACCSetConstruct *S) {
+ VisitStmt(S);
+ OpenACCClauseProfiler P{*this};
+ P.VisitOpenACCClauseList(S->clauses());
+}
+
void StmtProfiler::VisitHLSLOutArgExpr(const HLSLOutArgExpr *S) {
VisitStmt(S);
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 018147e68aba60..d74020048060de 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -2971,6 +2971,9 @@ void TextNodeDumper::VisitOpenACCShutdownConstruct(
const OpenACCShutdownConstruct *S) {
OS << " " << S->getDirectiveKind();
}
+void TextNodeDumper::VisitOpenACCSetConstruct(const OpenACCSetConstruct *S) {
+ OS << " " << S->getDirectiveKind();
+}
void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
AddChild("begin", [=] { OS << S->getStartingElementPos(); });
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index f1a75cdfeda7d7..85be2b47c6f2ea 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -479,6 +479,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OpenACCShutdownConstructClass:
EmitOpenACCShutdownConstruct(cast<OpenACCShutdownConstruct>(*S));
break;
+ case Stmt::OpenACCSetConstructClass:
+ EmitOpenACCSetConstruct(cast<OpenACCSetConstruct>(*S));
+ break;
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index ff421130e8328f..0cd03c97ae99a7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4137,6 +4137,11 @@ class CodeGenFunction : public CodeGenTypeCache {
// but in the future we will implement some sort of IR.
}
+ void EmitOpenACCSetConstruct(const OpenACCSetConstruct &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
//===--------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index ac3666394d0e86..94f59bbc0aa36a 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1401,6 +1401,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OpenACCWaitConstructClass:
case Stmt::OpenACCInitConstructClass:
case Stmt::OpenACCShutdownConstructClass:
+ case Stmt::OpenACCSetConstructClass:
// These expressions can never throw.
return CT_Cannot;
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 42bbdf1f3f9fa9..a23bdcf001c506 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -587,7 +587,8 @@ bool isDirectiveKindImplemented(OpenACCDirectiveKind DK) {
isOpenACCCombinedDirectiveKind(DK) || isOpenACCDataDirectiveKind(DK) ||
DK == OpenACCDirectiveKind::Loop || DK == OpenACCDirectiveKind::Wait ||
DK == OpenACCDirectiveKind::Init ||
- DK == OpenACCDirectiveKind::Shutdown;
+ DK == OpenACCDirectiveKind::Shutdown ||
+ DK == OpenACCDirectiveKind::Set;
}
class SemaOpenACCClauseVisitor {
@@ -709,9 +710,9 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
// There is no prose in the standard that says duplicates aren't allowed,
// but this diagnostic is present in other compilers, as well as makes
- // sense. Prose DOES exist for 'data' and 'host_data', 'enter data' and 'exit
- // data' both don't, but other implmementations do this. OpenACC issue 519
- // filed for the latter two.
+ // sense. Prose DOES exist for 'data' and 'host_data', 'set', 'enter data' and
+ // 'exit data' both don't, but other implmementations do this. OpenACC issue
+ // 519 filed for the latter two.
// GCC allows this on init/shutdown, presumably for good reason, so we do too.
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Init &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Shutdown &&
@@ -963,6 +964,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
return isNotImplemented();
+ // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
+ // same directive.
+ if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
+ checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
+ return nullptr;
+
assert(Clause.getNumIntExprs() == 1 &&
"Invalid number of expressions for device_num");
return OpenACCDeviceNumClause::Create(
@@ -1177,6 +1184,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
return isNotImplemented();
+ // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
+ // same directive.
+ if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
+ checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
+ return nullptr;
+
// TODO OpenACC: Once we get enough of the CodeGen implemented that we have
// a source for the list of valid architectures, we need to warn on unknown
// identifiers here.
@@ -1900,6 +1913,7 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
case OpenACCDirectiveKind::Wait:
case OpenACCDirectiveKind::Init:
case OpenACCDirectiveKind::Shutdown:
+ case OpenACCDirectiveKind::Set:
llvm_unreachable("Doesn't have an associated stmt");
default:
case OpenACCDirectiveKind::Invalid:
@@ -2328,6 +2342,7 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
case OpenACCDirectiveKind::HostData:
case OpenACCDirectiveKind::Init:
case OpenACCDirectiveKind::Shutdown:
+ case OpenACCDirectiveKind::Set:
// Nothing to do here, there is no real legalization that needs to happen
// here as these constructs do not take any arguments.
break;
@@ -3661,6 +3676,24 @@ bool SemaOpenACC::ActOnStartStmtDirective(
return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
<< K << GetListOfClauses({OpenACCClauseKind::UseDevice});
+ // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
+ // clause must appear.
+ if (K == OpenACCDirectiveKind::Set &&
+ llvm::find_if(
+ Clauses,
+ llvm::IsaPred</*OpenACCDefaultAsyncClause,*/ // TODO: ERICH Need to
+ // implement.
+ // DefaultAsyncClause
+ // then enable this.
+ OpenACCDeviceNumClause, OpenACCDeviceTypeClause,
+ OpenACCIfClause>) == Clauses.end())
+ return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
+ << K
+ << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
+ OpenACCClauseKind::DeviceNum,
+ OpenACCClauseKind::DeviceType,
+ OpenACCClauseKind::If});
+
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
}
@@ -3724,6 +3757,10 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(
return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
EndLoc, Clauses);
}
+ case OpenACCDirectiveKind::Set: {
+ return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
+ EndLoc, Clauses);
+ }
}
llvm_unreachable("Unhandled case in directive handling?");
}
@@ -3739,6 +3776,7 @@ StmtResult SemaOpenACC::ActOnAssociatedStmt(
case OpenACCDirectiveKind::Wait:
case OpenACCDirectiveKind::Init:
case OpenACCDirectiveKind::Shutdown:
+ case OpenACCDirectiveKind::Set:
llvm_unreachable(
"these don't have associated statements, so shouldn't get here");
case OpenACCDirectiveKind::Parallel:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 0121be81bc6acd..1d25efb1d45c92 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4169,6 +4169,15 @@ class TreeTransform {
SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {});
}
+ StmtResult RebuildOpenACCSetConstruct(SourceLocation BeginLoc,
+ SourceLocation DirLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OpenACCClause *> Clauses) {
+ return getSema().OpenACC().ActOnEndStmtDirective(
+ OpenACCDirectiveKind::Set, BeginLoc, DirLoc, SourceLocation{},
+ SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {});
+ }
+
StmtResult RebuildOpenACCWaitConstruct(
SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs,
@@ -12422,6 +12431,22 @@ StmtResult TreeTransform<Derived>::TransformOpenACCShutdownConstruct(
C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(),
TransformedClauses);
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOpenACCSetConstruct(OpenACCSetConstruct *C) {
+ getSema().OpenACC().ActOnConstruct(C->getDirectiveKind(), C->getBeginLoc());
+
+ llvm::SmallVector<OpenACCClause *> TransformedClauses =
+ getDerived().TransformOpenACCClauseList(C->getDirectiveKind(),
+ C->clauses());
+ if (getSema().OpenACC().ActOnStartStmtDirective(
+ C->getDirectiveKind(), C->getBeginLoc(), TransformedClauses))
+ return StmtError();
+
+ return getDerived().RebuildOpenACCSetConstruct(
+ C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(),
+ TransformedClauses);
+}
template <typename Derived>
StmtResult
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 9e8cf19a6f0f72..32e20c1508144a 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2875,6 +2875,11 @@ void ASTStmtReader::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
VisitOpenACCConstructStmt(S);
}
+void ASTStmtReader::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
+ VisitStmt(S);
+ VisitOpenACCConstructStmt(S);
+}
+
void ASTStmtReader::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) {
VisitStmt(S);
VisitOpenACCAssociatedStmtConstruct(S);
@@ -4407,6 +4412,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = OpenACCShutdownConstruct::CreateEmpty(Context, NumClauses);
break;
}
+ case STMT_OPENACC_SET_CONSTRUCT: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ S = OpenACCSetConstruct::CreateEmpty(Context, NumClauses);
+ break;
+ }
case EXPR_REQUIRES: {
unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields];
unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1];
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 1d42b43c3e2ca0..de0e7bf5f176fc 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2957,6 +2957,12 @@ void ASTStmtWriter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
Code = serialization::STMT_OPENACC_SHUTDOWN_CONSTRUCT;
}
+void ASTStmtWriter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
+ VisitStmt(S);
+ VisitOpenACCConstructStmt(S);
+ Code = serialization::STMT_OPENACC_SET_CONSTRUCT;
+}
+
void ASTStmtWriter::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) {
VisitStmt(S);
VisitOpenACCAssociatedStmtConstruct(S);
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 362a985b9174a8..70e95c2c644c09 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1832,6 +1832,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OpenACCWaitConstructClass:
case Stmt::OpenACCInitConstructClass:
case Stmt::OpenACCShutdownConstructClass:
+ case Stmt::OpenACCSetConstructClass:
case Stmt::OMPUnrollDirectiveClass:
case Stmt::OMPMetaDirectiveClass:
case Stmt::HLSLOutArgExprClass: {
diff --git a/clang/test/AST/ast-print-openacc-set-construct.cpp b/clang/test/AST/ast-print-openacc-set-construct.cpp
new file mode 100644
index 00000000000000..11e17bd274ea15
--- /dev/null
+++ b/clang/test/AST/ast-print-openacc-set-construct.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -fopenacc -ast-print %s -o - | FileCheck %s
+
+unsigned Int;
+
+void uses() {
+// CHECK: #pragma acc set if(Int == 5) device_type(I) device_num(Int)
+#pragma acc set default_async(Int) if (Int == 5) device_type(I) device_num(Int)
+// CHECK: #pragma acc set device_type(I) device_num(Int)
+#pragma acc set default_async(Int) device_type(I) device_num(Int)
+// CHECK: #pragma acc set if(Int == 5) device_num(Int)
+#pragma acc set default_async(Int) if (Int == 5) device_num(Int)
+// CHECK: #pragma acc set if(Int == 5) device_type(I)
+#pragma acc set default_async(Int) if (Int == 5) device_type(I)
+// CHECK: #pragma acc set if(Int == 5) device_type(I) device_num(Int)
+#pragma acc set if (Int == 5) device_type(I) device_num(Int)
+// CHECK-NOT: default_async(Int)
+// TODO: OpenACC: Enable this when we have default_async implemented.
+// #pragma acc set default_async(Int)
+// CHECK: #pragma acc set if(Int == 5)
+#pragma acc set if (Int == 5)
+// CHECK: #pragma acc set device_type(I)
+#pragma acc set device_type(I)
+// CHECK: #pragma acc set device_num(Int)
+#pragma acc set device_num(Int)
+}
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index 8a404a5a1987d4..748931072bbf03 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -821,28 +821,28 @@ void IntExprParsing() {
#pragma acc init device_num(returns_int())
// expected-error at +2{{expected '('}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
#pragma acc set default_async
// expected-error at +2{{expected expression}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
#pragma acc set default_async()
// expected-error at +2{{use of undeclared identifier 'invalid'}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
#pragma acc set default_async(invalid)
// expected-error at +3{{expected ')'}}
// expected-note at +2{{to match this '('}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
#pragma acc set default_async(5, 4)
- // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-warning at +1{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
#pragma acc set default_async(5)
- // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-warning at +1{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
#pragma acc set default_async(returns_int())
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
index 878c38e8bedc72..7f090f828feb7c 100644
--- a/clang/test/ParserOpenACC/parse-constructs.c
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -148,7 +148,7 @@ void func() {
#pragma acc shutdown clause list
for(;;){}
// expected-error at +2{{invalid OpenACC clause 'clause'}}
- // expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
#pragma acc set clause list
for(;;){}
// expected-error at +2{{invalid OpenACC clause 'clause'}}
diff --git a/clang/test/SemaOpenACC/set-construct-ast.cpp b/clang/test/SemaOpenACC/set-construct-ast.cpp
new file mode 100644
index 00000000000000..2553378c51283d
--- /dev/null
+++ b/clang/test/SemaOpenACC/set-construct-ast.cpp
@@ -0,0 +1,87 @@
+// 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
+
+int some_int();
+long some_long();
+void NormalFunc() {
+ // CHECK-LABEL: NormalFunc
+ // CHECK-NEXT: CompoundStmt
+
+#pragma acc set default_async(some_int()) device_num(some_long()) device_type(DT) if (some_int() < some_long())
+ // CHECK-NEXT: OpenACCSetConstruct{{.*}}set
+ // CHECK-NEXT: device_num clause
+ // CHECK-NEXT: CallExpr{{.*}} 'long'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()'
+ // CHECK-NEXT: device_type(DT)
+ // CHECK-NEXT: if clause
+ // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
+ // CHECK-NEXT: ImplicitCastExpr{{.*}}'long'
+ // CHECK-NEXT: CallExpr{{.*}}'int'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'some_int' 'int ()'
+ // CHECK-NEXT: CallExpr{{.*}} 'long'
+ // CHECK-NEXT: ImplicitCastExpr
+ // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()'
+}
+
+template<typename T>
+void TemplFunc(T t) {
+ // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc
+ // CHECK-NEXT: TemplateTypeParmDecl
+ // CHECK-NEXT: FunctionDecl{{.*}}TemplFunc
+ // CHECK-NEXT: ParmVarDecl{{.*}} t 'T'
+ // CHECK-NEXT: CompoundStmt
+
+#pragma acc set default_async(T::value) device_num(t) device_type(DT) if (T::value < t)
+ // CHECK-NEXT: OpenACCSetConstruct{{.*}}set
+ // CHECK-NEXT: device_num clause
+ // CHECK-NEXT: DeclRefExpr{{.*}}'t' 'T'
+ // CHECK-NEXT: device_type(DT)
+ // CHECK-NEXT: if clause
+ // CHECK-NEXT: BinaryOperator{{.*}}'<dependent type>' '<'
+ // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}} '<dependent type>'
+ // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T'
+ // CHECK-NEXT: DeclRefExpr{{.*}}'t' 'T'
+
+ // Instantiation:
+ // CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void (SomeStruct)' implicit_instantiation
+ // CHECK-NEXT: TemplateArgument type 'SomeStruct'
+ // CHECK-NEXT: RecordType{{.*}} 'SomeStruct'
+ // CHECK-NEXT: CXXRecord{{.*}} 'SomeStruct'
+ // CHECK-NEXT: ParmVarDecl{{.*}} t 'SomeStruct'
+ // CHECK-NEXT: CompoundStmt
+
+ // CHECK-NEXT: OpenACCSetConstruct{{.*}}set
+ // CHECK-NEXT: device_num clause
+ // CHECK-NEXT: ImplicitCastExpr {{.*}}'unsigned int'
+ // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int'
+ // CHECK-NEXT: MemberExpr{{.*}}.operator unsigned int
+ // CHECK-NEXT: DeclRefExpr{{.*}}'t' 'SomeStruct'
+ // CHECK-NEXT: device_type(DT)
+ // CHECK-NEXT: if clause
+ // CHECK-NEXT: BinaryOperator{{.*}}'bool' '<'
+ // CHECK-NEXT: ImplicitCastExpr {{.*}}'unsigned int'
+ // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int'
+ // CHECK-NEXT: NestedNameSpecifier TypeSpec 'SomeStruct'
+ // CHECK-NEXT: ImplicitCastExpr {{.*}}'unsigned int'
+ // CHECK-NEXT: CXXMemberCallExpr{{.*}}'unsigned int'
+ // CHECK-NEXT: MemberExpr{{.*}}.operator unsigned int
+ // CHECk-NEXT: DeclRefExpr{{.*}}'t' 'SomeStruct'
+}
+
+struct SomeStruct{
+ static constexpr unsigned value = 5;
+ operator unsigned();
+};
+
+void use() {
+ TemplFunc(SomeStruct{});
+}
+#endif
diff --git a/clang/test/SemaOpenACC/set-construct.cpp b/clang/test/SemaOpenACC/set-construct.cpp
new file mode 100644
index 00000000000000..196bbdbc1d0481
--- /dev/null
+++ b/clang/test/SemaOpenACC/set-construct.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 %s -fopenacc -verify
+
+struct NotConvertible{} NC;
+short getS();
+int getI();
+
+struct AmbiguousConvert{
+ operator int(); // #AMBIG_INT
+ operator short(); // #AMBIG_SHORT
+ operator float();
+} Ambiguous;
+
+struct ExplicitConvertOnly {
+ explicit operator int() const; // #EXPL_CONV
+} Explicit;
+
+void uses() {
+ // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+#pragma acc set default_async(getI())
+#pragma acc set device_num(getI())
+#pragma acc set device_type(getI)
+#pragma acc set device_type(getI) if (getI() < getS())
+
+ // expected-error at +1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}}
+#pragma acc set if (NC) device_type(I)
+
+ // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +1{{OpenACC clause 'device_num' requires expression of integer type ('struct NotConvertible' invalid)}}
+#pragma acc set device_num(NC)
+ // expected-error at +4{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-error at +3{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}}
+ // expected-note@#AMBIG_INT{{conversion to integral type 'int'}}
+ // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}}
+#pragma acc set device_num(Ambiguous)
+ // expected-error at +2{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}}
+ // expected-note@#EXPL_CONV{{conversion to integral type 'int'}}
+#pragma acc set device_num(Explicit)
+
+ // expected-error at +2{{OpenACC clause 'default_async' requires expression of integer type ('struct NotConvertible' invalid)}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+#pragma acc set default_async(NC)
+ // expected-error at +4{{multiple conversions from expression type 'struct AmbiguousConvert' to an integral type}}
+ // expected-note@#AMBIG_INT{{conversion to integral type 'int'}}
+ // expected-note@#AMBIG_SHORT{{conversion to integral type 'short'}}
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+#pragma acc set default_async(Ambiguous)
+ // expected-error at +4{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}}
+ // expected-note@#EXPL_CONV{{conversion to integral type 'int'}}
+ // expected-error at +2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-warning at +1{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+#pragma acc set default_async(Explicit)
+
+ // expected-error at +1{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+#pragma acc set
+
+#pragma acc set if (true)
+
+ // expected-error at +3{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}}
+ // expected-warning at +2{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+ // expected-warning at +1{{OpenACC clause 'default_async' not yet implemented, clause ignored}}
+#pragma acc set default_async(getI()) default_async(getI())
+
+ // expected-error at +2{{'device_num' clause cannot appear more than once on a 'set' directive}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc set device_num(getI()) device_num(getI())
+
+ // expected-error at +2{{'device_type' clause cannot appear more than once on a 'set' directive}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc set device_type(I) device_type(I)
+ // expected-error at +2{{'if' clause cannot appear more than once on a 'set' directive}}
+ // expected-note at +1{{previous clause is here}}
+#pragma acc set device_type(I) if(true) if (true)
+}
diff --git a/clang/test/SemaOpenACC/unimplemented-construct.c b/clang/test/SemaOpenACC/unimplemented-construct.c
index 42737eb08d93fe..b22bfa5a69bb0e 100644
--- a/clang/test/SemaOpenACC/unimplemented-construct.c
+++ b/clang/test/SemaOpenACC/unimplemented-construct.c
@@ -4,8 +4,8 @@
#pragma acc routine
struct S {
-// expected-warning at +1{{OpenACC construct 'set' not yet implemented, pragma ignored}}
-#pragma acc set
+// expected-warning at +1{{OpenACC construct 'declare' not yet implemented, pragma ignored}}
+#pragma acc declare
int foo;
};
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 7967c10f9f713e..ce83014a6e9eee 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2192,6 +2192,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>,
void VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *D);
void VisitOpenACCInitConstruct(const OpenACCInitConstruct *D);
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *D);
+ void VisitOpenACCSetConstruct(const OpenACCSetConstruct *D);
void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
void VisitOMPLoopBasedDirective(const OMPLoopBasedDirective *D);
void VisitOMPLoopDirective(const OMPLoopDirective *D);
@@ -3658,6 +3659,12 @@ void EnqueueVisitor::VisitOpenACCShutdownConstruct(
EnqueueChildren(Clause);
}
+void EnqueueVisitor::VisitOpenACCSetConstruct(const OpenACCSetConstruct *C) {
+ EnqueueChildren(C);
+ for (auto *Clause : C->clauses())
+ EnqueueChildren(Clause);
+}
+
void EnqueueVisitor::VisitAnnotateAttr(const AnnotateAttr *A) {
EnqueueChildren(A);
}
@@ -6426,6 +6433,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OpenACCInitConstruct");
case CXCursor_OpenACCShutdownConstruct:
return cxstring::createRef("OpenACCShutdownConstruct");
+ case CXCursor_OpenACCSetConstruct:
+ return cxstring::createRef("OpenACCSetConstruct");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index f56e77b42f9d73..cbc3485d419709 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -909,6 +909,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OpenACCShutdownConstructClass:
K = CXCursor_OpenACCShutdownConstruct;
break;
+ case Stmt::OpenACCSetConstructClass:
+ K = CXCursor_OpenACCSetConstruct;
+ break;
case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
K = CXCursor_OMPTargetParallelGenericLoopDirective;
break;
More information about the cfe-commits
mailing list