[clang] db81e8c - [OpenACC] Initial sema implementation of 'update' construct
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 7 08:20:28 PST 2025
Author: erichkeane
Date: 2025-01-07T08:20:20-08:00
New Revision: db81e8c42e121e62a00587b12d2b972dfcfb98c0
URL: https://github.com/llvm/llvm-project/commit/db81e8c42e121e62a00587b12d2b972dfcfb98c0
DIFF: https://github.com/llvm/llvm-project/commit/db81e8c42e121e62a00587b12d2b972dfcfb98c0.diff
LOG: [OpenACC] Initial sema implementation of 'update' construct
This executable construct has a larger list of clauses than some of the
others, plus has some additional restrictions. This patch implements
the AST node, plus the 'cannot be the body of a if, while, do, switch,
or label' statement restriction. Future patches will handle the
rest of the restrictions, which are based on clauses.
Added:
clang/test/AST/ast-print-openacc-update-construct.cpp
clang/test/SemaOpenACC/update-construct-ast.cpp
clang/test/SemaOpenACC/update-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/DiagnosticSemaKinds.td
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/SemaStmt.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/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 3f95f1db2fbe51..63d266dc60ec73 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2202,7 +2202,11 @@ enum CXCursorKind {
*/
CXCursor_OpenACCSetConstruct = 330,
- CXCursor_LastStmt = CXCursor_OpenACCSetConstruct,
+ /** OpenACC update Construct.
+ */
+ CXCursor_OpenACCUpdateConstruct = 331,
+
+ CXCursor_LastStmt = CXCursor_OpenACCUpdateConstruct,
/**
* Cursor that represents the translation unit itself.
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 92954cf566c832..d500f4eadef757 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -4082,6 +4082,8 @@ DEF_TRAVERSE_STMT(OpenACCShutdownConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
DEF_TRAVERSE_STMT(OpenACCSetConstruct,
{ TRY_TO(VisitOpenACCClauseList(S->clauses())); })
+DEF_TRAVERSE_STMT(OpenACCUpdateConstruct,
+ { 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 d3cc106ff00812..ebbee152f918f8 100644
--- a/clang/include/clang/AST/StmtOpenACC.h
+++ b/clang/include/clang/AST/StmtOpenACC.h
@@ -712,5 +712,44 @@ class OpenACCSetConstruct final
SourceLocation End,
ArrayRef<const OpenACCClause *> Clauses);
};
+// This class represents an 'update' construct, which has just a clause list.
+class OpenACCUpdateConstruct final
+ : public OpenACCConstructStmt,
+ private llvm::TrailingObjects<OpenACCUpdateConstruct,
+ const OpenACCClause *> {
+ friend TrailingObjects;
+ OpenACCUpdateConstruct(unsigned NumClauses)
+ : OpenACCConstructStmt(OpenACCUpdateConstructClass,
+ OpenACCDirectiveKind::Update, SourceLocation{},
+ SourceLocation{}, SourceLocation{}) {
+ std::uninitialized_value_construct(
+ getTrailingObjects<const OpenACCClause *>(),
+ getTrailingObjects<const OpenACCClause *>() + NumClauses);
+ setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
+ NumClauses));
+ }
+
+ OpenACCUpdateConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
+ SourceLocation End,
+ ArrayRef<const OpenACCClause *> Clauses)
+ : OpenACCConstructStmt(OpenACCUpdateConstructClass,
+ OpenACCDirectiveKind::Update, 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() == OpenACCUpdateConstructClass;
+ }
+ static OpenACCUpdateConstruct *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses);
+ static OpenACCUpdateConstruct *
+ 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 59cd3ce5c8fbbc..4aaae48ba8b42f 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -419,6 +419,7 @@ class TextNodeDumper
void VisitOpenACCInitConstruct(const OpenACCInitConstruct *S);
void VisitOpenACCSetConstruct(const OpenACCSetConstruct *S);
void VisitOpenACCShutdownConstruct(const OpenACCShutdownConstruct *S);
+ void VisitOpenACCUpdateConstruct(const OpenACCUpdateConstruct *S);
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
void VisitEmbedExpr(const EmbedExpr *S);
void VisitAtomicExpr(const AtomicExpr *AE);
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1a5541591a1608..70f87a104a9821 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12827,6 +12827,10 @@ def err_acc_loop_not_monotonic
"('++', '--', or compound assignment)">;
def err_acc_construct_one_clause_of
: Error<"OpenACC '%0' construct must have at least one %1 clause">;
+def err_acc_update_as_body
+ : Error<"OpenACC 'update' construct may not appear in place of the "
+ "statement following a%select{n if statement| while statement| do "
+ "statement| switch statement| label statement}0">;
// AMDGCN builtins diagnostics
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 2ecf19ef6252d9..ce2c48bd3c84e9 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -316,6 +316,7 @@ def OpenACCWaitConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCInitConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCShutdownConstruct : StmtNode<OpenACCConstructStmt>;
def OpenACCSetConstruct : StmtNode<OpenACCConstructStmt>;
+def OpenACCUpdateConstruct : 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 a46a7e133f1b2b..aac165130b7192 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -2025,6 +2025,7 @@ enum StmtCode {
STMT_OPENACC_INIT_CONSTRUCT,
STMT_OPENACC_SHUTDOWN_CONSTRUCT,
STMT_OPENACC_SET_CONSTRUCT,
+ STMT_OPENACC_UPDATE_CONSTRUCT,
// HLSL Constructs
EXPR_HLSL_OUT_ARG,
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index 889573f57b40a7..2b0ac716bab56f 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -284,3 +284,24 @@ OpenACCSetConstruct::Create(const ASTContext &C, SourceLocation Start,
auto *Inst = new (Mem) OpenACCSetConstruct(Start, DirectiveLoc, End, Clauses);
return Inst;
}
+
+OpenACCUpdateConstruct *
+OpenACCUpdateConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) {
+ void *Mem = C.Allocate(
+ OpenACCUpdateConstruct::totalSizeToAlloc<const OpenACCClause *>(
+ NumClauses));
+ auto *Inst = new (Mem) OpenACCUpdateConstruct(NumClauses);
+ return Inst;
+}
+
+OpenACCUpdateConstruct *
+OpenACCUpdateConstruct::Create(const ASTContext &C, SourceLocation Start,
+ SourceLocation DirectiveLoc, SourceLocation End,
+ ArrayRef<const OpenACCClause *> Clauses) {
+ void *Mem = C.Allocate(
+ OpenACCUpdateConstruct::totalSizeToAlloc<const OpenACCClause *>(
+ Clauses.size()));
+ auto *Inst =
+ new (Mem) OpenACCUpdateConstruct(Start, DirectiveLoc, End, Clauses);
+ return Inst;
+}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 52eead979b175a..52bcb5135d3513 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1204,10 +1204,12 @@ void StmtPrinter::VisitOpenACCInitConstruct(OpenACCInitConstruct *S) {
void StmtPrinter::VisitOpenACCShutdownConstruct(OpenACCShutdownConstruct *S) {
PrintOpenACCConstruct(S);
}
-
void StmtPrinter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
PrintOpenACCConstruct(S);
}
+void StmtPrinter::VisitOpenACCUpdateConstruct(OpenACCUpdateConstruct *S) {
+ PrintOpenACCConstruct(S);
+}
void StmtPrinter::VisitOpenACCWaitConstruct(OpenACCWaitConstruct *S) {
Indent() << "#pragma acc wait";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 150b92ef6a1abd..b68c83f99550b3 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2780,6 +2780,13 @@ void StmtProfiler::VisitOpenACCSetConstruct(const OpenACCSetConstruct *S) {
P.VisitOpenACCClauseList(S->clauses());
}
+void StmtProfiler::VisitOpenACCUpdateConstruct(
+ const OpenACCUpdateConstruct *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 00e3af3e811259..eedd8faad9e85f 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -2931,7 +2931,6 @@ void TextNodeDumper::VisitOpenACCConstructStmt(const OpenACCConstructStmt *S) {
OS << " " << S->getDirectiveKind();
}
void TextNodeDumper::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) {
-
if (S->isOrphanedLoopConstruct())
OS << " <orphan>";
else
@@ -2940,40 +2939,44 @@ void TextNodeDumper::VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S) {
void TextNodeDumper::VisitOpenACCCombinedConstruct(
const OpenACCCombinedConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCDataConstruct(const OpenACCDataConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCEnterDataConstruct(
const OpenACCEnterDataConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCExitDataConstruct(
const OpenACCExitDataConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCHostDataConstruct(
const OpenACCHostDataConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCWaitConstruct(const OpenACCWaitConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCInitConstruct(const OpenACCInitConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCShutdownConstruct(
const OpenACCShutdownConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitOpenACCSetConstruct(const OpenACCSetConstruct *S) {
- OS << " " << S->getDirectiveKind();
+ VisitOpenACCConstructStmt(S);
+}
+void TextNodeDumper::VisitOpenACCUpdateConstruct(
+ const OpenACCUpdateConstruct *S) {
+ VisitOpenACCConstructStmt(S);
}
void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 85be2b47c6f2ea..c8ff48fc733125 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -482,6 +482,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OpenACCSetConstructClass:
EmitOpenACCSetConstruct(cast<OpenACCSetConstruct>(*S));
break;
+ case Stmt::OpenACCUpdateConstructClass:
+ EmitOpenACCUpdateConstruct(cast<OpenACCUpdateConstruct>(*S));
+ break;
}
}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 0cd03c97ae99a7..bc612a0bfb32ba 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4142,6 +4142,11 @@ class CodeGenFunction : public CodeGenTypeCache {
// but in the future we will implement some sort of IR.
}
+ void EmitOpenACCUpdateConstruct(const OpenACCUpdateConstruct &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 94f59bbc0aa36a..ac5d51a1d2ff6e 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1402,6 +1402,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Stmt::OpenACCInitConstructClass:
case Stmt::OpenACCShutdownConstructClass:
case Stmt::OpenACCSetConstructClass:
+ case Stmt::OpenACCUpdateConstructClass:
// These expressions can never throw.
return CT_Cannot;
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 846b1966e765a9..1ab033cbbfc1a8 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -1936,6 +1936,7 @@ bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
case OpenACCDirectiveKind::Init:
case OpenACCDirectiveKind::Shutdown:
case OpenACCDirectiveKind::Set:
+ case OpenACCDirectiveKind::Update:
llvm_unreachable("Doesn't have an associated stmt");
default:
case OpenACCDirectiveKind::Invalid:
@@ -2365,6 +2366,7 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
case OpenACCDirectiveKind::Init:
case OpenACCDirectiveKind::Shutdown:
case OpenACCDirectiveKind::Set:
+ case OpenACCDirectiveKind::Update:
// Nothing to do here, there is no real legalization that needs to happen
// here as these constructs do not take any arguments.
break;
@@ -3713,6 +3715,9 @@ bool SemaOpenACC::ActOnStartStmtDirective(
OpenACCClauseKind::DeviceType,
OpenACCClauseKind::If});
+ // TODO: OpenACC: 'Update' construct needs to have one of 'self', 'host', or
+ // 'device'. Implement here.
+
return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
}
@@ -3780,6 +3785,10 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(
return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
EndLoc, Clauses);
}
+ case OpenACCDirectiveKind::Update: {
+ return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
+ EndLoc, Clauses);
+ }
}
llvm_unreachable("Unhandled case in directive handling?");
}
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index d9149f7ee40bbf..25a07d0315eac1 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -625,6 +625,15 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
if (getCurScope()->isInOpenACCComputeConstructScope())
setFunctionHasBranchProtectedScope();
+ // OpenACC3.3 2.14.4:
+ // The update directive is executable. It must not appear in place of the
+ // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or
+ // C++.
+ if (isa<OpenACCUpdateConstruct>(SubStmt)) {
+ Diag(SubStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*Label*/ 4;
+ SubStmt = new (Context) NullStmt(SubStmt->getBeginLoc());
+ }
+
// Otherwise, things are good. Fill in the declaration and return it.
LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
TheDecl->setStmt(LS);
@@ -1019,6 +1028,15 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc,
Diags.Report(IfLoc, diag::warn_consteval_if_always_true) << Immediate;
}
+ // OpenACC3.3 2.14.4:
+ // The update directive is executable. It must not appear in place of the
+ // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or
+ // C++.
+ if (isa<OpenACCUpdateConstruct>(thenStmt)) {
+ Diag(thenStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*if*/ 0;
+ thenStmt = new (Context) NullStmt(thenStmt->getBeginLoc());
+ }
+
return BuildIfStmt(IfLoc, StatementKind, LParenLoc, InitStmt, Cond, RParenLoc,
thenStmt, ElseLoc, elseStmt);
}
@@ -1297,6 +1315,16 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
getCurFunction()->SwitchStack.pop_back();
if (!BodyStmt) return StmtError();
+
+ // OpenACC3.3 2.14.4:
+ // The update directive is executable. It must not appear in place of the
+ // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or
+ // C++.
+ if (isa<OpenACCUpdateConstruct>(BodyStmt)) {
+ Diag(BodyStmt->getBeginLoc(), diag::err_acc_update_as_body) << /*switch*/ 3;
+ BodyStmt = new (Context) NullStmt(BodyStmt->getBeginLoc());
+ }
+
SS->setBody(BodyStmt, SwitchLoc);
Expr *CondExpr = SS->getCond();
@@ -1774,6 +1802,15 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc,
!Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc()))
CommaVisitor(*this).Visit(CondVal.second);
+ // OpenACC3.3 2.14.4:
+ // The update directive is executable. It must not appear in place of the
+ // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or
+ // C++.
+ if (isa<OpenACCUpdateConstruct>(Body)) {
+ Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << /*while*/ 1;
+ Body = new (Context) NullStmt(Body->getBeginLoc());
+ }
+
if (isa<NullStmt>(Body))
getCurCompoundScope().setHasEmptyLoopBodies();
@@ -1803,6 +1840,15 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
!Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc()))
CommaVisitor(*this).Visit(Cond);
+ // OpenACC3.3 2.14.4:
+ // The update directive is executable. It must not appear in place of the
+ // statement following an 'if', 'while', 'do', 'switch', or 'label' in C or
+ // C++.
+ if (isa<OpenACCUpdateConstruct>(Body)) {
+ Diag(Body->getBeginLoc(), diag::err_acc_update_as_body) << /*do*/ 2;
+ Body = new (Context) NullStmt(Body->getBeginLoc());
+ }
+
return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen);
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c40ff8b0d20111..bff1e5bd8f078e 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4178,6 +4178,15 @@ class TreeTransform {
SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {});
}
+ StmtResult RebuildOpenACCUpdateConstruct(SourceLocation BeginLoc,
+ SourceLocation DirLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OpenACCClause *> Clauses) {
+ return getSema().OpenACC().ActOnEndStmtDirective(
+ OpenACCDirectiveKind::Update, BeginLoc, DirLoc, SourceLocation{},
+ SourceLocation{}, {}, SourceLocation{}, EndLoc, Clauses, {});
+ }
+
StmtResult RebuildOpenACCWaitConstruct(
SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs,
@@ -12471,6 +12480,23 @@ TreeTransform<Derived>::TransformOpenACCSetConstruct(OpenACCSetConstruct *C) {
TransformedClauses);
}
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOpenACCUpdateConstruct(
+ OpenACCUpdateConstruct *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().RebuildOpenACCUpdateConstruct(
+ C->getBeginLoc(), C->getDirectiveLoc(), C->getEndLoc(),
+ TransformedClauses);
+}
+
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOpenACCWaitConstruct(OpenACCWaitConstruct *C) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 32e20c1508144a..4766f34e9f3a82 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2880,6 +2880,11 @@ void ASTStmtReader::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
VisitOpenACCConstructStmt(S);
}
+void ASTStmtReader::VisitOpenACCUpdateConstruct(OpenACCUpdateConstruct *S) {
+ VisitStmt(S);
+ VisitOpenACCConstructStmt(S);
+}
+
void ASTStmtReader::VisitOpenACCHostDataConstruct(OpenACCHostDataConstruct *S) {
VisitStmt(S);
VisitOpenACCAssociatedStmtConstruct(S);
@@ -4417,6 +4422,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = OpenACCSetConstruct::CreateEmpty(Context, NumClauses);
break;
}
+ case STMT_OPENACC_UPDATE_CONSTRUCT: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ S = OpenACCUpdateConstruct::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 de0e7bf5f176fc..7eedf7da7d3fc8 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2963,6 +2963,12 @@ void ASTStmtWriter::VisitOpenACCSetConstruct(OpenACCSetConstruct *S) {
Code = serialization::STMT_OPENACC_SET_CONSTRUCT;
}
+void ASTStmtWriter::VisitOpenACCUpdateConstruct(OpenACCUpdateConstruct *S) {
+ VisitStmt(S);
+ VisitOpenACCConstructStmt(S);
+ Code = serialization::STMT_OPENACC_UPDATE_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 70e95c2c644c09..ff8bdcea9a2201 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1833,6 +1833,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::OpenACCInitConstructClass:
case Stmt::OpenACCShutdownConstructClass:
case Stmt::OpenACCSetConstructClass:
+ case Stmt::OpenACCUpdateConstructClass:
case Stmt::OMPUnrollDirectiveClass:
case Stmt::OMPMetaDirectiveClass:
case Stmt::HLSLOutArgExprClass: {
diff --git a/clang/test/AST/ast-print-openacc-update-construct.cpp b/clang/test/AST/ast-print-openacc-update-construct.cpp
new file mode 100644
index 00000000000000..db9d1c0855c982
--- /dev/null
+++ b/clang/test/AST/ast-print-openacc-update-construct.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fopenacc -ast-print %s -o - | FileCheck %s
+void uses() {
+ // CHECK: #pragma acc update
+#pragma acc update
+}
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index 27970615c95811..3da06c3af63f37 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -343,23 +343,20 @@ struct HasMembersArray {
void SelfUpdate() {
struct Members s;
- // expected-error at +2{{expected '('}}
- // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
+ // expected-error at +1{{expected '('}}
#pragma acc update self
for(int i = 0; i < 5;++i) {}
- // expected-error at +6{{use of undeclared identifier 'zero'}}
- // expected-error at +5{{expected ','}}
- // expected-error at +4{{expected expression}}
- // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
- // expected-warning at +2{{OpenACC clause 'if_present' not yet implemented, clause ignored}}
- // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
+ // expected-error at +5{{use of undeclared identifier 'zero'}}
+ // expected-error at +4{{expected ','}}
+ // expected-error at +3{{expected expression}}
+ // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+ // expected-warning at +1{{OpenACC clause 'if_present' not yet implemented, clause ignored}}
#pragma acc update self(zero : s.array[s.value : 5], s.value), if_present
for(int i = 0; i < 5;++i) {}
- // expected-warning at +3{{OpenACC clause 'self' not yet implemented, clause ignored}}
- // expected-warning at +2{{OpenACC clause 'if_present' not yet implemented, clause ignored}}
- // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
+ // expected-warning at +2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+ // expected-warning at +1{{OpenACC clause 'if_present' not yet implemented, clause ignored}}
#pragma acc update self(s.array[s.value : 5], s.value), if_present
for(int i = 0; i < 5;++i) {}
}
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
index 7f090f828feb7c..9948e33ac94d1c 100644
--- a/clang/test/ParserOpenACC/parse-constructs.c
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -151,8 +151,7 @@ void func() {
// 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'}}
- // expected-warning at +1{{OpenACC construct 'update' not yet implemented, pragma ignored}}
+ // expected-error at +1{{invalid OpenACC clause 'clause'}}
#pragma acc update clause list
for(;;){}
}
diff --git a/clang/test/SemaOpenACC/update-construct-ast.cpp b/clang/test/SemaOpenACC/update-construct-ast.cpp
new file mode 100644
index 00000000000000..0e793428ec9b82
--- /dev/null
+++ b/clang/test/SemaOpenACC/update-construct-ast.cpp
@@ -0,0 +1,46 @@
+// 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 NormalFunc() {
+ // CHECK-LABEL: NormalFunc
+ // CHECK-NEXT: CompoundStmt
+
+#pragma acc update
+ // CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
+}
+
+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 update
+ // CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
+
+ // 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: OpenACCUpdateConstruct{{.*}}update
+}
+
+struct SomeStruct{
+ static constexpr unsigned value = 5;
+ operator unsigned();
+};
+void use() {
+ TemplFunc(SomeStruct{});
+}
+#endif
diff --git a/clang/test/SemaOpenACC/update-construct.cpp b/clang/test/SemaOpenACC/update-construct.cpp
new file mode 100644
index 00000000000000..3bada827a7a3cd
--- /dev/null
+++ b/clang/test/SemaOpenACC/update-construct.cpp
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 %s -fopenacc -verify
+
+void uses() {
+ int Var;
+ // expected-warning at +2{{OpenACC clause 'async' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update async self(Var)
+ // expected-warning at +2{{OpenACC clause 'wait' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update wait self(Var)
+ // expected-warning at +2{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented}}
+#pragma acc update self(Var) device_type(I)
+ // expected-warning at +2{{OpenACC clause 'if' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update if(true) self(Var)
+ // expected-warning at +2{{OpenACC clause 'if_present' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update if_present self(Var)
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update self(Var)
+ // expected-warning at +1{{OpenACC clause 'host' not yet implemented}}
+#pragma acc update host(Var)
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+
+ // TODO: OpenACC: These all should diagnose as they aren't allowed after
+ // device_type.
+ // expected-warning at +3{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented}}
+#pragma acc update self(Var) device_type(I) device_type(I)
+ // expected-warning at +3{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
+#pragma acc update self(Var) device_type(I) if(true)
+ // expected-warning at +3{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'if_present' not yet implemented}}
+#pragma acc update self(Var) device_type(I) if_present
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'self' not yet implemented}}
+#pragma acc update device_type(I) self(Var)
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'host' not yet implemented}}
+#pragma acc update device_type(I) host(Var)
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device_type(I) device(Var)
+ // These 2 are OK.
+ // expected-warning at +3{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'async' not yet implemented}}
+#pragma acc update self(Var) device_type(I) async
+ // expected-warning at +3{{OpenACC clause 'self' not yet implemented}}
+ // expected-warning at +2{{OpenACC clause 'device_type' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'wait' not yet implemented}}
+#pragma acc update self(Var) device_type(I) wait
+
+ // TODO: OpenACC: These should diagnose because there isn't at least 1 of
+ // 'self', 'host', or 'device'.
+ // expected-warning at +1{{OpenACC clause 'async' not yet implemented}}
+#pragma acc update async
+ // expected-warning at +1{{OpenACC clause 'wait' not yet implemented}}
+#pragma acc update wait
+ // expected-warning at +1{{OpenACC clause 'device_type' not yet implemented}}
+#pragma acc update device_type(I)
+ // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
+#pragma acc update if(true)
+ // expected-warning at +1{{OpenACC clause 'if_present' not yet implemented}}
+#pragma acc update if_present
+
+ // TODO: OpenACC: There should only be a max of 1 'if'.
+ // expected-warning at +2{{OpenACC clause 'if' not yet implemented}}
+ // expected-warning at +1{{OpenACC clause 'if' not yet implemented}}
+#pragma acc update if(true) if (false)
+
+ // TODO: OpenACC: There is restrictions on the contents of a 'varlist', so
+ // those should be checked here too.
+
+ // Cannot be the body of an 'if', 'while', 'do', 'switch', or
+ // 'label'.
+ // expected-error at +3{{OpenACC 'update' construct may not appear in place of the statement following an if statement}}
+ if (true)
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+
+ // expected-error at +3{{OpenACC 'update' construct may not appear in place of the statement following a while statement}}
+ while (true)
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+
+ // expected-error at +3{{OpenACC 'update' construct may not appear in place of the statement following a do statement}}
+ do
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+ while (true);
+
+ // expected-error at +3{{OpenACC 'update' construct may not appear in place of the statement following a switch statement}}
+ switch(Var)
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+
+ // expected-error at +3{{OpenACC 'update' construct may not appear in place of the statement following a label statement}}
+ LABEL:
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+
+ // For loops are OK.
+ for (;;)
+ // expected-warning at +1{{OpenACC clause 'device' not yet implemented}}
+#pragma acc update device(Var)
+}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 3e761024392cb2..4114d9a37f1ecd 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -6439,6 +6439,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OpenACCShutdownConstruct");
case CXCursor_OpenACCSetConstruct:
return cxstring::createRef("OpenACCSetConstruct");
+ case CXCursor_OpenACCUpdateConstruct:
+ return cxstring::createRef("OpenACCUpdateConstruct");
}
llvm_unreachable("Unhandled CXCursorKind");
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index cbc3485d419709..ee276d8e4e1481 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -912,6 +912,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
case Stmt::OpenACCSetConstructClass:
K = CXCursor_OpenACCSetConstruct;
break;
+ case Stmt::OpenACCUpdateConstructClass:
+ K = CXCursor_OpenACCUpdateConstruct;
+ break;
case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
K = CXCursor_OMPTargetParallelGenericLoopDirective;
break;
More information about the cfe-commits
mailing list