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@+2{{expected '('}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+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@+2{{expected expression}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+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@+2{{use of undeclared identifier 'invalid'}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+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@+3{{expected ')'}} // expected-note@+2{{to match this '('}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+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@+2{{OpenACC clause 'default_async' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented, clause ignored}} #pragma acc set default_async(5) - // expected-warning@+2{{OpenACC clause 'default_async' not yet implemented, clause ignored}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // expected-error@+2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-warning@+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@+2{{invalid OpenACC clause 'clause'}} - // expected-warning@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} + // 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'}} 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@+2{{OpenACC clause 'default_async' not yet implemented, clause ignored}} + // expected-error@+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@+1{{value of type 'struct NotConvertible' is not contextually convertible to 'bool'}} +#pragma acc set if (NC) device_type(I) + + // expected-error@+2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-error@+1{{OpenACC clause 'device_num' requires expression of integer type ('struct NotConvertible' invalid)}} +#pragma acc set device_num(NC) + // expected-error@+4{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-error@+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@+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@+2{{OpenACC clause 'default_async' requires expression of integer type ('struct NotConvertible' invalid)}} + // expected-error@+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@+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@+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@+4{{OpenACC integer expression requires explicit conversion from 'struct ExplicitConvertOnly' to 'int'}} + // expected-note@#EXPL_CONV{{conversion to integral type 'int'}} + // expected-error@+2{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented, clause ignored}} +#pragma acc set default_async(Explicit) + + // expected-error@+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@+3{{OpenACC 'set' construct must have at least one 'default_async', 'device_num', 'device_type' or 'if' clause}} + // expected-warning@+2{{OpenACC clause 'default_async' not yet implemented, clause ignored}} + // expected-warning@+1{{OpenACC clause 'default_async' not yet implemented, clause ignored}} +#pragma acc set default_async(getI()) default_async(getI()) + + // expected-error@+2{{'device_num' clause cannot appear more than once on a 'set' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc set device_num(getI()) device_num(getI()) + + // expected-error@+2{{'device_type' clause cannot appear more than once on a 'set' directive}} + // expected-note@+1{{previous clause is here}} +#pragma acc set device_type(I) device_type(I) + // expected-error@+2{{'if' clause cannot appear more than once on a 'set' directive}} + // expected-note@+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@+1{{OpenACC construct 'set' not yet implemented, pragma ignored}} -#pragma acc set +// expected-warning@+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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits