Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8756,8 +8756,6 @@ def warn_omp_alignment_not_power_of_two : Warning< "aligned clause will be ignored because the requested alignment is not a power of 2">, InGroup; -def err_omp_enclosed_declare_target : Error< - "declare target region may not be enclosed within another declare target region">; def err_omp_invalid_target_decl : Error< "%0 used in declare target directive is not a variable or a function name">; def err_omp_declare_target_multiple : Error< Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -8616,8 +8616,8 @@ // private: void *VarDataSharingAttributesStack; - /// Set to true inside '#pragma omp declare target' region. - bool IsInOpenMPDeclareTargetContext = false; + /// Number of nested '#pragma omp declare target' directives. + unsigned DeclareTargetNestingLevel = 0; /// Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); @@ -8751,7 +8751,7 @@ SourceLocation IdLoc = SourceLocation()); /// Return true inside OpenMP declare target region. bool isInOpenMPDeclareTargetContext() const { - return IsInOpenMPDeclareTargetContext; + return DeclareTargetNestingLevel > 0; } /// Return true inside OpenMP target region. bool isInOpenMPTargetExecutionDirective() const; Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -12870,19 +12870,14 @@ Diag(Loc, diag::err_omp_region_not_file_context); return false; } - if (IsInOpenMPDeclareTargetContext) { - Diag(Loc, diag::err_omp_enclosed_declare_target); - return false; - } - - IsInOpenMPDeclareTargetContext = true; + ++DeclareTargetNestingLevel; return true; } void Sema::ActOnFinishOpenMPDeclareTargetDirective() { - assert(IsInOpenMPDeclareTargetContext && + assert(DeclareTargetNestingLevel > 0 && "Unexpected ActOnFinishOpenMPDeclareTargetDirective"); - IsInOpenMPDeclareTargetContext = false; + --DeclareTargetNestingLevel; } void Sema::ActOnOpenMPDeclareTargetName(Scope *CurScope, Index: clang/test/OpenMP/Inputs/declare_target_include.h =================================================================== --- /dev/null +++ clang/test/OpenMP/Inputs/declare_target_include.h @@ -0,0 +1,3 @@ +#pragma omp declare target + void zyx(); +#pragma omp end declare target Index: clang/test/OpenMP/declare_target_ast_print.cpp =================================================================== --- clang/test/OpenMP/declare_target_ast_print.cpp +++ clang/test/OpenMP/declare_target_ast_print.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s -// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp-simd -I %S/Inputs -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s // expected-no-diagnostics #ifndef HEADER @@ -169,6 +169,32 @@ // CHECK: #pragma omp end declare target // CHECK: int b; +#pragma omp declare target + #include "declare_target_include.h" + void xyz(); +#pragma omp end declare target + +// CHECK: #pragma omp declare target +// CHECK: void zyx(); +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: void xyz(); +// CHECK: #pragma omp end declare target + +#pragma omp declare target + #pragma omp declare target + void abc(); + #pragma omp end declare target + void cba(); +#pragma omp end declare target + +// CHECK: #pragma omp declare target +// CHECK: void abc(); +// CHECK: #pragma omp end declare target +// CHECK: #pragma omp declare target +// CHECK: void cba(); +// CHECK: #pragma omp end declare target + int main (int argc, char **argv) { foo(); foo_c(); Index: clang/test/OpenMP/declare_target_messages.cpp =================================================================== --- clang/test/OpenMP/declare_target_messages.cpp +++ clang/test/OpenMP/declare_target_messages.cpp @@ -59,8 +59,19 @@ } } +#pragma omp declare target + void abc(); +#pragma omp end declare target +void cba(); +#pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}} -#pragma omp declare target // expected-note {{to match this '#pragma omp declare target'}} +#pragma omp declare target // expected-note {{to match this '#pragma omp declare target'}} + #pragma omp declare target + void def(); + #pragma omp end declare target + void fed(); + +#pragma omp declare target // expected-note {{to match this '#pragma omp declare target'}} // expected-error {{expected '#pragma omp end declare target'}} #pragma omp threadprivate(a) // expected-note {{defined as threadprivate or thread local}} extern int b; int g;