[llvm] fcba7c3 - [OPENMP50]Initial support for scan directive.

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 20 05:28:47 PDT 2020


Author: Alexey Bataev
Date: 2020-03-20T07:58:15-04:00
New Revision: fcba7c3534f98851531095f8457eb3142e237f0b

URL: https://github.com/llvm/llvm-project/commit/fcba7c3534f98851531095f8457eb3142e237f0b
DIFF: https://github.com/llvm/llvm-project/commit/fcba7c3534f98851531095f8457eb3142e237f0b.diff

LOG: [OPENMP50]Initial support for scan directive.

Addedi basic parsing/sema/serialization support for scan directive.

Added: 
    clang/test/OpenMP/scan_ast_print.cpp
    clang/test/OpenMP/scan_messages.cpp

Modified: 
    clang/include/clang-c/Index.h
    clang/include/clang/AST/RecursiveASTVisitor.h
    clang/include/clang/AST/StmtOpenMP.h
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Basic/StmtNodes.td
    clang/include/clang/Sema/Sema.h
    clang/include/clang/Serialization/ASTBitCodes.h
    clang/lib/AST/StmtOpenMP.cpp
    clang/lib/AST/StmtPrinter.cpp
    clang/lib/AST/StmtProfile.cpp
    clang/lib/Basic/OpenMPKinds.cpp
    clang/lib/CodeGen/CGOpenMPRuntime.cpp
    clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
    clang/lib/CodeGen/CGStmt.cpp
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaExceptionSpec.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReaderStmt.cpp
    clang/lib/Serialization/ASTWriterStmt.cpp
    clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
    clang/test/OpenMP/nesting_of_regions.cpp
    clang/tools/libclang/CIndex.cpp
    clang/tools/libclang/CXCursor.cpp
    llvm/include/llvm/Frontend/OpenMP/OMPKinds.def

Removed: 
    


################################################################################
diff  --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 9d4930a3887a..ad2bb6a76c43 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2578,7 +2578,11 @@ enum CXCursorKind {
    */
   CXCursor_OMPDepobjDirective             = 286,
 
-  CXCursor_LastStmt = CXCursor_OMPDepobjDirective,
+  /** OpenMP scan directive.
+   */
+  CXCursor_OMPScanDirective               = 287,
+
+  CXCursor_LastStmt = CXCursor_OMPScanDirective,
 
   /**
    * Cursor that represents the translation unit itself.

diff  --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 27a0bc774184..4cc8b95c3bd1 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2852,6 +2852,9 @@ DEF_TRAVERSE_STMT(OMPFlushDirective,
 DEF_TRAVERSE_STMT(OMPDepobjDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPScanDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 DEF_TRAVERSE_STMT(OMPOrderedDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 

diff  --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index 5f7589acdb9e..b390bf0042f9 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -4688,6 +4688,63 @@ class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
   }
 };
 
+/// This represents '#pragma omp scan' directive.
+///
+/// \code
+/// #pragma omp scan inclusive(a)
+/// \endcode
+/// In this example directive '#pragma omp scan' has clause 'inclusive' with
+/// list item 'a'.
+class OMPScanDirective final : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                   unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPScanDirectiveClass,
+                               llvm::omp::OMPD_scan, StartLoc, EndLoc,
+                               NumClauses, 0) {}
+
+  /// Build an empty directive.
+  ///
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPScanDirective(unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPScanDirectiveClass,
+                               llvm::omp::OMPD_scan, SourceLocation(),
+                               SourceLocation(), NumClauses, 0) {}
+
+public:
+  /// Creates directive with a list of \a Clauses.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param Clauses List of clauses (only single OMPFlushClause clause is
+  /// allowed).
+  ///
+  static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+                                  SourceLocation EndLoc,
+                                  ArrayRef<OMPClause *> Clauses);
+
+  /// Creates an empty directive with the place for \a NumClauses
+  /// clauses.
+  ///
+  /// \param C AST context.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
+                                       EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPScanDirectiveClass;
+  }
+};
+
 } // end namespace clang
 
 #endif

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 92af99fe5719..38d0fe445268 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9823,9 +9823,10 @@ def err_omp_prohibited_region : Error<
   "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|"
   "; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|"
   "; perhaps you forget to enclose 'omp %3' directive into a target region?|"
-  "; perhaps you forget to enclose 'omp %3' directive into a teams region?}2">;
+  "; perhaps you forget to enclose 'omp %3' directive into a teams region?|"
+  "; perhaps you forget to enclose 'omp %3' directive into a for, simd, or for simd region?}2">;
 def err_omp_prohibited_region_simd : Error<
-  "OpenMP constructs may not be nested inside a simd region%select{| except for ordered simd, simd or atomic directive}0">;
+  "OpenMP constructs may not be nested inside a simd region%select{| except for ordered simd, simd, scan, or atomic directive}0">;
 def err_omp_prohibited_region_atomic : Error<
   "OpenMP constructs may not be nested inside an atomic region">;
 def err_omp_prohibited_region_critical_same_name : Error<
@@ -10016,7 +10017,7 @@ def warn_omp_nesting_simd : Warning<
   InGroup<SourceUsesOpenMP>;
 def err_omp_orphaned_device_directive : Error<
   "orphaned 'omp %0' directives are prohibited"
-  "; perhaps you forget to enclose the directive into a %select{|||target |teams }1region?">;
+  "; perhaps you forget to enclose the directive into a %select{|||target |teams|for, simd, or for simd }1region?">;
 def err_omp_reduction_non_addressable_expression : Error<
   "expected addressable reduction item for the task-based directives">;
 def err_omp_reduction_with_nogroup : Error<

diff  --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 41c6dbdb42e9..a617ab80021f 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -233,6 +233,7 @@ def OMPTaskwaitDirective : StmtNode<OMPExecutableDirective>;
 def OMPTaskgroupDirective : StmtNode<OMPExecutableDirective>;
 def OMPFlushDirective : StmtNode<OMPExecutableDirective>;
 def OMPDepobjDirective : StmtNode<OMPExecutableDirective>;
+def OMPScanDirective : StmtNode<OMPExecutableDirective>;
 def OMPOrderedDirective : StmtNode<OMPExecutableDirective>;
 def OMPAtomicDirective : StmtNode<OMPExecutableDirective>;
 def OMPTargetDirective : StmtNode<OMPExecutableDirective>;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 28f6705b307f..d09d095eb357 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10094,6 +10094,10 @@ class Sema final {
   StmtResult ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
                                         SourceLocation StartLoc,
                                         SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp scan'.
+  StmtResult ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
+                                      SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
   /// Called on well-formed '\#pragma omp ordered' after parsing of the
   /// associated statement.
   StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,

diff  --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 31226fb0516c..e5088ac9cbab 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1826,6 +1826,7 @@ namespace serialization {
       STMT_OMP_TASKWAIT_DIRECTIVE,
       STMT_OMP_FLUSH_DIRECTIVE,
       STMT_OMP_DEPOBJ_DIRECTIVE,
+      STMT_OMP_SCAN_DIRECTIVE,
       STMT_OMP_ORDERED_DIRECTIVE,
       STMT_OMP_ATOMIC_DIRECTIVE,
       STMT_OMP_TARGET_DIRECTIVE,

diff  --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index 153d492598d3..995f710876af 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -781,6 +781,27 @@ OMPDepobjDirective *OMPDepobjDirective::CreateEmpty(const ASTContext &C,
   return new (Mem) OMPDepobjDirective(NumClauses);
 }
 
+OMPScanDirective *OMPScanDirective::Create(const ASTContext &C,
+                                           SourceLocation StartLoc,
+                                           SourceLocation EndLoc,
+                                           ArrayRef<OMPClause *> Clauses) {
+  unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
+  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * Clauses.size(),
+                         alignof(OMPScanDirective));
+  auto *Dir = new (Mem) OMPScanDirective(StartLoc, EndLoc, Clauses.size());
+  Dir->setClauses(Clauses);
+  return Dir;
+}
+
+OMPScanDirective *OMPScanDirective::CreateEmpty(const ASTContext &C,
+                                                unsigned NumClauses,
+                                                EmptyShell) {
+  unsigned Size = llvm::alignTo(sizeof(OMPScanDirective), alignof(OMPClause *));
+  void *Mem = C.Allocate(Size + sizeof(OMPClause *) * NumClauses,
+                         alignof(OMPScanDirective));
+  return new (Mem) OMPScanDirective(NumClauses);
+}
+
 OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
                                                  SourceLocation StartLoc,
                                                  SourceLocation EndLoc,

diff  --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index f7a97c2743c1..68d0b144ced5 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -758,6 +758,11 @@ void StmtPrinter::VisitOMPDepobjDirective(OMPDepobjDirective *Node) {
   PrintOMPExecutableDirective(Node);
 }
 
+void StmtPrinter::VisitOMPScanDirective(OMPScanDirective *Node) {
+  Indent() << "#pragma omp scan";
+  PrintOMPExecutableDirective(Node);
+}
+
 void StmtPrinter::VisitOMPOrderedDirective(OMPOrderedDirective *Node) {
   Indent() << "#pragma omp ordered";
   PrintOMPExecutableDirective(Node, Node->hasClausesOfKind<OMPDependClause>());

diff  --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 8d43491ea8f4..832eff46a7c0 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -900,6 +900,10 @@ void StmtProfiler::VisitOMPDepobjDirective(const OMPDepobjDirective *S) {
   VisitOMPExecutableDirective(S);
 }
 
+void StmtProfiler::VisitOMPScanDirective(const OMPScanDirective *S) {
+  VisitOMPExecutableDirective(S);
+}
+
 void StmtProfiler::VisitOMPOrderedDirective(const OMPOrderedDirective *S) {
   VisitOMPExecutableDirective(S);
 }

diff  --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index f2106531d6eb..0e27a1652c39 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -608,6 +608,18 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
       break;
     }
     break;
+  case OMPD_scan:
+    if (OpenMPVersion < 50)
+      return false;
+    switch (CKind) {
+#define OPENMP_SCAN_CLAUSE(Name)                                               \
+  case OMPC_##Name:                                                            \
+    return true;
+#include "clang/Basic/OpenMPKinds.def"
+    default:
+      break;
+    }
+    break;
   case OMPD_atomic:
     if (OpenMPVersion < 50 &&
         (CKind == OMPC_acq_rel || CKind == OMPC_acquire ||
@@ -1251,6 +1263,7 @@ void clang::getOpenMPCaptureRegions(
   case OMPD_cancel:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_declare_reduction:
   case OMPD_declare_mapper:
   case OMPD_declare_simd:

diff  --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index c4e4578c4b04..b00027586767 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -6992,6 +6992,7 @@ emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
   case OMPD_atomic:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_teams:
   case OMPD_target_data:
   case OMPD_target_exit_data:
@@ -7304,6 +7305,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
   case OMPD_atomic:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_teams:
   case OMPD_target_data:
   case OMPD_target_exit_data:
@@ -9089,6 +9091,7 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
     case OMPD_atomic:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_teams:
     case OMPD_target_data:
     case OMPD_target_exit_data:
@@ -9867,6 +9870,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
     case OMPD_atomic:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_teams:
     case OMPD_target_data:
     case OMPD_target_exit_data:
@@ -10508,6 +10512,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
     case OMPD_atomic:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_teams:
     case OMPD_target_data:
     case OMPD_distribute:

diff  --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index b139529d8eb3..4b5c85541a7a 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -787,6 +787,7 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
     case OMPD_atomic:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_teams:
     case OMPD_target_data:
     case OMPD_target_exit_data:
@@ -864,6 +865,7 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx,
   case OMPD_atomic:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_teams:
   case OMPD_target_data:
   case OMPD_target_exit_data:
@@ -1034,6 +1036,7 @@ static bool hasNestedLightweightDirective(ASTContext &Ctx,
     case OMPD_atomic:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_teams:
     case OMPD_target_data:
     case OMPD_target_exit_data:
@@ -1117,6 +1120,7 @@ static bool supportsLightweightRuntime(ASTContext &Ctx,
   case OMPD_atomic:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_teams:
   case OMPD_target_data:
   case OMPD_target_exit_data:

diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 49f1725ed470..85c3bcca0647 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -250,6 +250,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
   case Stmt::OMPDepobjDirectiveClass:
     EmitOMPDepobjDirective(cast<OMPDepobjDirective>(*S));
     break;
+  case Stmt::OMPScanDirectiveClass:
+    llvm_unreachable("Scan directive not supported yet.");
+    break;
   case Stmt::OMPOrderedDirectiveClass:
     EmitOMPOrderedDirective(cast<OMPOrderedDirective>(*S));
     break;

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 6f6de47aa0bb..c5026f7eda14 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1843,6 +1843,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
   case OMPD_taskgroup:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_for:
   case OMPD_for_simd:
   case OMPD_sections:
@@ -2066,6 +2067,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
   }
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_taskyield:
   case OMPD_barrier:
   case OMPD_taskwait:

diff  --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 5c9844e1cd28..6eb5b71248ab 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1439,6 +1439,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
   case Stmt::OMPDistributeSimdDirectiveClass:
   case Stmt::OMPFlushDirectiveClass:
   case Stmt::OMPDepobjDirectiveClass:
+  case Stmt::OMPScanDirectiveClass:
   case Stmt::OMPForDirectiveClass:
   case Stmt::OMPForSimdDirectiveClass:
   case Stmt::OMPMasterDirectiveClass:

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 7d0821829daa..777cc5447545 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3858,6 +3858,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
   case OMPD_cancel:
   case OMPD_flush:
   case OMPD_depobj:
+  case OMPD_scan:
   case OMPD_declare_reduction:
   case OMPD_declare_mapper:
   case OMPD_declare_simd:
@@ -4202,12 +4203,14 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
       ShouldBeInParallelRegion,
       ShouldBeInOrderedRegion,
       ShouldBeInTargetRegion,
-      ShouldBeInTeamsRegion
+      ShouldBeInTeamsRegion,
+      ShouldBeInLoopSimdRegion,
     } Recommend = NoRecommend;
     if (isOpenMPSimdDirective(ParentRegion) &&
         ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
          (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
-          CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic))) {
+          CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
+          CurrentRegion != OMPD_scan))) {
       // OpenMP [2.16, Nesting of Regions]
       // OpenMP constructs may not be nested inside a simd region.
       // OpenMP [2.8.1,simd Construct, Restrictions]
@@ -4366,6 +4369,16 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
            ParentRegion != OMPD_target);
       OrphanSeen = ParentRegion == OMPD_unknown;
       Recommend = ShouldBeInTargetRegion;
+    } else if (CurrentRegion == OMPD_scan) {
+      // OpenMP [2.16, Nesting of Regions]
+      // If specified, a teams construct must be contained within a target
+      // construct.
+      NestingProhibited =
+          SemaRef.LangOpts.OpenMP < 50 ||
+          (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
+           ParentRegion != OMPD_for_simd);
+      OrphanSeen = ParentRegion == OMPD_unknown;
+      Recommend = ShouldBeInLoopSimdRegion;
     }
     if (!NestingProhibited &&
         !isOpenMPTargetExecutionDirective(CurrentRegion) &&
@@ -4874,6 +4887,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
            "No associated statement allowed for 'omp depobj' directive");
     Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
     break;
+  case OMPD_scan:
+    assert(AStmt == nullptr &&
+           "No associated statement allowed for 'omp scan' directive");
+    Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
+    break;
   case OMPD_ordered:
     Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
                                       EndLoc);
@@ -8773,6 +8791,12 @@ StmtResult Sema::ActOnOpenMPDepobjDirective(ArrayRef<OMPClause *> Clauses,
   return OMPDepobjDirective::Create(Context, StartLoc, EndLoc, Clauses);
 }
 
+StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
+                                          SourceLocation StartLoc,
+                                          SourceLocation EndLoc) {
+  return OMPScanDirective::Create(Context, StartLoc, EndLoc, Clauses);
+}
+
 StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
                                              Stmt *AStmt,
                                              SourceLocation StartLoc,
@@ -11251,6 +11275,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11322,6 +11347,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11398,6 +11424,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11471,6 +11498,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11545,6 +11573,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11618,6 +11647,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11690,6 +11720,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:
@@ -11765,6 +11796,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
     case OMPD_cancellation_point:
     case OMPD_flush:
     case OMPD_depobj:
+    case OMPD_scan:
     case OMPD_declare_reduction:
     case OMPD_declare_mapper:
     case OMPD_declare_simd:

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 9186ef0deb2a..8d0c466edec3 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -8303,6 +8303,17 @@ TreeTransform<Derived>::TransformOMPDepobjDirective(OMPDepobjDirective *D) {
   return Res;
 }
 
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPScanDirective(OMPScanDirective *D) {
+  DeclarationNameInfo DirName;
+  getDerived().getSema().StartOpenMPDSABlock(OMPD_scan, DirName, nullptr,
+                                             D->getBeginLoc());
+  StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
+  getDerived().getSema().EndOpenMPDSABlock(Res.get());
+  return Res;
+}
+
 template <typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) {

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 1fbcab209303..c0ed123826eb 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2377,6 +2377,13 @@ void ASTStmtReader::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
   VisitOMPExecutableDirective(D);
 }
 
+void ASTStmtReader::VisitOMPScanDirective(OMPScanDirective *D) {
+  VisitStmt(D);
+  // The NumClauses field was read in ReadStmtFromStream.
+  Record.skipInts(1);
+  VisitOMPExecutableDirective(D);
+}
+
 void ASTStmtReader::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
   VisitStmt(D);
   // The NumClauses field was read in ReadStmtFromStream.
@@ -3213,6 +3220,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
           Context, Record[ASTStmtReader::NumStmtFields], Empty);
       break;
 
+    case STMT_OMP_SCAN_DIRECTIVE:
+      S = OMPScanDirective::CreateEmpty(
+          Context, Record[ASTStmtReader::NumStmtFields], Empty);
+      break;
+
     case STMT_OMP_ORDERED_DIRECTIVE:
       S = OMPOrderedDirective::CreateEmpty(
           Context, Record[ASTStmtReader::NumStmtFields], Empty);

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index b25b2df8783a..41f8bb8c4d36 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2330,6 +2330,13 @@ void ASTStmtWriter::VisitOMPDepobjDirective(OMPDepobjDirective *D) {
   Code = serialization::STMT_OMP_DEPOBJ_DIRECTIVE;
 }
 
+void ASTStmtWriter::VisitOMPScanDirective(OMPScanDirective *D) {
+  VisitStmt(D);
+  Record.push_back(D->getNumClauses());
+  VisitOMPExecutableDirective(D);
+  Code = serialization::STMT_OMP_SCAN_DIRECTIVE;
+}
+
 void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
   VisitStmt(D);
   Record.push_back(D->getNumClauses());

diff  --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 1b13c49713ba..1bdf7f170f8b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1258,6 +1258,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::OMPTaskgroupDirectiveClass:
     case Stmt::OMPFlushDirectiveClass:
     case Stmt::OMPDepobjDirectiveClass:
+    case Stmt::OMPScanDirectiveClass:
     case Stmt::OMPOrderedDirectiveClass:
     case Stmt::OMPAtomicDirectiveClass:
     case Stmt::OMPTargetDirectiveClass:

diff  --git a/clang/test/OpenMP/nesting_of_regions.cpp b/clang/test/OpenMP/nesting_of_regions.cpp
index 53656a2e669f..4ecfac6f0777 100644
--- a/clang/test/OpenMP/nesting_of_regions.cpp
+++ b/clang/test/OpenMP/nesting_of_regions.cpp
@@ -84,6 +84,11 @@ void foo() {
   }
 #pragma omp parallel
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp parallel
+  {
 #pragma omp taskwait
     bar();
   }
@@ -230,7 +235,7 @@ void foo() {
 // SIMD DIRECTIVE
 #pragma omp simd
   for (int i = 0; i < 10; ++i) {
-#pragma omp for // expected-error {{OpenMP constructs may not be nested inside a simd region}}
+#pragma omp for // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{OpenMP constructs may not be nested inside a simd region except for ordered simd, simd, scan, or atomic directive}}
     for (int i = 0; i < 10; ++i)
       ;
   }
@@ -332,6 +337,11 @@ void foo() {
   }
 #pragma omp simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}}
+    bar();
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -608,6 +618,11 @@ void foo() {
   }
 #pragma omp for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -861,6 +876,11 @@ void foo() {
   }
 #pragma omp for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}}
+    bar();
+  }
+#pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -1152,6 +1172,10 @@ void foo() {
   }
 #pragma omp sections
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'sections' region}}
+  }
+#pragma omp sections
+  {
 #pragma omp taskwait
   }
 #pragma omp sections
@@ -1455,6 +1479,14 @@ void foo() {
   {
 #pragma omp section
     {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'section' region}}
+      bar();
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
 #pragma omp taskwait
       bar();
     }
@@ -1755,6 +1787,11 @@ void foo() {
   }
 #pragma omp single
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'single' region}}
+    bar();
+  }
+#pragma omp single
+  {
 #pragma omp taskwait
     bar();
   }
@@ -2030,6 +2067,11 @@ void foo() {
   }
 #pragma omp master
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'master' region}}
+    bar();
+  }
+#pragma omp master
+  {
 #pragma omp taskwait
     bar();
   }
@@ -2292,6 +2334,11 @@ void foo() {
   }
 #pragma omp critical
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'critical' region}}
+    bar();
+  }
+#pragma omp critical
+  {
 #pragma omp taskwait
     bar();
   }
@@ -2571,6 +2618,11 @@ void foo() {
   }
 #pragma omp parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel for' region}}
+    bar();
+  }
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -2840,6 +2892,11 @@ void foo() {
   }
 #pragma omp parallel for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -3120,6 +3177,11 @@ void foo() {
   }
 #pragma omp parallel master
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel master' region}}
+    bar();
+  }
+#pragma omp parallel master
+  {
 #pragma omp taskwait
     bar();
   }
@@ -3383,6 +3445,10 @@ void foo() {
   }
 #pragma omp parallel sections
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel sections' region}}
+  }
+#pragma omp parallel sections
+  {
 #pragma omp taskwait
   }
 #pragma omp parallel sections
@@ -3585,6 +3651,11 @@ void foo() {
   }
 #pragma omp task
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'task' region}}
+    bar();
+  }
+#pragma omp task
+  {
 #pragma omp taskwait
     bar();
   }
@@ -3848,6 +3919,11 @@ void foo() {
   }
 #pragma omp ordered
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'ordered' region}}
+    bar();
+  }
+#pragma omp ordered
+  {
 #pragma omp taskwait
     bar();
   }
@@ -4142,6 +4218,13 @@ void foo() {
   // expected-error at +2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note at +1 {{expected an expression statement}}
   {
+#pragma omp scan // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+    bar();
+  }
+#pragma omp atomic
+  // expected-error at +2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note at +1 {{expected an expression statement}}
+  {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
     bar();
   }
@@ -4406,6 +4489,11 @@ void foo() {
   }
 #pragma omp target
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+  {
 #pragma omp taskwait
     bar();
   }
@@ -4640,6 +4728,11 @@ void foo() {
   }
 #pragma omp target parallel
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target parallel
+  {
 #pragma omp taskwait
     bar();
   }
@@ -4906,6 +4999,11 @@ void foo() {
   }
 #pragma omp target parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target parallel for' region}}
+    bar();
+  }
+#pragma omp target parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -5140,6 +5238,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams
+  {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams
   {
 #pragma omp taskwait // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
@@ -5439,6 +5543,11 @@ void foo() {
   }
 #pragma omp taskloop
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'taskloop' region}}
+    bar();
+  }
+#pragma omp taskloop
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -5761,6 +5870,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
@@ -6073,6 +6189,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute parallel for
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
@@ -6385,6 +6508,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -6669,6 +6799,11 @@ void foo() {
   }
 #pragma omp target simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -6912,6 +7047,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
@@ -7175,6 +7316,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
@@ -7458,6 +7605,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'teams distribute simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -7741,6 +7894,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'teams distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -8024,6 +8183,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute parallel for
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
@@ -8237,6 +8402,11 @@ void foo() {
   }
 #pragma omp target teams
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams
+  {
 #pragma omp taskwait // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
     bar();
   }
@@ -8511,6 +8681,11 @@ void foo() {
   }
 #pragma omp target teams distribute
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
     bar();
   }
@@ -8754,6 +8929,11 @@ void foo() {
   }
 #pragma omp target teams distribute parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target teams distribute parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
     bar();
   }
@@ -8997,6 +9177,11 @@ void foo() {
   }
 #pragma omp target teams distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target teams distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -9240,6 +9425,11 @@ void foo() {
   }
 #pragma omp target teams distribute simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target teams distribute simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -9433,6 +9623,11 @@ void foo() {
   }
 #pragma omp parallel
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp parallel
+  {
 #pragma omp taskwait
     bar();
   }
@@ -9666,6 +9861,11 @@ void foo() {
   }
 #pragma omp simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}}
+    bar();
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -9916,6 +10116,11 @@ void foo() {
   }
 #pragma omp for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{region cannot be closely nested inside 'for' region}}
+    bar();
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -10156,6 +10361,11 @@ void foo() {
   }
 #pragma omp for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}}
+    bar();
+  }
+#pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -10405,6 +10615,11 @@ void foo() {
   }
 #pragma omp sections
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'sections' region}}
+    bar();
+  }
+#pragma omp sections
+  {
 #pragma omp taskwait
   }
 #pragma omp sections
@@ -10698,6 +10913,14 @@ void foo() {
   {
 #pragma omp section
     {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'section' region}}
+      bar();
+    }
+  }
+#pragma omp sections
+  {
+#pragma omp section
+    {
 #pragma omp taskwait
       bar();
     }
@@ -10991,6 +11214,11 @@ void foo() {
   }
 #pragma omp single
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'single' region}}
+    bar();
+  }
+#pragma omp single
+  {
 #pragma omp taskwait
     bar();
   }
@@ -11258,6 +11486,11 @@ void foo() {
   }
 #pragma omp master
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'master' region}}
+    bar();
+  }
+#pragma omp master
+  {
 #pragma omp taskwait
     bar();
   }
@@ -11513,6 +11746,11 @@ void foo() {
   }
 #pragma omp critical
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'critical' region}}
+    bar();
+  }
+#pragma omp critical
+  {
 #pragma omp taskwait
     bar();
   }
@@ -11797,6 +12035,11 @@ void foo() {
   }
 #pragma omp parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel for' region}}
+    bar();
+  }
+#pragma omp parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -12067,6 +12310,11 @@ void foo() {
   }
 #pragma omp parallel for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp parallel for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -12331,6 +12579,10 @@ void foo() {
   }
 #pragma omp parallel sections
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'parallel sections' region}}
+  }
+#pragma omp parallel sections
+  {
 #pragma omp taskwait
   }
 #pragma omp parallel sections
@@ -12532,6 +12784,11 @@ void foo() {
   }
 #pragma omp task
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'task' region}}
+    bar();
+  }
+#pragma omp task
+  {
 #pragma omp taskwait
     bar();
   }
@@ -12804,6 +13061,13 @@ void foo() {
   // expected-error at +2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
   // expected-note at +1 {{expected an expression statement}}
   {
+#pragma omp scan // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
+    bar();
+  }
+#pragma omp atomic
+  // expected-error at +2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
+  // expected-note at +1 {{expected an expression statement}}
+  {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside an atomic region}}
     bar();
   }
@@ -13067,6 +13331,11 @@ void foo() {
   }
 #pragma omp target
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+  {
 #pragma omp taskwait
     bar();
   }
@@ -13292,6 +13561,11 @@ void foo() {
   }
 #pragma omp target parallel
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target parallel' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target parallel
+  {
 #pragma omp taskwait
     bar();
   }
@@ -13558,6 +13832,11 @@ void foo() {
   }
 #pragma omp target parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target parallel for' region}}
+    bar();
+  }
+#pragma omp target parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -13791,6 +14070,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams
+  {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams
   {
 #pragma omp taskwait // expected-error {{region cannot be closely nested inside 'teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
@@ -14094,6 +14379,11 @@ void foo() {
   }
 #pragma omp taskloop
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'taskloop' region}}
+    bar();
+  }
+#pragma omp taskloop
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
     bar();
   }
@@ -14386,6 +14676,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
@@ -14708,6 +15005,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute parallel for
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait
@@ -15028,6 +15332,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -15340,6 +15651,13 @@ void foo() {
   }
 #pragma omp target
 #pragma omp teams
+#pragma omp distribute simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'distribute simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
+#pragma omp teams
 #pragma omp distribute simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -15616,6 +15934,11 @@ void foo() {
   }
 #pragma omp target simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -15870,6 +16193,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
@@ -16153,6 +16482,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'teams distribute simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -16436,6 +16771,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'teams distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
@@ -16719,6 +17060,12 @@ void foo() {
     bar();
   }
 #pragma omp target
+#pragma omp teams distribute parallel for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'teams distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target
 #pragma omp teams distribute parallel for
   for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
@@ -16932,6 +17279,11 @@ void foo() {
   }
 #pragma omp target teams
   {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams
+  {
 #pragma omp taskwait // expected-error {{region cannot be closely nested inside 'target teams' region; perhaps you forget to enclose 'omp taskwait' directive into a parallel region?}}
     bar();
   }
@@ -17206,6 +17558,11 @@ void foo() {
   }
 #pragma omp target teams distribute
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams distribute' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
     bar();
   }
@@ -17449,6 +17806,11 @@ void foo() {
   }
 #pragma omp target teams distribute parallel for
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // expected-error {{region cannot be closely nested inside 'target teams distribute parallel for' region}}
+    bar();
+  }
+#pragma omp target teams distribute parallel for
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // OK
     bar();
   }
@@ -17692,6 +18054,11 @@ void foo() {
   }
 #pragma omp target teams distribute parallel for simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target teams distribute parallel for simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute parallel for simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }
@@ -17935,6 +18302,11 @@ void foo() {
   }
 #pragma omp target teams distribute simd
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan // omp45-error {{OpenMP constructs may not be nested inside a simd region}} omp50-error {{region cannot be closely nested inside 'target teams distribute simd' region; perhaps you forget to enclose 'omp scan' directive into a for, simd, or for simd region?}}
+    bar();
+  }
+#pragma omp target teams distribute simd
+  for (int i = 0; i < 10; ++i) {
 #pragma omp taskwait // expected-error {{OpenMP constructs may not be nested inside a simd region}}
     bar();
   }

diff  --git a/clang/test/OpenMP/scan_ast_print.cpp b/clang/test/OpenMP/scan_ast_print.cpp
new file mode 100644
index 000000000000..042605d8a508
--- /dev/null
+++ b/clang/test/OpenMP/scan_ast_print.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void foo() {}
+
+template <class T>
+T tmain(T argc) {
+  static T a;
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan
+  }
+  return a + argc;
+}
+// CHECK:      static T a;
+// CHECK-NEXT: #pragma omp for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan{{$}}
+// CHECK:      static int a;
+// CHECK-NEXT: #pragma omp for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan
+// CHECK:      static char a;
+// CHECK-NEXT: #pragma omp for
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan
+
+int main(int argc, char **argv) {
+  static int a;
+// CHECK: static int a;
+#pragma omp for simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan
+  }
+// CHECK-NEXT: #pragma omp for simd
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan{{$}}
+  return tmain(argc) + tmain(argv[0][0]) + a;
+}
+
+#endif

diff  --git a/clang/test/OpenMP/scan_messages.cpp b/clang/test/OpenMP/scan_messages.cpp
new file mode 100644
index 000000000000..4533b9aed10d
--- /dev/null
+++ b/clang/test/OpenMP/scan_messages.cpp
@@ -0,0 +1,164 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s
+
+template <class T>
+T tmain(T argc) {
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan
+    ;
+  }
+#pragma omp for
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan allocate(argc)  // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp scan'}}
+#pragma omp scan untied  // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}}
+#pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}}
+  }
+#pragma omp for simd
+  for (int i = 0; i < 10; ++i)
+    if (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    if (argc) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  while (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    while (argc) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  do
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    while (argc)
+      ;
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  do {
+#pragma omp scan
+  } while (argc);
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  switch (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    switch (argc)
+    case 1:
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+  switch (argc)
+  case 1: {
+#pragma omp scan
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  switch (argc) {
+#pragma omp scan
+  case 1:
+#pragma omp scan
+    break;
+  default: {
+#pragma omp scan
+  } break;
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  for (;;)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    for (;;) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+label:
+#pragma omp scan
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+label1 : {
+#pragma omp scan
+}}
+
+  return T();
+}
+
+int main(int argc, char **argv) {
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan
+  ;
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+#pragma omp scan untied  // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp scan'}}
+#pragma omp scan unknown // expected-warning {{extra tokens at the end of '#pragma omp scan' are ignored}}
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  if (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    if (argc) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  while (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    while (argc) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  do
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    while (argc)
+      ;
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  do {
+#pragma omp scan
+  } while (argc);
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  switch (argc)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    switch (argc)
+    case 1:
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+  switch (argc)
+  case 1: {
+#pragma omp scan
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  switch (argc) {
+#pragma omp scan
+  case 1:
+#pragma omp scan
+    break;
+  default: {
+#pragma omp scan
+  } break;
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i)
+  for (;;)
+#pragma omp scan // expected-error {{'#pragma omp scan' cannot be an immediate substatement}}
+    for (;;) {
+#pragma omp scan
+    }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+label:
+#pragma omp scan
+  }
+#pragma omp simd
+  for (int i = 0; i < 10; ++i) {
+label1 : {
+#pragma omp scan
+}
+}
+
+  return tmain(argc);
+}

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index df5530c73c6d..e4727c86fafe 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2048,6 +2048,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
   void VisitOMPCancelDirective(const OMPCancelDirective *D);
   void VisitOMPFlushDirective(const OMPFlushDirective *D);
   void VisitOMPDepobjDirective(const OMPDepobjDirective *D);
+  void VisitOMPScanDirective(const OMPScanDirective *D);
   void VisitOMPOrderedDirective(const OMPOrderedDirective *D);
   void VisitOMPAtomicDirective(const OMPAtomicDirective *D);
   void VisitOMPTargetDirective(const OMPTargetDirective *D);
@@ -2885,6 +2886,10 @@ void EnqueueVisitor::VisitOMPDepobjDirective(const OMPDepobjDirective *D) {
   VisitOMPExecutableDirective(D);
 }
 
+void EnqueueVisitor::VisitOMPScanDirective(const OMPScanDirective *D) {
+  VisitOMPExecutableDirective(D);
+}
+
 void EnqueueVisitor::VisitOMPOrderedDirective(const OMPOrderedDirective *D) {
   VisitOMPExecutableDirective(D);
 }
@@ -5519,6 +5524,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
     return cxstring::createRef("OMPFlushDirective");
   case CXCursor_OMPDepobjDirective:
     return cxstring::createRef("OMPDepobjDirective");
+  case CXCursor_OMPScanDirective:
+    return cxstring::createRef("OMPScanDirective");
   case CXCursor_OMPOrderedDirective:
     return cxstring::createRef("OMPOrderedDirective");
   case CXCursor_OMPAtomicDirective:

diff  --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index e10c742c65ea..5e857def4c91 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -638,6 +638,9 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
   case Stmt::OMPDepobjDirectiveClass:
     K = CXCursor_OMPDepobjDirective;
     break;
+  case Stmt::OMPScanDirectiveClass:
+    K = CXCursor_OMPScanDirective;
+    break;
   case Stmt::OMPOrderedDirectiveClass:
     K = CXCursor_OMPOrderedDirective;
     break;

diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index 20e5b95a827a..d37c3911edf2 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -92,6 +92,7 @@ __OMP_DIRECTIVE_EXT(master_taskloop_simd, "master taskloop simd")
 __OMP_DIRECTIVE_EXT(parallel_master_taskloop_simd,
                     "parallel master taskloop simd")
 __OMP_DIRECTIVE(depobj)
+__OMP_DIRECTIVE(scan)
 
 // Has to be the last because Clang implicitly expects it to be.
 __OMP_DIRECTIVE(unknown)


        


More information about the llvm-commits mailing list