summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOpenMP.cpp
diff options
context:
space:
mode:
authorSamuel Antao <sfantao@us.ibm.com>2016-05-26 17:39:58 +0000
committerSamuel Antao <sfantao@us.ibm.com>2016-05-26 17:39:58 +0000
commit661c0904e144929ba9581a4bd7488961a8a1a331 (patch)
treedb2ddc9f112aa8a17dc0c178dc1c07c10d2e28f2 /clang/lib/Sema/SemaOpenMP.cpp
parent7f32420ed520ae6298900e8a50109c265c4dba85 (diff)
downloadbcm5719-llvm-661c0904e144929ba9581a4bd7488961a8a1a331.tar.gz
bcm5719-llvm-661c0904e144929ba9581a4bd7488961a8a1a331.zip
[OpenMP] Parsing and sema support for the to clause
Summary: The patch contains the parsing and sema support for the `to` clause. Patch based on the original post by Kelvin Li. Reviewers: carlo.bertolli, hfinkel, kkwli0, arpith-jacob, ABataev Subscribers: caomhin, cfe-commits Differential Revision: http://reviews.llvm.org/D18597 llvm-svn: 270880
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp269
1 files changed, 172 insertions, 97 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 14830f21557..eb572909ae2 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6521,10 +6521,11 @@ Sema::ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses,
StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc) {
- // TODO: Set this flag accordingly when we add support for the 'to' and 'from'
- // clauses.
bool seenMotionClause = false;
-
+ for (auto *C : Clauses) {
+ if (C->getClauseKind() == OMPC_to)
+ seenMotionClause = true;
+ }
if (!seenMotionClause) {
Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
return StmtError();
@@ -6798,6 +6799,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
+ case OMPC_to:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7084,6 +7086,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
+ case OMPC_to:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7235,6 +7238,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_hint:
case OMPC_unknown:
case OMPC_uniform:
+ case OMPC_to:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7419,6 +7423,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_defaultmap:
case OMPC_unknown:
case OMPC_uniform:
+ case OMPC_to:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7532,6 +7537,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
DepLinMapLoc, ColonLoc, VarList, StartLoc,
LParenLoc, EndLoc);
break;
+ case OMPC_to:
+ Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -9874,13 +9882,14 @@ static bool CheckArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
return ConstLength.getSExtValue() != 1;
}
-// Return the expression of the base of the map clause or null if it cannot
-// be determined and do all the necessary checks to see if the expression is
-// valid as a standalone map clause expression. In the process, record all the
+// Return the expression of the base of the mappable expression or null if it
+// cannot be determined and do all the necessary checks to see if the expression
+// is valid as a standalone mappable expression. In the process, record all the
// components of the expression.
static Expr *CheckMapClauseExpressionBase(
Sema &SemaRef, Expr *E,
- OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents) {
+ OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
+ OpenMPClauseKind CKind) {
SourceLocation ELoc = E->getExprLoc();
SourceRange ERange = E->getSourceRange();
@@ -9966,8 +9975,8 @@ static Expr *CheckMapClauseExpressionBase(
// A bit-field cannot appear in a map clause.
//
if (FD->isBitField()) {
- SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_map_clause)
- << CurE->getSourceRange();
+ SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
+ << CurE->getSourceRange() << getOpenMPClauseName(CKind);
break;
}
@@ -10089,7 +10098,8 @@ static Expr *CheckMapClauseExpressionBase(
static bool CheckMapConflicts(
Sema &SemaRef, DSAStackTy *DSAS, ValueDecl *VD, Expr *E,
bool CurrentRegionOnly,
- OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents) {
+ OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents,
+ OpenMPClauseKind CKind) {
assert(VD && E);
SourceLocation ELoc = E->getExprLoc();
SourceRange ERange = E->getSourceRange();
@@ -10164,7 +10174,13 @@ static bool CheckMapConflicts(
// other, it means they are sharing storage.
if (CI == CE && SI == SE) {
if (CurrentRegionOnly) {
- SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
+ if (CKind == OMPC_map)
+ SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
+ else {
+ assert(CKind == OMPC_to);
+ SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
+ << ERange;
+ }
SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
<< RE->getSourceRange();
return true;
@@ -10219,7 +10235,13 @@ static bool CheckMapConflicts(
//
// An expression is a subset of the other.
if (CurrentRegionOnly && (CI == CE || SI == SE)) {
- SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
+ if (CKind == OMPC_map)
+ SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
+ else {
+ assert(CKind == OMPC_to);
+ SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
+ << ERange;
+ }
SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
<< RE->getSourceRange();
return true;
@@ -10264,32 +10286,51 @@ static bool CheckMapConflicts(
return FoundError;
}
-OMPClause *
-Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
- OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
- SourceLocation MapLoc, SourceLocation ColonLoc,
- ArrayRef<Expr *> VarList, SourceLocation StartLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc) {
- SmallVector<Expr *, 4> Vars;
+namespace {
+// Utility struct that gathers all the related lists associated with a mappable
+// expression.
+struct MappableVarListInfo final {
+ // The list of expressions.
+ ArrayRef<Expr *> VarList;
+ // The list of processed expressions.
+ SmallVector<Expr *, 16> ProcessedVarList;
+ // The mappble components for each expression.
+ OMPClauseMappableExprCommon::MappableExprComponentLists VarComponents;
+ // The base declaration of the variable.
+ SmallVector<ValueDecl *, 16> VarBaseDeclarations;
+
+ MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
+ // We have a list of components and base declarations for each entry in the
+ // variable list.
+ VarComponents.reserve(VarList.size());
+ VarBaseDeclarations.reserve(VarList.size());
+ }
+};
+}
+
+// Check the validity of the provided variable list for the provided clause kind
+// \a CKind. In the check process the valid expressions, and mappable expression
+// components and variables are extracted and used to fill \a Vars,
+// \a ClauseComponents, and \a ClauseBaseDeclarations. \a MapType and
+// \a IsMapTypeImplicit are expected to be valid if the clause kind is 'map'.
+static void
+checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
+ OpenMPClauseKind CKind, MappableVarListInfo &MVLI,
+ SourceLocation StartLoc,
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown,
+ bool IsMapTypeImplicit = false) {
+ // We only expect mappable expressions in 'to' and 'map' clauses.
+ assert((CKind == OMPC_map || CKind == OMPC_to) &&
+ "Unexpected clause kind with mappable expressions!");
// Keep track of the mappable components and base declarations in this clause.
// Each entry in the list is going to have a list of components associated. We
// record each set of the components so that we can build the clause later on.
// In the end we should have the same amount of declarations and component
// lists.
- OMPClauseMappableExprCommon::MappableExprComponentLists ClauseComponents;
- SmallVector<ValueDecl *, 16> ClauseBaseDeclarations;
- ClauseComponents.reserve(VarList.size());
- ClauseBaseDeclarations.reserve(VarList.size());
-
- for (auto &RE : VarList) {
- assert(RE && "Null expr in omp map");
- if (isa<DependentScopeDeclRefExpr>(RE)) {
- // It will be analyzed later.
- Vars.push_back(RE);
- continue;
- }
+ for (auto &RE : MVLI.VarList) {
+ assert(RE && "Null expr in omp to/map clause");
SourceLocation ELoc = RE->getExprLoc();
auto *VE = RE->IgnoreParenLValueCasts();
@@ -10299,14 +10340,15 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
VE->containsUnexpandedParameterPack()) {
// We can only analyze this information once the missing information is
// resolved.
- Vars.push_back(RE);
+ MVLI.ProcessedVarList.push_back(RE);
continue;
}
auto *SimpleExpr = RE->IgnoreParenCasts();
if (!RE->IgnoreParenImpCasts()->isLValue()) {
- Diag(ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
+ SemaRef.Diag(ELoc,
+ diag::err_omp_expected_named_var_member_or_array_expression)
<< RE->getSourceRange();
continue;
}
@@ -10316,7 +10358,8 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
// Obtain the array or member expression bases if required. Also, fill the
// components array with all the components identified in the process.
- auto *BE = CheckMapClauseExpressionBase(*this, SimpleExpr, CurComponents);
+ auto *BE =
+ CheckMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind);
if (!BE)
continue;
@@ -10339,107 +10382,125 @@ Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
(void)FD;
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
- // threadprivate variables cannot appear in a map clause.
- if (VD && DSAStack->isThreadPrivate(VD)) {
- auto DVar = DSAStack->getTopDSA(VD, false);
- Diag(ELoc, diag::err_omp_threadprivate_in_map);
- ReportOriginalDSA(*this, DSAStack, VD, DVar);
+ // threadprivate variables cannot appear in a map clause.
+ // OpenMP 4.5 [2.10.5, target update Construct]
+ // threadprivate variables cannot appear in a from clause.
+ if (VD && DSAS->isThreadPrivate(VD)) {
+ auto DVar = DSAS->getTopDSA(VD, false);
+ SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
+ << getOpenMPClauseName(CKind);
+ ReportOriginalDSA(SemaRef, DSAS, VD, DVar);
continue;
}
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
// A list item cannot appear in both a map clause and a data-sharing
// attribute clause on the same construct.
- //
- // TODO: Implement this check - it cannot currently be tested because of
- // missing implementation of the other data sharing clauses in target
- // directives.
// Check conflicts with other map clause expressions. We check the conflicts
// with the current construct separately from the enclosing data
- // environment, because the restrictions are different.
- if (CheckMapConflicts(*this, DSAStack, CurDeclaration, SimpleExpr,
- /*CurrentRegionOnly=*/true, CurComponents))
+ // environment, because the restrictions are different. We only have to
+ // check conflicts across regions for the map clauses.
+ if (CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ /*CurrentRegionOnly=*/true, CurComponents, CKind))
break;
- if (CheckMapConflicts(*this, DSAStack, CurDeclaration, SimpleExpr,
- /*CurrentRegionOnly=*/false, CurComponents))
+ if (CKind == OMPC_map &&
+ CheckMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
+ /*CurrentRegionOnly=*/false, CurComponents, CKind))
break;
+ // OpenMP 4.5 [2.10.5, target update Construct]
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
// If the type of a list item is a reference to a type T then the type will
// be considered to be T for all purposes of this clause.
QualType Type = CurDeclaration->getType().getNonReferenceType();
+ // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
+ // A list item in a to or from clause must have a mappable type.
// OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
// A list item must have a mappable type.
- if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), *this,
- DSAStack, Type))
+ if (!CheckTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
+ DSAS, Type))
continue;
- // target enter data
- // OpenMP [2.10.2, Restrictions, p. 99]
- // A map-type must be specified in all map clauses and must be either
- // to or alloc.
- OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
- if (DKind == OMPD_target_enter_data &&
- !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) {
- Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
- << (IsMapTypeImplicit ? 1 : 0)
- << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
- << getOpenMPDirectiveName(DKind);
- continue;
- }
-
- // target exit_data
- // OpenMP [2.10.3, Restrictions, p. 102]
- // A map-type must be specified in all map clauses and must be either
- // from, release, or delete.
- DKind = DSAStack->getCurrentDirective();
- if (DKind == OMPD_target_exit_data &&
- !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
- MapType == OMPC_MAP_delete)) {
- Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
- << (IsMapTypeImplicit ? 1 : 0)
- << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
- << getOpenMPDirectiveName(DKind);
- continue;
- }
+ if (CKind == OMPC_map) {
+ // target enter data
+ // OpenMP [2.10.2, Restrictions, p. 99]
+ // A map-type must be specified in all map clauses and must be either
+ // to or alloc.
+ OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
+ if (DKind == OMPD_target_enter_data &&
+ !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc)) {
+ SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
+ << (IsMapTypeImplicit ? 1 : 0)
+ << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
+ << getOpenMPDirectiveName(DKind);
+ continue;
+ }
- // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
- // A list item cannot appear in both a map clause and a data-sharing
- // attribute clause on the same construct
- if (DKind == OMPD_target && VD) {
- auto DVar = DSAStack->getTopDSA(VD, false);
- if (isOpenMPPrivate(DVar.CKind)) {
- Diag(ELoc, diag::err_omp_variable_in_map_and_dsa)
- << getOpenMPClauseName(DVar.CKind)
- << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
- ReportOriginalDSA(*this, DSAStack, CurDeclaration, DVar);
+ // target exit_data
+ // OpenMP [2.10.3, Restrictions, p. 102]
+ // A map-type must be specified in all map clauses and must be either
+ // from, release, or delete.
+ if (DKind == OMPD_target_exit_data &&
+ !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
+ MapType == OMPC_MAP_delete)) {
+ SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
+ << (IsMapTypeImplicit ? 1 : 0)
+ << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
+ << getOpenMPDirectiveName(DKind);
continue;
}
+
+ // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
+ // A list item cannot appear in both a map clause and a data-sharing
+ // attribute clause on the same construct
+ if (DKind == OMPD_target && VD) {
+ auto DVar = DSAS->getTopDSA(VD, false);
+ if (isOpenMPPrivate(DVar.CKind)) {
+ SemaRef.Diag(ELoc, diag::err_omp_variable_in_map_and_dsa)
+ << getOpenMPClauseName(DVar.CKind)
+ << getOpenMPDirectiveName(DSAS->getCurrentDirective());
+ ReportOriginalDSA(SemaRef, DSAS, CurDeclaration, DVar);
+ continue;
+ }
+ }
}
// Save the current expression.
- Vars.push_back(RE);
+ MVLI.ProcessedVarList.push_back(RE);
// Store the components in the stack so that they can be used to check
// against other clauses later on.
- DSAStack->addMappableExpressionComponents(CurDeclaration, CurComponents);
+ DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents);
// Save the components and declaration to create the clause. For purposes of
// the clause creation, any component list that has has base 'this' uses
// null as base declaration.
- ClauseComponents.resize(ClauseComponents.size() + 1);
- ClauseComponents.back().append(CurComponents.begin(), CurComponents.end());
- ClauseBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
- : CurDeclaration);
+ MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
+ MVLI.VarComponents.back().append(CurComponents.begin(),
+ CurComponents.end());
+ MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
+ : CurDeclaration);
}
+}
+
+OMPClause *
+Sema::ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier,
+ OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+ SourceLocation MapLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+ MappableVarListInfo MVLI(VarList);
+ checkMappableExpressionList(*this, DSAStack, OMPC_map, MVLI, StartLoc,
+ MapType, IsMapTypeImplicit);
// We need to produce a map clause even if we don't have variables so that
// other diagnostics related with non-existing map clauses are accurate.
- return OMPMapClause::Create(
- Context, StartLoc, LParenLoc, EndLoc, Vars, ClauseBaseDeclarations,
- ClauseComponents, MapTypeModifier, MapType, IsMapTypeImplicit, MapLoc);
+ return OMPMapClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
+ MVLI.VarComponents, MapTypeModifier, MapType,
+ IsMapTypeImplicit, MapLoc);
}
QualType Sema::ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
@@ -11042,3 +11103,17 @@ void Sema::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D) {
}
checkDeclInTargetContext(E->getExprLoc(), E->getSourceRange(), *this, D);
}
+
+OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ MappableVarListInfo MVLI(VarList);
+ checkMappableExpressionList(*this, DSAStack, OMPC_to, MVLI, StartLoc);
+ if (MVLI.ProcessedVarList.empty())
+ return nullptr;
+
+ return OMPToClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
+ MVLI.VarComponents);
+}
OpenPOWER on IntegriCloud