summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Antao <sfantao@us.ibm.com>2016-05-26 17:49:04 +0000
committerSamuel Antao <sfantao@us.ibm.com>2016-05-26 17:49:04 +0000
commitec172c6da02111b2e1150b3bd94578789d4fbd14 (patch)
tree86d58f9d1449977bacb1d6e03886ad0461602716
parentd6e6bf1808f54cd755847aed3a4ee40b27102cb5 (diff)
downloadbcm5719-llvm-ec172c6da02111b2e1150b3bd94578789d4fbd14.tar.gz
bcm5719-llvm-ec172c6da02111b2e1150b3bd94578789d4fbd14.zip
[OpenMP] Parsing and sema support for the from clause
Summary: The patch contains the parsing and sema support for the `from` clause. Patch based on the original post by Kelvin Li. Reviewers: hfinkel, carlo.bertolli, kkwli0, arpith-jacob, ABataev Subscribers: caomhin, cfe-commits Differential Revision: http://reviews.llvm.org/D18488 llvm-svn: 270882
-rw-r--r--clang/include/clang/AST/OpenMPClause.h104
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h6
-rw-r--r--clang/include/clang/Basic/OpenMPKinds.def2
-rw-r--r--clang/include/clang/Sema/Sema.h5
-rw-r--r--clang/lib/AST/OpenMPClause.cpp51
-rw-r--r--clang/lib/AST/StmtPrinter.cpp8
-rw-r--r--clang/lib/AST/StmtProfile.cpp3
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp2
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp1
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp6
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp33
-rw-r--r--clang/lib/Sema/TreeTransform.h26
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp53
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp20
-rw-r--r--clang/test/OpenMP/target_update_ast_print.cpp7
-rw-r--r--clang/test/OpenMP/target_update_device_messages.cpp24
-rw-r--r--clang/test/OpenMP/target_update_from_messages.cpp176
-rw-r--r--clang/test/OpenMP/target_update_if_messages.cpp36
-rw-r--r--clang/test/OpenMP/target_update_messages.cpp2
-rw-r--r--clang/test/OpenMP/target_update_to_messages.cpp4
-rw-r--r--clang/tools/libclang/CIndex.cpp3
21 files changed, 532 insertions, 40 deletions
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 071284f790a..52eeaafaf43 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -4113,6 +4113,110 @@ public:
reinterpret_cast<Stmt **>(varlist_end()));
}
};
+
+/// \brief This represents clause 'from' in the '#pragma omp ...'
+/// directives.
+///
+/// \code
+/// #pragma omp target update from(a,b)
+/// \endcode
+/// In this example directive '#pragma omp target update' has clause 'from'
+/// with the variables 'a' and 'b'.
+///
+class OMPFromClause final
+ : public OMPMappableExprListClause<OMPFromClause>,
+ private llvm::TrailingObjects<
+ OMPFromClause, Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent> {
+ friend TrailingObjects;
+ friend OMPVarListClause;
+ friend OMPMappableExprListClause;
+ friend class OMPClauseReader;
+
+ /// Define the sizes of each trailing object array except the last one. This
+ /// is required for TrailingObjects to work properly.
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return varlist_size();
+ }
+ size_t numTrailingObjects(OverloadToken<ValueDecl *>) const {
+ return getUniqueDeclarationsNum();
+ }
+ size_t numTrailingObjects(OverloadToken<unsigned>) const {
+ return getUniqueDeclarationsNum() + getTotalComponentListNum();
+ }
+
+ /// \brief Build clause with number of variables \a NumVars.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
+ ///
+ explicit OMPFromClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents)
+ : OMPMappableExprListClause(OMPC_from, StartLoc, LParenLoc, EndLoc,
+ NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents) {}
+
+ /// \brief Build an empty clause.
+ ///
+ /// \param NumVars Number of expressions listed in this clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of component lists in this clause.
+ /// \param NumComponents Total number of expression components in the clause.
+ ///
+ explicit OMPFromClause(unsigned NumVars, unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists, unsigned NumComponents)
+ : OMPMappableExprListClause(
+ OMPC_from, SourceLocation(), SourceLocation(), SourceLocation(),
+ NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {}
+
+public:
+ /// \brief Creates clause with a list of variables \a Vars.
+ ///
+ /// \param C AST context.
+ /// \brief StartLoc Starting location of the clause.
+ /// \brief EndLoc Ending location of the clause.
+ /// \param Vars The original expression used in the clause.
+ /// \param Declarations Declarations used in the clause.
+ /// \param ComponentLists Component lists used in the clause.
+ ///
+ static OMPFromClause *Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> Vars,
+ ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists);
+
+ /// \brief Creates an empty clause with the place for \a NumVars variables.
+ ///
+ /// \param C AST context.
+ /// \param NumVars Number of expressions listed in the clause.
+ /// \param NumUniqueDeclarations Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponentLists Number of unique base declarations in this
+ /// clause.
+ /// \param NumComponents Total number of expression components in the clause.
+ ///
+ static OMPFromClause *CreateEmpty(const ASTContext &C, unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents);
+
+ static bool classof(const OMPClause *T) {
+ return T->getClauseKind() == OMPC_from;
+ }
+
+ child_range children() {
+ return child_range(reinterpret_cast<Stmt **>(varlist_begin()),
+ reinterpret_cast<Stmt **>(varlist_end()));
+ }
+};
} // end namespace clang
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 1c8a58a74ea..1693976cf85 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2890,6 +2890,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPToClause(OMPToClause *C) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPFromClause(OMPFromClause *C) {
+ TRY_TO(VisitOMPClauseList(C));
+ return true;
+}
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index c744bfe51a7..cf91bc78c22 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -211,6 +211,7 @@ OPENMP_CLAUSE(hint, OMPHintClause)
OPENMP_CLAUSE(dist_schedule, OMPDistScheduleClause)
OPENMP_CLAUSE(defaultmap, OMPDefaultmapClause)
OPENMP_CLAUSE(to, OMPToClause)
+OPENMP_CLAUSE(from, OMPFromClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@@ -452,6 +453,7 @@ OPENMP_TARGET_PARALLEL_FOR_CLAUSE(linear)
OPENMP_TARGET_UPDATE_CLAUSE(if)
OPENMP_TARGET_UPDATE_CLAUSE(device)
OPENMP_TARGET_UPDATE_CLAUSE(to)
+OPENMP_TARGET_UPDATE_CLAUSE(from)
// Clauses allowed for OpenMP directive 'teams'.
// TODO More clauses for 'teams' directive.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 58f23b25eac..2e068cff890 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8423,6 +8423,11 @@ public:
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// \brief Called on well-formed 'from' clause.
+ OMPClause *ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// \brief The kind of conversion being performed.
enum CheckedConversionKind {
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 1449e37ce6e..5b51c277d6f 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -88,6 +88,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
break;
}
@@ -150,6 +151,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
break;
}
@@ -676,3 +678,52 @@ OMPToClause *OMPToClause::CreateEmpty(const ASTContext &C, unsigned NumVars,
return new (Mem) OMPToClause(NumVars, NumUniqueDeclarations,
NumComponentLists, NumComponents);
}
+
+OMPFromClause *
+OMPFromClause::Create(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ ArrayRef<Expr *> Vars, ArrayRef<ValueDecl *> Declarations,
+ MappableExprComponentListsRef ComponentLists) {
+ unsigned NumVars = Vars.size();
+ unsigned NumUniqueDeclarations =
+ getUniqueDeclarationsTotalNumber(Declarations);
+ unsigned NumComponentLists = ComponentLists.size();
+ unsigned NumComponents = getComponentsTotalNumber(ComponentLists);
+
+ // We need to allocate:
+ // NumVars x Expr* - we have an original list expression for each clause list
+ // entry.
+ // NumUniqueDeclarations x ValueDecl* - unique base declarations associated
+ // with each component list.
+ // (NumUniqueDeclarations + NumComponentLists) x unsigned - we specify the
+ // number of lists for each unique declaration and the size of each component
+ // list.
+ // NumComponents x MappableComponent - the total of all the components in all
+ // the lists.
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+
+ OMPFromClause *Clause = new (Mem)
+ OMPFromClause(StartLoc, LParenLoc, EndLoc, NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+
+ Clause->setVarRefs(Vars);
+ Clause->setClauseInfo(Declarations, ComponentLists);
+ return Clause;
+}
+
+OMPFromClause *OMPFromClause::CreateEmpty(const ASTContext &C, unsigned NumVars,
+ unsigned NumUniqueDeclarations,
+ unsigned NumComponentLists,
+ unsigned NumComponents) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *, ValueDecl *, unsigned,
+ OMPClauseMappableExprCommon::MappableComponent>(
+ NumVars, NumUniqueDeclarations,
+ NumUniqueDeclarations + NumComponentLists, NumComponents));
+ return new (Mem) OMPFromClause(NumVars, NumUniqueDeclarations,
+ NumComponentLists, NumComponents);
+}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 81ce0b5b662..2e15c81cccd 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -920,6 +920,14 @@ void OMPClausePrinter::VisitOMPToClause(OMPToClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPFromClause(OMPFromClause *Node) {
+ if (!Node->varlist_empty()) {
+ OS << "from";
+ VisitOMPClauseList(Node, '(');
+ OS << ")";
+ }
+}
+
void OMPClausePrinter::VisitOMPDistScheduleClause(OMPDistScheduleClause *Node) {
OS << "dist_schedule(" << getOpenMPSimpleClauseTypeName(
OMPC_dist_schedule, Node->getDistScheduleKind());
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 22b0b31285e..688530bb5bd 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -494,6 +494,9 @@ void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) {
void OMPClauseProfiler::VisitOMPToClause(const OMPToClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseProfiler::VisitOMPFromClause(const OMPFromClause *C) {
+ VisitOMPClauseList(C);
+}
}
void
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 4a3423b89b0..5e0e9ba0012 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -163,6 +163,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_hint:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@@ -299,6 +300,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_hint:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 75845add54e..e20ac0aebc0 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -3135,6 +3135,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_defaultmap:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index a009736fd98..b1635cfa9a0 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1043,7 +1043,8 @@ bool Parser::ParseOpenMPSimpleVarList(
/// update-clause | capture-clause | seq_cst-clause | device-clause |
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
/// thread_limit-clause | priority-clause | grainsize-clause |
-/// nogroup-clause | num_tasks-clause | hint-clause | to-clause
+/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
+/// from-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@@ -1168,6 +1169,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_depend:
case OMPC_map:
case OMPC_to:
+ case OMPC_from:
Clause = ParseOpenMPVarListClause(DKind, CKind);
break;
case OMPC_unknown:
@@ -1730,6 +1732,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/// to | from | tofrom | alloc | release | delete ':' ] list ')';
/// to-clause:
/// 'to' '(' list ')'
+/// from-clause:
+/// 'from' '(' list ')'
///
/// For 'linear' clause linear-list may have the following forms:
/// list
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index eb572909ae2..154ea8ae6fa 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6523,7 +6523,7 @@ StmtResult Sema::ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation EndLoc) {
bool seenMotionClause = false;
for (auto *C : Clauses) {
- if (C->getClauseKind() == OMPC_to)
+ if (C->getClauseKind() == OMPC_to || C->getClauseKind() == OMPC_from)
seenMotionClause = true;
}
if (!seenMotionClause) {
@@ -6800,6 +6800,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7087,6 +7088,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7239,6 +7241,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7424,6 +7427,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_unknown:
case OMPC_uniform:
case OMPC_to:
+ case OMPC_from:
llvm_unreachable("Clause is not allowed.");
}
return Res;
@@ -7540,6 +7544,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_to:
Res = ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_from:
+ Res = ActOnOpenMPFromClause(VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@@ -10177,7 +10184,7 @@ static bool CheckMapConflicts(
if (CKind == OMPC_map)
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
else {
- assert(CKind == OMPC_to);
+ assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
}
@@ -10238,7 +10245,7 @@ static bool CheckMapConflicts(
if (CKind == OMPC_map)
SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
else {
- assert(CKind == OMPC_to);
+ assert(CKind == OMPC_to || CKind == OMPC_from);
SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
<< ERange;
}
@@ -10319,8 +10326,8 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
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) &&
+ // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
+ assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
"Unexpected clause kind with mappable expressions!");
// Keep track of the mappable components and base declarations in this clause.
@@ -10330,7 +10337,7 @@ checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS,
// lists.
for (auto &RE : MVLI.VarList) {
- assert(RE && "Null expr in omp to/map clause");
+ assert(RE && "Null expr in omp to/from/map clause");
SourceLocation ELoc = RE->getExprLoc();
auto *VE = RE->IgnoreParenLValueCasts();
@@ -11117,3 +11124,17 @@ OMPClause *Sema::ActOnOpenMPToClause(ArrayRef<Expr *> VarList,
MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
MVLI.VarComponents);
}
+
+OMPClause *Sema::ActOnOpenMPFromClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ MappableVarListInfo MVLI(VarList);
+ checkMappableExpressionList(*this, DSAStack, OMPC_from, MVLI, StartLoc);
+ if (MVLI.ProcessedVarList.empty())
+ return nullptr;
+
+ return OMPFromClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
+ MVLI.VarComponents);
+}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 72181ca68ae..38c4fd69f6a 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1762,6 +1762,18 @@ public:
return getSema().ActOnOpenMPToClause(VarList, StartLoc, LParenLoc, EndLoc);
}
+ /// \brief Build a new OpenMP 'from' clause.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ OMPClause *RebuildOMPFromClause(ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPFromClause(VarList, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -8063,6 +8075,20 @@ OMPClause *TreeTransform<Derived>::TransformOMPToClause(OMPToClause *C) {
C->getLParenLoc(), C->getLocEnd());
}
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPFromClause(OMPFromClause *C) {
+ llvm::SmallVector<Expr *, 16> Vars;
+ Vars.reserve(C->varlist_size());
+ for (auto *VE : C->varlists()) {
+ ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
+ if (EVar.isInvalid())
+ return 0;
+ Vars.push_back(EVar.get());
+ }
+ return getDerived().RebuildOMPFromClause(Vars, C->getLocStart(),
+ C->getLParenLoc(), C->getLocEnd());
+}
+
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 3e09896da21..15e289f6f8e 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1903,6 +1903,15 @@ OMPClause *OMPClauseReader::readClause() {
NumComponents);
break;
}
+ case OMPC_from: {
+ unsigned NumVars = Record[Idx++];
+ unsigned NumDeclarations = Record[Idx++];
+ unsigned NumLists = Record[Idx++];
+ unsigned NumComponents = Record[Idx++];
+ C = OMPFromClause::CreateEmpty(Context, NumVars, NumDeclarations, NumLists,
+ NumComponents);
+ break;
+ }
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@@ -2376,6 +2385,50 @@ void OMPClauseReader::VisitOMPToClause(OMPToClause *C) {
C->setComponents(Components, ListSizes);
}
+void OMPClauseReader::VisitOMPFromClause(OMPFromClause *C) {
+ C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
+ auto NumVars = C->varlist_size();
+ auto UniqueDecls = C->getUniqueDeclarationsNum();
+ auto TotalLists = C->getTotalComponentListNum();
+ auto TotalComponents = C->getTotalComponentsNum();
+
+ SmallVector<Expr *, 16> Vars;
+ Vars.reserve(NumVars);
+ for (unsigned i = 0; i != NumVars; ++i)
+ Vars.push_back(Reader->Reader.ReadSubExpr());
+ C->setVarRefs(Vars);
+
+ SmallVector<ValueDecl *, 16> Decls;
+ Decls.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ Decls.push_back(
+ Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx));
+ C->setUniqueDecls(Decls);
+
+ SmallVector<unsigned, 16> ListsPerDecl;
+ ListsPerDecl.reserve(UniqueDecls);
+ for (unsigned i = 0; i < UniqueDecls; ++i)
+ ListsPerDecl.push_back(Record[Idx++]);
+ C->setDeclNumLists(ListsPerDecl);
+
+ SmallVector<unsigned, 32> ListSizes;
+ ListSizes.reserve(TotalLists);
+ for (unsigned i = 0; i < TotalLists; ++i)
+ ListSizes.push_back(Record[Idx++]);
+ C->setComponentListSizes(ListSizes);
+
+ SmallVector<OMPClauseMappableExprCommon::MappableComponent, 32> Components;
+ Components.reserve(TotalComponents);
+ for (unsigned i = 0; i < TotalComponents; ++i) {
+ Expr *AssociatedExpr = Reader->Reader.ReadSubExpr();
+ ValueDecl *AssociatedDecl =
+ Reader->Reader.ReadDeclAs<ValueDecl>(Reader->F, Record, Idx);
+ Components.push_back(OMPClauseMappableExprCommon::MappableComponent(
+ AssociatedExpr, AssociatedDecl));
+ }
+ C->setComponents(Components, ListSizes);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 1afc00410b5..5382b4af922 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2111,6 +2111,26 @@ void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {
}
}
+void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
+ Record.push_back(C->varlist_size());
+ Record.push_back(C->getUniqueDeclarationsNum());
+ Record.push_back(C->getTotalComponentListNum());
+ Record.push_back(C->getTotalComponentsNum());
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto *E : C->varlists())
+ Record.AddStmt(E);
+ for (auto *D : C->all_decls())
+ Record.AddDeclRef(D);
+ for (auto N : C->all_num_lists())
+ Record.push_back(N);
+ for (auto N : C->all_lists_sizes())
+ Record.push_back(N);
+ for (auto &M : C->all_components()) {
+ Record.AddStmt(M.getAssociatedExpression());
+ Record.AddDeclRef(M.getAssociatedDeclaration());
+ }
+}
+
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
diff --git a/clang/test/OpenMP/target_update_ast_print.cpp b/clang/test/OpenMP/target_update_ast_print.cpp
index 253dad2db8c..fcb8625d7b2 100644
--- a/clang/test/OpenMP/target_update_ast_print.cpp
+++ b/clang/test/OpenMP/target_update_ast_print.cpp
@@ -14,20 +14,25 @@ T foo(T targ, U uarg) {
U b;
int l;
#pragma omp target update to(a) if(l>5) device(l)
+
+#pragma omp target update from(b) if(l<5) device(l-1)
return a + targ + (T)b;
}
// CHECK: static int a;
// CHECK-NEXT: float b;
// CHECK-NEXT: int l;
// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l)
+// CHECK-NEXT: #pragma omp target update from(b) if(l < 5) device(l - 1)
// CHECK: static char a;
// CHECK-NEXT: float b;
// CHECK-NEXT: int l;
// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l)
+// CHECK-NEXT: #pragma omp target update from(b) if(l < 5) device(l - 1)
// CHECK: static T a;
// CHECK-NEXT: U b;
// CHECK-NEXT: int l;
// CHECK-NEXT: #pragma omp target update to(a) if(l > 5) device(l)
+// CHECK-NEXT: #pragma omp target update from(b) if(l < 5) device(l - 1)
int main(int argc, char **argv) {
static int a;
@@ -39,6 +44,8 @@ int main(int argc, char **argv) {
// CHECK-NEXT: float f;
#pragma omp target update to(a) if(f>0.0) device(n)
// CHECK-NEXT: #pragma omp target update to(a) if(f > 0.) device(n)
+#pragma omp target update from(f) if(f<0.0) device(n+1)
+ // CHECK-NEXT: #pragma omp target update from(f) if(f < 0.) device(n + 1)
return foo(argc, f) + foo(argv[0][0], f) + a;
}
diff --git a/clang/test/OpenMP/target_update_device_messages.cpp b/clang/test/OpenMP/target_update_device_messages.cpp
index 8163f1e32ed..37112755805 100644
--- a/clang/test/OpenMP/target_update_device_messages.cpp
+++ b/clang/test/OpenMP/target_update_device_messages.cpp
@@ -17,27 +17,27 @@ int tmain(T argc, S **argv) {
#pragma omp target update to(i) device () // expected-error {{expected expression}}
#pragma omp target update to(i) device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(i) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
-#pragma omp target update device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update device (argc + argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update device (S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(i) device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
+#pragma omp target update from(i) device (argc + argc)
+#pragma omp target update from(i) device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}}
+#pragma omp target update from(i) device (S1) // expected-error {{'S1' does not refer to a value}}
+#pragma omp target update from(i) device (3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
+#pragma omp target update from(i) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
}
int main(int argc, char **argv) {
int j;
#pragma omp target update to(j) device // expected-error {{expected '(' after 'device'}}
-#pragma omp target update device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(j) device ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(j) device () // expected-error {{expected expression}}
-#pragma omp target update device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(j) device (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(j) device (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
-#pragma omp target update device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(j) device (argc > 0 ? argv[1] : argv[2]) // expected-error {{expression must have integral or unscoped enumeration type, not 'char *'}}
#pragma omp target update to(j) device (argc + argc)
-#pragma omp target update device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(j) device (argc), device (argc+1) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'device' clause}}
#pragma omp target update to(j) device (S1) // expected-error {{'S1' does not refer to a value}}
-#pragma omp target update device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(j) device (-2) // expected-error {{argument to 'device' clause must be a non-negative integer value}}
#pragma omp target update to(j) device (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
- return tmain(argc, argv);
+ return tmain(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}
}
diff --git a/clang/test/OpenMP/target_update_from_messages.cpp b/clang/test/OpenMP/target_update_from_messages.cpp
new file mode 100644
index 00000000000..6aff083b6a4
--- /dev/null
+++ b/clang/test/OpenMP/target_update_from_messages.cpp
@@ -0,0 +1,176 @@
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo() {
+}
+
+bool foobool(int argc) {
+ return argc;
+}
+
+struct S1; // expected-note 2 {{declared here}}
+extern S1 a;
+class S2 {
+ mutable int a;
+public:
+ S2():a(0) { }
+ S2(S2 &s2):a(s2.a) { }
+ static float S2s; // expected-note 4 {{mappable type cannot contain static members}}
+ static const float S2sc; // expected-note 4 {{mappable type cannot contain static members}}
+};
+const float S2::S2sc = 0;
+const S2 b;
+const S2 ba[5];
+class S3 {
+ int a;
+public:
+ S3():a(0) { }
+ S3(S3 &s3):a(s3.a) { }
+};
+const S3 c;
+const S3 ca[5];
+extern const int f;
+class S4 {
+ int a;
+ S4();
+ S4(const S4 &s4);
+public:
+ S4(int v):a(v) { }
+};
+class S5 {
+ int a;
+ S5():a(0) {}
+ S5(const S5 &s5):a(s5.a) { }
+public:
+ S5(int v):a(v) { }
+};
+struct S6 {
+ int ii;
+ int aa[30];
+ float xx;
+ double *pp;
+};
+struct S7 {
+ int i;
+ int a[50];
+ float x;
+ S6 s6[5];
+ double *p;
+ unsigned bfa : 4;
+};
+
+S3 h;
+#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
+
+typedef int to;
+
+template <typename T, int I> // expected-note {{declared here}}
+T tmain(T argc) {
+ const T d = 5;
+ const T da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ T i, t[20];
+ T &j = i;
+ T *k = &j;
+ T x;
+ T y;
+ T from;
+ const T (&l)[5] = da;
+ T *m;
+ S7 s7;
+
+#pragma omp target update from // expected-error {{expected '(' after 'from'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from() // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update() // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(alloc) // expected-error {{use of undeclared identifier 'alloc'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(x)
+#pragma omp target update from(t[:I])
+#pragma omp target update from(T) // expected-error {{'T' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(I) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(S2::S2s)
+#pragma omp target update from(S2::S2sc)
+#pragma omp target update from(from)
+#pragma omp target update from(y x) // expected-error {{expected ',' or ')' in 'from' clause}}
+#pragma omp target update from(argc > 0 ? x : y) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target update from(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(h) // expected-error {{threadprivate variables are not allowed in 'from' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(k), to(k) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}}
+#pragma omp target update from(t), from(t[:5]) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}}
+#pragma omp target update from(da)
+#pragma omp target update from(da[:4])
+
+#pragma omp target update from(x, a[:2]) // expected-error {{subscripted value is not an array or pointer}}
+#pragma omp target update from(x, c[:]) // expected-error {{subscripted value is not an array or pointer}}
+#pragma omp target update from(x, (m+1)[2]) // expected-error 2 {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(s7.i, s7.a[:3])
+#pragma omp target update from(s7.s6[1].aa[0:5])
+#pragma omp target update from(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}}
+#pragma omp target update from(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}}
+#pragma omp target update from(s7.p[:10])
+#pragma omp target update from(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'from' clause}}
+#pragma omp target update from(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+#pragma omp target data map(to: s7.i)
+ {
+#pragma omp target update from(s7.x)
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ const int d = 5;
+ const int da[5] = { 0 };
+ S4 e(4);
+ S5 g(5);
+ int i, t[20];
+ int &j = i;
+ int *k = &j;
+ int x;
+ int y;
+ int from;
+ const int (&l)[5] = da;
+ int *m;
+ S7 s7;
+
+#pragma omp target update from // expected-error {{expected '(' after 'from'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from() // expected-error {{expected expression}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update() // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(alloc) // expected-error {{use of undeclared identifier 'alloc'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(x)
+#pragma omp target update from(t[:i])
+#pragma omp target update from(S2::S2s)
+#pragma omp target update from(S2::S2sc)
+#pragma omp target update from(from)
+#pragma omp target update from(y x) // expected-error {{expected ',' or ')' in 'from' clause}}
+#pragma omp target update from(argc > 0 ? x : y) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(S1) // expected-error {{'S1' does not refer to a value}}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
+#pragma omp target update from(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(h) // expected-error {{threadprivate variables are not allowed in 'from' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(k), to(k) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}}
+#pragma omp target update from(t), from(t[:5]) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}}
+#pragma omp target update from(da)
+#pragma omp target update from(da[:4])
+
+#pragma omp target update from(x, a[:2]) // expected-error {{subscripted value is not an array or pointer}}
+#pragma omp target update from(x, c[:]) // expected-error {{subscripted value is not an array or pointer}}
+#pragma omp target update from(x, (m+1)[2]) // expected-error {{expected expression containing only member accesses and/or array sections based on named variables}}
+#pragma omp target update from(s7.i, s7.a[:3])
+#pragma omp target update from(s7.s6[1].aa[0:5])
+#pragma omp target update from(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP array section is not allowed here}}
+#pragma omp target update from(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP array section is not allowed here}}
+#pragma omp target update from(s7.p[:10])
+#pragma omp target update from(x, s7.bfa) // expected-error {{bit fields cannot be used to specify storage in a 'from' clause}}
+#pragma omp target update from(x, s7.p[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
+#pragma omp target data map(to: s7.i)
+ {
+#pragma omp target update from(s7.x)
+ }
+
+ return tmain<int, 3>(argc)+tmain<to, 4>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 3>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
+}
+
diff --git a/clang/test/OpenMP/target_update_if_messages.cpp b/clang/test/OpenMP/target_update_if_messages.cpp
index 6d94105aef8..97715e07242 100644
--- a/clang/test/OpenMP/target_update_if_messages.cpp
+++ b/clang/test/OpenMP/target_update_if_messages.cpp
@@ -13,46 +13,46 @@ template <class T, class S> // expected-note {{declared here}}
int tmain(T argc, S **argv) {
int n;
#pragma omp target update to(n) if // expected-error {{expected '(' after 'if'}}
-#pragma omp target update if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if () // expected-error {{expected expression}}
-#pragma omp target update if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
-#pragma omp target update if (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if (argc > 0 ? argv[1] : argv[2])
#pragma omp target update to(n) if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}}
-#pragma omp target update if (S) // expected-error {{'S' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if (S) // expected-error {{'S' does not refer to a value}}
#pragma omp target update to(n) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(argc)
-#pragma omp target update if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(n) if(target update : argc)
-#pragma omp target update if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}}
#pragma omp target update to(n) if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}}
-#pragma omp target update if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(n) if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
return 0;
}
int main(int argc, char **argv) {
int m;
#pragma omp target update to(m) if // expected-error {{expected '(' after 'if'}}
-#pragma omp target update if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if () // expected-error {{expected expression}}
-#pragma omp target update if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if (argc)) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
-#pragma omp target update if (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if (argc > 0 ? argv[1] : argv[2])
#pragma omp target update to(m) if (foobool(argc)), if (true) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause}}
-#pragma omp target update if (S1) // expected-error {{'S1' does not refer to a value}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if (S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp target update to(m) if (argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if (argc argc) // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if (1 0) // expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if(if(tmain(argc, argv) // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if(target update // expected-warning {{missing ':' after directive name modifier - ignoring}} expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if(target update : // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp target update to(m) if(target update : argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp target update if(target update : argc) // expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if(target update : argc)
#pragma omp target update to(m) if(target update : argc) if (for:argc) // expected-error {{directive name modifier 'for' is not allowed for '#pragma omp target update'}}
-#pragma omp target update if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
+#pragma omp target update from(m) if(target update : argc) if (target update:argc) // expected-error {{directive '#pragma omp target update' cannot contain more than one 'if' clause with 'target update' name modifier}}
#pragma omp target update to(m) if(target update : argc) if (argc) // expected-error {{no more 'if' clause is allowed}} expected-note {{previous clause with directive name modifier specified here}}
return tmain(argc, argv);
}
diff --git a/clang/test/OpenMP/target_update_messages.cpp b/clang/test/OpenMP/target_update_messages.cpp
index fbebab67687..73f1eeca8ef 100644
--- a/clang/test/OpenMP/target_update_messages.cpp
+++ b/clang/test/OpenMP/target_update_messages.cpp
@@ -24,7 +24,7 @@ int main(int argc, char **argv) {
#pragma omp target update to(m) ] // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
#pragma omp target update to(m) ) // expected-warning {{extra tokens at the end of '#pragma omp target update' are ignored}}
- #pragma omp target update to(m) // OK
+ #pragma omp target update from(m) // OK
{
foo();
}
diff --git a/clang/test/OpenMP/target_update_to_messages.cpp b/clang/test/OpenMP/target_update_to_messages.cpp
index 6096b10b451..641d0bd949a 100644
--- a/clang/test/OpenMP/target_update_to_messages.cpp
+++ b/clang/test/OpenMP/target_update_to_messages.cpp
@@ -97,7 +97,7 @@ T tmain(T argc) {
#pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
#pragma omp target update to(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
#pragma omp target update to(h) // expected-error {{threadprivate variables are not allowed in 'to' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update to(k), to(k) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}}
+#pragma omp target update to(k), from(k) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}}
#pragma omp target update to(t), to(t[:5]) // expected-error 2 {{variable can appear only once in OpenMP 'target update' construct}} expected-note 2 {{used here}}
#pragma omp target update to(da)
#pragma omp target update to(da[:4])
@@ -150,7 +150,7 @@ int main(int argc, char **argv) {
#pragma omp target update to(a, b, c, d, f) // expected-error {{incomplete type 'S1' where a complete type is required}} expected-error 2 {{type 'S2' is not mappable to target}}
#pragma omp target update to(ba) // expected-error 2 {{type 'S2' is not mappable to target}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
#pragma omp target update to(h) // expected-error {{threadprivate variables are not allowed in 'to' clause}} expected-error {{expected at least one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
-#pragma omp target update to(k), to(k) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}}
+#pragma omp target update to(k), from(k) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}}
#pragma omp target update to(t), to(t[:5]) // expected-error {{variable can appear only once in OpenMP 'target update' construct}} expected-note {{used here}}
#pragma omp target update to(da)
#pragma omp target update to(da[:4])
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 29e47fc6600..78df3ce264c 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2249,6 +2249,9 @@ void OMPClauseEnqueue::VisitOMPDefaultmapClause(
void OMPClauseEnqueue::VisitOMPToClause(const OMPToClause *C) {
VisitOMPClauseList(C);
}
+void OMPClauseEnqueue::VisitOMPFromClause(const OMPFromClause *C) {
+ VisitOMPClauseList(C);
+}
}
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
OpenPOWER on IntegriCloud