diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 72effbc3e02fc..f6211d4497531 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -1269,6 +1269,12 @@ class OMPDefaultClause : public OMPClause { /// Start location of the kind in source code. SourceLocation KindKwLoc; + /// Variable-Category to indicate where Kind is applied + OpenMPDefaultClauseVariableCategory VC = OMPC_DEFAULT_VC_all; + + /// Start location of Variable-Category + SourceLocation VCLoc; + /// Set kind of the clauses. /// /// \param K Argument of clause. @@ -1279,6 +1285,15 @@ class OMPDefaultClause : public OMPClause { /// \param KLoc Argument location. void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } + /// Set Variable Category used with the Kind Clause (Default Modifier) + void setDefaultVariableCategory(OpenMPDefaultClauseVariableCategory VC) { + this->VC = VC; + } + + void setDefaultVariableCategoryLocation(SourceLocation VCLoc) { + this->VCLoc = VCLoc; + } + public: /// Build 'default' clause with argument \a A ('none' or 'shared'). /// @@ -1288,10 +1303,11 @@ class OMPDefaultClause : public OMPClause { /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. OMPDefaultClause(llvm::omp::DefaultKind A, SourceLocation ALoc, + OpenMPDefaultClauseVariableCategory VC, SourceLocation VCLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) : OMPClause(llvm::omp::OMPC_default, StartLoc, EndLoc), - LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} + LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc), VC(VC), VCLoc(VCLoc) {} /// Build an empty clause. OMPDefaultClause() @@ -1310,6 +1326,10 @@ class OMPDefaultClause : public OMPClause { /// Returns location of clause kind. SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } + OpenMPDefaultClauseVariableCategory getDefaultVC() { return VC; } + + SourceLocation getDefaultVCLoc() { return VCLoc; } + child_range children() { return child_range(child_iterator(), child_iterator()); } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a591a25367301..5d6539a7e15f0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11714,6 +11714,8 @@ def note_omp_default_dsa_none : Note< "explicit data sharing attribute requested here">; def note_omp_defaultmap_attr_none : Note< "explicit data sharing attribute, data mapping attribute, or is_device_ptr clause requested here">; +def err_omp_default_vc : Error< + "wrong variable category specified with modifier %0 in the default clause">; def err_omp_wrong_dsa : Error< "%0 variable cannot be %1">; def err_omp_variably_modified_type_not_supported : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def index 9d6f816eea91f..79c11b851c557 100644 --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -35,6 +35,9 @@ #ifndef OPENMP_DIST_SCHEDULE_KIND #define OPENMP_DIST_SCHEDULE_KIND(Name) #endif +#ifndef OPENMP_DEFAULT_VARIABLE_CATEGORY +#define OPENMP_DEFAULT_VARIABLE_CATEGORY(Name) +#endif #ifndef OPENMP_DEFAULTMAP_KIND #define OPENMP_DEFAULTMAP_KIND(Name) #endif @@ -112,6 +115,13 @@ OPENMP_SCHEDULE_MODIFIER(simd) OPENMP_DEVICE_MODIFIER(ancestor) OPENMP_DEVICE_MODIFIER(device_num) +// Variable-category attributes for 'default' clause. +OPENMP_DEFAULT_VARIABLE_CATEGORY(aggregate) +OPENMP_DEFAULT_VARIABLE_CATEGORY(all) +OPENMP_DEFAULT_VARIABLE_CATEGORY(allocatable) +OPENMP_DEFAULT_VARIABLE_CATEGORY(pointer) +OPENMP_DEFAULT_VARIABLE_CATEGORY(scalar) + // Static attributes for 'defaultmap' clause. OPENMP_DEFAULTMAP_KIND(scalar) OPENMP_DEFAULTMAP_KIND(aggregate) @@ -267,6 +277,7 @@ OPENMP_DOACROSS_MODIFIER(source_omp_cur_iteration) #undef OPENMP_MAP_MODIFIER_KIND #undef OPENMP_MOTION_MODIFIER_KIND #undef OPENMP_DIST_SCHEDULE_KIND +#undef OPENMP_DEFAULT_VARIABLE_CATEGORY #undef OPENMP_DEFAULTMAP_KIND #undef OPENMP_DEFAULTMAP_MODIFIER #undef OPENMP_DOACROSS_MODIFIER diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h index f40db4c13c55a..be0e79ae17123 100644 --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -107,6 +107,13 @@ enum OpenMPDistScheduleClauseKind { OMPC_DIST_SCHEDULE_unknown }; +/// OpenMP variable-category for 'default' clause. +enum OpenMPDefaultClauseVariableCategory { +#define OPENMP_DEFAULT_VARIABLE_CATEGORY(Name) OMPC_DEFAULT_VC_##Name, +#include "clang/Basic/OpenMPKinds.def" + OMPC_DEFAULT_VC_unknown +}; + /// OpenMP attributes for 'defaultmap' clause. enum OpenMPDefaultmapClauseKind { #define OPENMP_DEFAULTMAP_KIND(Name) \ @@ -257,6 +264,10 @@ struct OMPInteropInfo final { llvm::SmallVector PreferTypes; }; +OpenMPDefaultClauseVariableCategory +getOpenMPDefaultVariableCategory(StringRef Str, const LangOptions &LangOpts); +const char *getOpenMPDefaultVariableCategoryName(unsigned VC); + unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts); const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h index 91c3d4bd5210e..23827051ed724 100644 --- a/clang/include/clang/Sema/SemaOpenMP.h +++ b/clang/include/clang/Sema/SemaOpenMP.h @@ -951,11 +951,11 @@ class SemaOpenMP : public SemaBase { SourceLocation LParenLoc, SourceLocation EndLoc); /// Called on well-formed 'default' clause. - OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, - SourceLocation KindLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc); + OMPClause * + ActOnOpenMPDefaultClause(llvm::omp::DefaultKind M, SourceLocation MLoc, + OpenMPDefaultClauseVariableCategory VCKind, + SourceLocation VCKindLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc); /// Called on well-formed 'proc_bind' clause. OMPClause *ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 0930ca27c29f8..69d33019c0952 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -1911,8 +1911,13 @@ void OMPClausePrinter::VisitOMPDetachClause(OMPDetachClause *Node) { void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) { OS << "default(" << getOpenMPSimpleClauseTypeName(OMPC_default, - unsigned(Node->getDefaultKind())) - << ")"; + unsigned(Node->getDefaultKind())); + if (Version >= 60 && Node->getDefaultVC() != OMPC_DEFAULT_VC_all) { + OS << ":" + << getOpenMPDefaultVariableCategoryName(unsigned(Node->getDefaultVC())); + } + + OS << ")"; } void OMPClausePrinter::VisitOMPProcBindClause(OMPProcBindClause *Node) { diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index 220b31b0f19bc..b957652d1383c 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -20,6 +20,26 @@ using namespace clang; using namespace llvm::omp; +OpenMPDefaultClauseVariableCategory +clang::getOpenMPDefaultVariableCategory(StringRef Str, + const LangOptions &LangOpts) { + return llvm::StringSwitch(Str) +#define OPENMP_DEFAULT_VARIABLE_CATEGORY(Name) \ + .Case(#Name, OMPC_DEFAULT_VC_##Name) +#include "clang/Basic/OpenMPKinds.def" + .Default(OMPC_DEFAULT_VC_unknown); +} + +const char *clang::getOpenMPDefaultVariableCategoryName(unsigned VC) { + switch (VC) { +#define OPENMP_DEFAULT_VARIABLE_CATEGORY(Name) \ + case OMPC_DEFAULT_VC_##Name: \ + return #Name; +#include "clang/Basic/OpenMPKinds.def" + } + llvm_unreachable("Invalid Variable Category in the default clause"); +} + unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str, const LangOptions &LangOpts) { switch (Kind) { @@ -896,4 +916,3 @@ bool clang::checkFailClauseParameter(OpenMPClauseKind FailClauseParameter) { FailClauseParameter == llvm::omp::OMPC_relaxed || FailClauseParameter == llvm::omp::OMPC_seq_cst; } - diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 5db2f2e2ccf86..7dceb2d208352 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -3083,7 +3083,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); break; case OMPC_fail: - case OMPC_default: case OMPC_proc_bind: case OMPC_atomic_default_mem_order: case OMPC_at: @@ -3115,6 +3114,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_schedule: case OMPC_dist_schedule: case OMPC_defaultmap: + case OMPC_default: case OMPC_order: // OpenMP [2.7.1, Restrictions, p. 3] // Only one schedule clause can appear on a loop directive. @@ -3734,6 +3734,32 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, ConsumeAnyToken(); if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) DelimLoc = ConsumeAnyToken(); + } else if (Kind == OMPC_default) { + // Get a default modifier + unsigned Modifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); + + Arg.push_back(Modifier); + KLoc.push_back(Tok.getLocation()); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + // Parse ':' + if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) { + ConsumeAnyToken(); + // Get a variable-category attribute for default clause modifier + OpenMPDefaultClauseVariableCategory VariableCategory = + getOpenMPDefaultVariableCategory( + Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); + Arg.push_back(VariableCategory); + KLoc.push_back(Tok.getLocation()); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + } else { + Arg.push_back(OMPC_DEFAULT_VC_all); + KLoc.push_back(SourceLocation()); + } } else if (Kind == OMPC_defaultmap) { // Get a defaultmap modifier unsigned Modifier = getOpenMPSimpleClauseType( @@ -3932,6 +3958,18 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, if (NeedAnExpression && Val.isInvalid()) return nullptr; + if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] && + (static_cast(Arg[0]) == OMP_DEFAULT_private || + static_cast(Arg[0]) == OMP_DEFAULT_firstprivate)) { + Diag(KLoc[0], diag::err_omp_invalid_dsa) + << getOpenMPClauseName(static_cast(Arg[0]) == + OMP_DEFAULT_private + ? OMPC_private + : OMPC_firstprivate) + << getOpenMPClauseName(OMPC_default) << "5.1"; + return nullptr; + } + if (ParseOnly) return nullptr; return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause( diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a1dd5b090c59b..c14bc9b3cb61f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -73,6 +73,18 @@ enum DefaultDataSharingAttributes { DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'. }; +/// Variable Category attributes to restrict the modifier of the +/// default clause (DefaultDataSharingAttributes) +/// Not mentioning any Variable category attribute indicates +/// the modifier (DefaultDataSharingAttributes) is for all variables. +enum DefaultDataSharingVCAttributes { + DSA_VC_all = 0, /// for all variables. + DSA_VC_aggregate = 1 << 0, /// for aggregate variables. + DSA_VC_allocatable = 1 << 1, /// for allocatable variables. + DSA_VC_pointer = 1 << 2, /// for pointer variables. + DSA_VC_scalar = 1 << 3, /// for scalar variables. +}; + /// Stack for tracking declarations used in OpenMP directives and /// clauses and their data-sharing attributes. class DSAStackTy { @@ -168,6 +180,8 @@ class DSAStackTy { LoopControlVariablesMapTy LCVMap; DefaultDataSharingAttributes DefaultAttr = DSA_unspecified; SourceLocation DefaultAttrLoc; + DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all; + SourceLocation DefaultAttrVCLoc; DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1]; OpenMPDirectiveKind Directive = OMPD_unknown; DeclarationNameInfo DirectiveName; @@ -735,6 +749,31 @@ class DSAStackTy { getTopOfStack().DefaultAttr = DSA_firstprivate; getTopOfStack().DefaultAttrLoc = Loc; } + /// Set default data sharing variable category attribute to aggregate. + void setDefaultDSAVCAggregate(SourceLocation VCLoc) { + getTopOfStack().DefaultVCAttr = DSA_VC_aggregate; + getTopOfStack().DefaultAttrVCLoc = VCLoc; + } + /// Set default data sharing variable category attribute to all. + void setDefaultDSAVCAll(SourceLocation VCLoc) { + getTopOfStack().DefaultVCAttr = DSA_VC_all; + getTopOfStack().DefaultAttrVCLoc = VCLoc; + } + /// Set default data sharing variable category attribute to allocatable. + void setDefaultDSAVCAllocatable(SourceLocation VCLoc) { + getTopOfStack().DefaultVCAttr = DSA_VC_allocatable; + getTopOfStack().DefaultAttrVCLoc = VCLoc; + } + /// Set default data sharing variable category attribute to pointer. + void setDefaultDSAVCPointer(SourceLocation VCLoc) { + getTopOfStack().DefaultVCAttr = DSA_VC_pointer; + getTopOfStack().DefaultAttrVCLoc = VCLoc; + } + /// Set default data sharing variable category attribute to scalar. + void setDefaultDSAVCScalar(SourceLocation VCLoc) { + getTopOfStack().DefaultVCAttr = DSA_VC_scalar; + getTopOfStack().DefaultAttrVCLoc = VCLoc; + } /// Set default data mapping attribute to Modifier:Kind void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) { @@ -1326,11 +1365,33 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter, return DVar; } + DefaultDataSharingAttributes IterDA = Iter->DefaultAttr; + switch (Iter->DefaultVCAttr) { + case DSA_VC_aggregate: + if (!VD->getType()->isAggregateType()) + IterDA = DSA_none; + break; + case DSA_VC_allocatable: + if (!(VD->getType()->isPointerType() || + VD->getType()->isVariableArrayType())) + IterDA = DSA_none; + break; + case DSA_VC_pointer: + if (!VD->getType()->isPointerType()) + IterDA = DSA_none; + break; + case DSA_VC_scalar: + if (!VD->getType()->isScalarType()) + IterDA = DSA_none; + break; + default:; + } + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, implicitly determined, p.1] // In a parallel or task construct, the data-sharing attributes of these // variables are determined by the default clause, if present. - switch (Iter->DefaultAttr) { + switch (IterDA) { case DSA_shared: DVar.CKind = OMPC_shared; DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; @@ -16263,10 +16324,6 @@ OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause( SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { OMPClause *Res = nullptr; switch (Kind) { - case OMPC_default: - Res = ActOnOpenMPDefaultClause(static_cast(Argument), - ArgumentLoc, StartLoc, LParenLoc, EndLoc); - break; case OMPC_proc_bind: Res = ActOnOpenMPProcBindClause(static_cast(Argument), ArgumentLoc, StartLoc, LParenLoc, EndLoc); @@ -16347,6 +16404,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause( case OMPC_num_tasks: case OMPC_hint: case OMPC_dist_schedule: + case OMPC_default: case OMPC_defaultmap: case OMPC_unknown: case OMPC_uniform: @@ -16380,38 +16438,58 @@ OMPClause *SemaOpenMP::ActOnOpenMPSimpleClause( return Res; } -OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause(DefaultKind Kind, - SourceLocation KindKwLoc, - SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc) { - if (Kind == OMP_DEFAULT_unknown) { - Diag(KindKwLoc, diag::err_omp_unexpected_clause_value) +OMPClause *SemaOpenMP::ActOnOpenMPDefaultClause( + llvm::omp::DefaultKind M, SourceLocation MLoc, + OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc, + SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { + if (M == OMP_DEFAULT_unknown) { + Diag(MLoc, diag::err_omp_unexpected_clause_value) << getListOfPossibleValues(OMPC_default, /*First=*/0, /*Last=*/unsigned(OMP_DEFAULT_unknown)) << getOpenMPClauseNameForDiag(OMPC_default); return nullptr; } - switch (Kind) { + switch (M) { case OMP_DEFAULT_none: - DSAStack->setDefaultDSANone(KindKwLoc); + DSAStack->setDefaultDSANone(MLoc); break; case OMP_DEFAULT_shared: - DSAStack->setDefaultDSAShared(KindKwLoc); + DSAStack->setDefaultDSAShared(MLoc); break; case OMP_DEFAULT_firstprivate: - DSAStack->setDefaultDSAFirstPrivate(KindKwLoc); + DSAStack->setDefaultDSAFirstPrivate(MLoc); break; case OMP_DEFAULT_private: - DSAStack->setDefaultDSAPrivate(KindKwLoc); + DSAStack->setDefaultDSAPrivate(MLoc); break; default: llvm_unreachable("DSA unexpected in OpenMP default clause"); } + switch (VCKind) { + case OMPC_DEFAULT_VC_aggregate: + DSAStack->setDefaultDSAVCAggregate(VCKindLoc); + break; + case OMPC_DEFAULT_VC_all: + DSAStack->setDefaultDSAVCAll(VCKindLoc); + break; + case OMPC_DEFAULT_VC_allocatable: + DSAStack->setDefaultDSAVCAllocatable(VCKindLoc); + break; + case OMPC_DEFAULT_VC_pointer: + DSAStack->setDefaultDSAVCPointer(VCKindLoc); + break; + case OMPC_DEFAULT_VC_scalar: + DSAStack->setDefaultDSAVCScalar(VCKindLoc); + break; + default: + Diag(VCKindLoc, diag::err_omp_default_vc) + << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M)); + } + return new (getASTContext()) - OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); + OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc); } OMPClause *SemaOpenMP::ActOnOpenMPProcBindClause(ProcBindKind Kind, @@ -16740,6 +16818,15 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( static_cast(Argument.back()), Expr, StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc); break; + case OMPC_default: + enum { DefaultModifier, DefaultVarCategory }; + Res = ActOnOpenMPDefaultClause( + static_cast(Argument[DefaultModifier]), + ArgumentLoc[DefaultModifier], + static_cast( + Argument[DefaultVarCategory]), + ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc); + break; case OMPC_defaultmap: enum { Modifier, DefaultmapKind }; Res = ActOnOpenMPDefaultmapClause( @@ -16788,7 +16875,6 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprWithArgClause( case OMPC_sizes: case OMPC_allocator: case OMPC_collapse: - case OMPC_default: case OMPC_proc_bind: case OMPC_private: case OMPC_firstprivate: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0587a7decbd8d..cd2442ff0cd1c 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1827,11 +1827,13 @@ class TreeTransform { /// By default, performs semantic analysis to build the new OpenMP clause. /// Subclasses may override this routine to provide different behavior. OMPClause *RebuildOMPDefaultClause(DefaultKind Kind, SourceLocation KindKwLoc, + OpenMPDefaultClauseVariableCategory VCKind, + SourceLocation VCLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { return getSema().OpenMP().ActOnOpenMPDefaultClause( - Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc); + Kind, KindKwLoc, VCKind, VCLoc, StartLoc, LParenLoc, EndLoc); } /// Build a new OpenMP 'proc_bind' clause. @@ -10614,8 +10616,9 @@ template OMPClause * TreeTransform::TransformOMPDefaultClause(OMPDefaultClause *C) { return getDerived().RebuildOMPDefaultClause( - C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getBeginLoc(), - C->getLParenLoc(), C->getEndLoc()); + C->getDefaultKind(), C->getDefaultKindKwLoc(), C->getDefaultVC(), + C->getDefaultVCLoc(), C->getBeginLoc(), C->getLParenLoc(), + C->getEndLoc()); } template diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 9b0e699b1a829..7015087647d31 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -11646,6 +11646,9 @@ void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { C->setDefaultKind(static_cast(Record.readInt())); C->setLParenLoc(Record.readSourceLocation()); C->setDefaultKindKwLoc(Record.readSourceLocation()); + C->setDefaultVariableCategory( + static_cast(Record.readInt())); + C->setDefaultVariableCategoryLocation(Record.readSourceLocation()); } void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8e219e54bf251..52322bb695967 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7884,6 +7884,8 @@ void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { Record.push_back(unsigned(C->getDefaultKind())); Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getDefaultKindKwLoc()); + Record.push_back(unsigned(C->getDefaultVC())); + Record.AddSourceLocation(C->getDefaultVCLoc()); } void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) { diff --git a/clang/test/OpenMP/parallel_ast_print.cpp b/clang/test/OpenMP/parallel_ast_print.cpp index 15439ea31215a..28dc611bf864d 100644 --- a/clang/test/OpenMP/parallel_ast_print.cpp +++ b/clang/test/OpenMP/parallel_ast_print.cpp @@ -21,11 +21,19 @@ // RUN: %clang_cc1 -DOMP60 -verify -Wno-vla -fopenmp-simd -fopenmp-version=60 -ast-print %s | FileCheck -check-prefixes=CHECK,OMP60 %s // RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -x c++ -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -std=c++11 -include-pch %t -verify -Wno-vla %s -ast-print | FileCheck -check-prefixes=CHECK,OMP60 %s +// RUN: %clang_cc1 -DOMP60 -fopenmp-simd -fopenmp-version=60 -std=c++11 -verify -Wno-vla %s -ast-dump | FileCheck -check-prefixes=OMP60_DUMP %s // expected-no-diagnostics #ifndef HEADER #define HEADER +#ifdef OMP60 +int global; +int global2; + +void bar(int j) { }; +#endif + void foo() {} struct S1 { @@ -185,6 +193,32 @@ T tmain(T argc, T *argv) { return 0; } + +#ifdef OMP60 +// OMP60_DUMP: FunctionDecl {{.*}}mainVC {{.*}} +// OMP60_DUMP: OMPParallelDirective {{.*}} +// OMP60_DUMP-NEXT: OMPSharedClause{{.*}} +// OMP60_DUMP-NEXT: {{.*}}DeclRefExpr{{.*}} 'global' 'int'{{.*}} +// OMP60_DUMP-NEXT: OMPDefaultClause {{.*}} +// OMP60_DUMP-NEXT: OMPFirstprivateClause{{.*}} +// OMP60_DUMP-NEXT: {{.*}}DeclRefExpr{{.*}} 'h' 'int[20]'{{.*}} +// OMP60_DUMP: OMPParallelDirective {{.*}} +// OMP60_DUMP-NEXT: OMPPrivateClause{{.*}} +// OMP60_DUMP-NEXT: {{.*}}DeclRefExpr{{.*}} 'global2' 'int'{{.*}} +// OMP60_DUMP-NEXT: OMPDefaultClause {{.*}} +// OMP60_DUMP-NEXT: OMPPrivateClause {{.*}} +// OMP60_DUMP-NEXT: {{.*}}DeclRefExpr{{.*}} 'j' 'int'{{.*}} +int mainVC(int argc, int *argv) { + int h[20]; + int j; +#pragma omp parallel shared(global) default(firstprivate: aggregate) + bar(h[1]), h[1] = global; +#pragma omp parallel private(global2) default(private: scalar) + bar(global2), j = global2; + return 0; +} +#endif + // CHECK: template T tmain(T argc, T *argv) { // CHECK-NEXT: T b = argc, c, d, e, f, g; // CHECK-NEXT: static T a; @@ -237,6 +271,14 @@ T tmain(T argc, T *argv) { // OMP60-NEXT: #pragma omp parallel if(1) num_threads(strict: s) proc_bind(close) reduction(^: e,f,arr[0:1][:argc]) reduction(default, &&: g) reduction(task, +: argc) message("msg") severity(warning) // OMP60-NEXT: foo() +// OMP60: int mainVC(int argc, int *argv) { +// OMP60-NEXT: int h[20]; +// OMP60-NEXT: int j; +// OMP60-NEXT: #pragma omp parallel shared(global) default(firstprivate:aggregate) +// OMP60-NEXT: bar(h[1]) , h[1] = global; +// OMP60-NEXT: #pragma omp parallel private(global2) default(private:scalar) +// OMP60-NEXT: bar(global2) , j = global2; + enum Enum { }; int main (int argc, char **argv) { diff --git a/clang/test/OpenMP/parallel_default_messages.cpp b/clang/test/OpenMP/parallel_default_messages.cpp index 37d3b5565f83c..842b1ac5a96b8 100644 --- a/clang/test/OpenMP/parallel_default_messages.cpp +++ b/clang/test/OpenMP/parallel_default_messages.cpp @@ -6,6 +6,7 @@ // RUN: %clang_cc1 -verify -fopenmp-version=30 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify=expected,ge40 -fopenmp -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized // RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-simd -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=60 -fopenmp -DOMP60 -ferror-limit 100 -o - %s -Wuninitialized void foo(); @@ -47,6 +48,23 @@ int main(int argc, char **argv) { } #endif +#ifdef OMP60 +#pragma omp parallel default(shared:) private(x,y) // expected-error {{wrong variable category specified with modifier shared in the default clause}} + { + ++x; + ++y; + } +#pragma omp parallel default(shared: junk) private(x,y) // expected-error {{wrong variable category specified with modifier shared in the default clause}} + { + ++x; + ++y; + } +#pragma omp parallel default(firstprivate: junk) private(x,y) // expected-error {{wrong variable category specified with modifier firstprivate in the default clause}} + { + ++x; + ++y; + } +#endif return 0; }