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@+2{{expected '('}} - // expected-warning@+1{{OpenACC construct 'update' not yet implemented, pragma ignored}} + // expected-error@+1{{expected '('}} #pragma acc update self for(int i = 0; i < 5;++i) {} - // expected-error@+6{{use of undeclared identifier 'zero'}} - // expected-error@+5{{expected ','}} - // expected-error@+4{{expected expression}} - // expected-warning@+3{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC clause 'if_present' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'update' not yet implemented, pragma ignored}} + // expected-error@+5{{use of undeclared identifier 'zero'}} + // expected-error@+4{{expected ','}} + // expected-error@+3{{expected expression}} + // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} + // expected-warning@+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@+3{{OpenACC clause 'self' not yet implemented, clause ignored}} - // expected-warning@+2{{OpenACC clause 'if_present' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'update' not yet implemented, pragma ignored}} + // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}} + // expected-warning@+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@+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@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'update' not yet implemented, pragma ignored}} + // expected-error@+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@+2{{OpenACC clause 'async' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update async self(Var) + // expected-warning@+2{{OpenACC clause 'wait' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update wait self(Var) + // expected-warning@+2{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented}} +#pragma acc update self(Var) device_type(I) + // expected-warning@+2{{OpenACC clause 'if' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update if(true) self(Var) + // expected-warning@+2{{OpenACC clause 'if_present' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update if_present self(Var) + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update self(Var) + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc update host(Var) + // expected-warning@+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@+3{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented}} +#pragma acc update self(Var) device_type(I) device_type(I) + // expected-warning@+3{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc update self(Var) device_type(I) if(true) + // expected-warning@+3{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'if_present' not yet implemented}} +#pragma acc update self(Var) device_type(I) if_present + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'self' not yet implemented}} +#pragma acc update device_type(I) self(Var) + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'host' not yet implemented}} +#pragma acc update device_type(I) host(Var) + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device_type(I) device(Var) + // These 2 are OK. + // expected-warning@+3{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+1{{OpenACC clause 'async' not yet implemented}} +#pragma acc update self(Var) device_type(I) async + // expected-warning@+3{{OpenACC clause 'self' not yet implemented}} + // expected-warning@+2{{OpenACC clause 'device_type' not yet implemented}} + // expected-warning@+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@+1{{OpenACC clause 'async' not yet implemented}} +#pragma acc update async + // expected-warning@+1{{OpenACC clause 'wait' not yet implemented}} +#pragma acc update wait + // expected-warning@+1{{OpenACC clause 'device_type' not yet implemented}} +#pragma acc update device_type(I) + // expected-warning@+1{{OpenACC clause 'if' not yet implemented}} +#pragma acc update if(true) + // expected-warning@+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@+2{{OpenACC clause 'if' not yet implemented}} + // expected-warning@+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@+3{{OpenACC 'update' construct may not appear in place of the statement following an if statement}} + if (true) + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device(Var) + + // expected-error@+3{{OpenACC 'update' construct may not appear in place of the statement following a while statement}} + while (true) + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device(Var) + + // expected-error@+3{{OpenACC 'update' construct may not appear in place of the statement following a do statement}} + do + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device(Var) + while (true); + + // expected-error@+3{{OpenACC 'update' construct may not appear in place of the statement following a switch statement}} + switch(Var) + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device(Var) + + // expected-error@+3{{OpenACC 'update' construct may not appear in place of the statement following a label statement}} + LABEL: + // expected-warning@+1{{OpenACC clause 'device' not yet implemented}} +#pragma acc update device(Var) + + // For loops are OK. + for (;;) + // expected-warning@+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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits