[Clang][OpenMP]Default clause variable category (#157063)
Support for Variable Category in Default Clause.
---------
Co-authored-by: Sunil Kuravinakop <kuravina@pe31.hpc.amslabs.hpecorp.net>
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 47a8109..0bc8590 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -576,7 +576,7 @@
| | | | Flang parser: https://github.com/llvm/llvm-project/pull/153807 |
| | | | Flang sema: https://github.com/llvm/llvm-project/pull/154779 |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| variable-category on default clause | :part:`In Progress` | :none:`unclaimed` | |
+| variable-category on default clause | :good:`done` | :none:`unclaimed` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
| Changes to omp_target_is_accessible | :part:`In Progress` | :part:`In Progress` | |
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 873d63f..41bec26 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -521,6 +521,7 @@
- Allow array length to be omitted in array section subscript expression.
- Fixed non-contiguous strided update in the ``omp target update`` directive with the ``from`` clause.
- Properly handle array section/assumed-size array privatization in C/C++.
+- Added support for ``variable-category`` modifier in ``default clause``.
Improvements
^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 72effbc..b2a6d4b 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -1269,6 +1269,12 @@
/// 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 @@
/// \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 @@
/// \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 @@
/// Returns location of clause kind.
SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
+ OpenMPDefaultClauseVariableCategory getDefaultVC() const { return VC; }
+
+ SourceLocation getDefaultVCLoc() const { 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 b0e669c..757404a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11714,6 +11714,8 @@
"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 9d6f816..79c11b8 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_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 @@
#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 d3285cd..115af7b 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -107,6 +107,13 @@
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 @@
llvm::SmallVector<Expr *, 4> 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 91c3d4b..2382705 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -951,11 +951,11 @@
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 0930ca2..69d3301 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1911,8 +1911,13 @@
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 3f8f64df..3255da8 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<OpenMPDefaultClauseVariableCategory>(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) {
@@ -902,4 +922,3 @@
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 5db2f2e..7dceb2d 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3083,7 +3083,6 @@
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 @@
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 @@
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 @@
if (NeedAnExpression && Val.isInvalid())
return nullptr;
+ if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&
+ (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||
+ static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {
+ Diag(KLoc[0], diag::err_omp_invalid_dsa)
+ << getOpenMPClauseName(static_cast<DefaultKind>(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 63a56a6..66bdd6e 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -73,6 +73,18 @@
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, /// for aggregate variables.
+ DSA_VC_allocatable, /// for allocatable variables.
+ DSA_VC_pointer, /// for pointer variables.
+ DSA_VC_scalar, /// for scalar variables.
+};
+
/// Stack for tracking declarations used in OpenMP directives and
/// clauses and their data-sharing attributes.
class DSAStackTy {
@@ -168,6 +180,8 @@
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 @@
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,34 @@
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;
+ case DSA_VC_all:
+ break;
+ }
+
// 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;
@@ -16265,10 +16327,6 @@
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
OMPClause *Res = nullptr;
switch (Kind) {
- case OMPC_default:
- Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
- ArgumentLoc, StartLoc, LParenLoc, EndLoc);
- break;
case OMPC_proc_bind:
Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
@@ -16349,6 +16407,7 @@
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_dist_schedule:
+ case OMPC_default:
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
@@ -16382,38 +16441,58 @@
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,
@@ -16742,6 +16821,15 @@
static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
break;
+ case OMPC_default:
+ enum { DefaultModifier, DefaultVarCategory };
+ Res = ActOnOpenMPDefaultClause(
+ static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
+ ArgumentLoc[DefaultModifier],
+ static_cast<OpenMPDefaultClauseVariableCategory>(
+ Argument[DefaultVarCategory]),
+ ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_defaultmap:
enum { Modifier, DefaultmapKind };
Res = ActOnOpenMPDefaultmapClause(
@@ -16790,7 +16878,6 @@
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 6136937..242ffb0 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1810,11 +1810,13 @@
/// 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.
@@ -10512,8 +10514,9 @@
OMPClause *
TreeTransform<Derived>::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 <typename Derived>
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 5f40e94..9ee8a0f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11632,6 +11632,9 @@
C->setDefaultKind(static_cast<llvm::omp::DefaultKind>(Record.readInt()));
C->setLParenLoc(Record.readSourceLocation());
C->setDefaultKindKwLoc(Record.readSourceLocation());
+ C->setDefaultVariableCategory(
+ Record.readEnum<OpenMPDefaultClauseVariableCategory>());
+ C->setDefaultVariableCategoryLocation(Record.readSourceLocation());
}
void OMPClauseReader::VisitOMPProcBindClause(OMPProcBindClause *C) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 15a3ed4..2aa7793 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7875,6 +7875,8 @@
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 15439ea..28dc611 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 @@
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 <typename T, int C> 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 @@
// 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 37d3b55..842b1ac 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 @@
}
#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;
}