diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2719,6 +2719,8 @@ "use of this statement in a constexpr %select{function|constructor}0 " "is incompatible with C++ standards before C++2b">, InGroup, DefaultIgnore; +def err_constexpr_body_invalid_omp_simd_stmt_with_clauses : Error< + "OpenMP simd statement with clauses not allowed in %select{constexpr|consteval}1 %select{function|constructor}0">; def ext_constexpr_type_definition : ExtWarn< "type definition in a constexpr %select{function|constructor}0 " "is a C++14 extension">, InGroup; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5489,6 +5489,13 @@ case Stmt::CXXTryStmtClass: // Evaluate try blocks by evaluating all sub statements. return EvaluateStmt(Result, Info, cast(S)->getTryBlock(), Case); + + case Stmt::OMPSimdDirectiveClass: { + const Stmt *LoopStmt = cast(S)->getAssociatedStmt(); + if (auto *CS = dyn_cast(LoopStmt)) + LoopStmt = CS->getCapturedStmt(); + return EvaluateStmt(Result, Info, LoopStmt, Case); + } } } @@ -8271,7 +8278,8 @@ // variable) or be ill-formed (and trigger an appropriate evaluation // diagnostic)). CallStackFrame *CurrFrame = Info.CurrentCall; - if (CurrFrame->Callee && CurrFrame->Callee->Equals(VD->getDeclContext())) { + if (CurrFrame->Callee && + CurrFrame->Callee->Encloses(VD->getDeclContext())) { // Function parameters are stored in some caller's frame. (Usually the // immediate caller, but for an inherited constructor they may be more // distant.) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2169,6 +2169,23 @@ return false; return true; + case Stmt::OMPSimdDirectiveClass: { + if (!cast(S)->clauses().empty()) { + if (Kind == Sema::CheckConstexprKind::Diagnose) { + SemaRef.Diag( + S->getBeginLoc(), + diag::err_constexpr_body_invalid_omp_simd_stmt_with_clauses) + << isa(Dcl) << Dcl->isConsteval(); + } + return false; + } + Stmt *LoopStmt = cast(S)->getAssociatedStmt(); + if (auto *CS = dyn_cast(LoopStmt)) + LoopStmt = CS->getCapturedStmt(); + return CheckConstexprFunctionStmt(SemaRef, Dcl, LoopStmt, ReturnStmts, + Cxx1yLoc, Cxx2aLoc, Cxx2bLoc, Kind); + } + default: if (!isa(S)) break; diff --git a/clang/test/SemaCXX/constexpr-openmp-simd.cpp b/clang/test/SemaCXX/constexpr-openmp-simd.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-openmp-simd.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -fopenmp -triple x86_64-apple-macosx10.14.0 %s +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -fopenmp -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -fopenmp -triple aarch64_be-linux-gnu %s +// RUN: %clang_cc1 -emit-llvm -std=c++2a -fopenmp -triple aarch64_be-linux-gnu %s -DEMIT_IR -o - | FileCheck %s + +constexpr int good(int r) { + + #pragma omp simd + for (int i = 0; i != 10; ++i) + r += 1; + + return r; +} + +int test1() { + if (good(10) == 20) + return 42; + return good(7); +// Make sure this is folded to 42 and not 17. +// CHECK: ret i32 42 +} + +#ifndef EMIT_IR +constexpr int bad(int r) { + #pragma omp simd private(r) // expected-error {{OpenMP simd statement with clauses not allowed in constexpr function}} + for (int i = 0; i != 10; ++i) + r += 1; + + return r; +} + +int test2() { + return bad(10); +} +#endif