forked from OSchip/llvm-project
[OPENMP] Parsing and sema analysis for 'copyprivate' clause.
llvm-svn: 211886
This commit is contained in:
parent
8f1f87c734
commit
bae9a793fd
|
@ -2433,6 +2433,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
|
||||
OMPCopyprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
|
||||
|
|
|
@ -1218,6 +1218,66 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'copyprivate' in the '#pragma omp ...'
|
||||
/// directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp single copyprivate(a,b)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp single' has clause 'copyprivate'
|
||||
/// with the variables 'a' and 'b'.
|
||||
///
|
||||
class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
|
||||
/// \brief Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param N Number of the variables in the clause.
|
||||
///
|
||||
OMPCopyprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
: OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc,
|
||||
LParenLoc, EndLoc, N) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
///
|
||||
explicit OMPCopyprivateClause(unsigned N)
|
||||
: OMPVarListClause<OMPCopyprivateClause>(
|
||||
OMPC_copyprivate, SourceLocation(), SourceLocation(),
|
||||
SourceLocation(), N) {}
|
||||
|
||||
public:
|
||||
/// \brief Creates clause with a list of variables \a VL.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param VL List of references to the variables.
|
||||
///
|
||||
static OMPCopyprivateClause *
|
||||
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> VL);
|
||||
/// \brief Creates an empty clause with \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of variables.
|
||||
///
|
||||
static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
|
||||
|
||||
StmtRange children() {
|
||||
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_copyprivate;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2455,6 +2455,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
|
||||
OMPCopyprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
|
||||
|
|
|
@ -7026,6 +7026,8 @@ def note_omp_predetermined_dsa : Note<
|
|||
"global variable is predetermined as shared|"
|
||||
"variable with automatic storage duration is predetermined as private}0"
|
||||
"%select{|; perhaps you forget to enclose 'omp %2' directive into a parallel or another task region?}1">;
|
||||
def note_omp_implicit_dsa : Note<
|
||||
"implicitly determined as %0">;
|
||||
def err_omp_loop_var_dsa : Error<
|
||||
"loop iteration variable may not be %0">;
|
||||
def err_omp_not_for : Error<
|
||||
|
|
|
@ -67,6 +67,7 @@ OPENMP_CLAUSE(reduction, OMPReductionClause)
|
|||
OPENMP_CLAUSE(linear, OMPLinearClause)
|
||||
OPENMP_CLAUSE(aligned, OMPAlignedClause)
|
||||
OPENMP_CLAUSE(copyin, OMPCopyinClause)
|
||||
OPENMP_CLAUSE(copyprivate, OMPCopyprivateClause)
|
||||
OPENMP_CLAUSE(proc_bind, OMPProcBindClause)
|
||||
OPENMP_CLAUSE(schedule, OMPScheduleClause)
|
||||
OPENMP_CLAUSE(ordered, OMPOrderedClause)
|
||||
|
@ -111,6 +112,7 @@ OPENMP_SECTIONS_CLAUSE(nowait)
|
|||
// TODO more clauses allowed for directive 'omp single'.
|
||||
OPENMP_SINGLE_CLAUSE(private)
|
||||
OPENMP_SINGLE_CLAUSE(firstprivate)
|
||||
OPENMP_SINGLE_CLAUSE(copyprivate)
|
||||
OPENMP_SINGLE_CLAUSE(nowait)
|
||||
|
||||
// Static attributes for 'default' clause.
|
||||
|
|
|
@ -7279,8 +7279,8 @@ public:
|
|||
Expr *Op);
|
||||
/// \brief Called on start of new data sharing attribute block.
|
||||
void StartOpenMPDSABlock(OpenMPDirectiveKind K,
|
||||
const DeclarationNameInfo &DirName,
|
||||
Scope *CurScope);
|
||||
const DeclarationNameInfo &DirName, Scope *CurScope,
|
||||
SourceLocation Loc);
|
||||
/// \brief Called on end of data sharing attribute block.
|
||||
void EndOpenMPDSABlock(Stmt *CurDirective);
|
||||
|
||||
|
@ -7300,8 +7300,7 @@ public:
|
|||
ArrayRef<Expr *> VarList);
|
||||
|
||||
// brief Initialization of captured region for OpenMP region.
|
||||
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
|
||||
Scope *CurScope);
|
||||
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
|
||||
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
|
@ -7460,6 +7459,11 @@ public:
|
|||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'copyprivate' clause.
|
||||
OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// \brief The kind of conversion being performed.
|
||||
enum CheckedConversionKind {
|
||||
|
|
|
@ -1280,6 +1280,28 @@ OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPCopyinClause(N);
|
||||
}
|
||||
|
||||
OMPCopyprivateClause *OMPCopyprivateClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * VL.size());
|
||||
OMPCopyprivateClause *Clause =
|
||||
new (Mem) OMPCopyprivateClause(StartLoc, LParenLoc, EndLoc, VL.size());
|
||||
Clause->setVarRefs(VL);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPCopyprivateClause *OMPCopyprivateClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned N) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyprivateClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * N);
|
||||
return new (Mem) OMPCopyprivateClause(N);
|
||||
}
|
||||
|
||||
void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
|
||||
assert(Clauses.size() == getNumClauses() &&
|
||||
"Number of clauses is not the same as the preallocated buffer");
|
||||
|
|
|
@ -748,6 +748,14 @@ void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
|
|||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPCopyprivateClause(OMPCopyprivateClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "copyprivate";
|
||||
VisitOMPClauseList(Node, '(');
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -335,6 +335,10 @@ void OMPClauseProfiler::VisitOMPAlignedClause(const OMPAlignedClause *C) {
|
|||
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void
|
||||
OMPClauseProfiler::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -95,6 +95,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_ordered:
|
||||
case OMPC_nowait:
|
||||
break;
|
||||
|
@ -149,6 +150,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_ordered:
|
||||
case OMPC_nowait:
|
||||
break;
|
||||
|
@ -193,7 +195,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
|||
break;
|
||||
case OMPD_sections:
|
||||
switch (CKind) {
|
||||
#define OPENMP_SECTIONS_CLAUSE(Name) \
|
||||
#define OPENMP_SECTIONS_CLAUSE(Name) \
|
||||
case OMPC_##Name: \
|
||||
return true;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
@ -203,7 +205,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
|||
break;
|
||||
case OMPD_single:
|
||||
switch (CKind) {
|
||||
#define OPENMP_SINGLE_CLAUSE(Name) \
|
||||
#define OPENMP_SINGLE_CLAUSE(Name) \
|
||||
case OMPC_##Name: \
|
||||
return true;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
|
|
@ -131,7 +131,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
|||
if (isOpenMPSimdDirective(DKind))
|
||||
ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
|
||||
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
||||
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope());
|
||||
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
|
||||
|
||||
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
OpenMPClauseKind CKind = Tok.isAnnotation()
|
||||
|
@ -159,7 +159,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
|||
{
|
||||
// The body is a block scope like in Lambdas and Blocks.
|
||||
Sema::CompoundScopeRAII CompoundScope(Actions);
|
||||
Actions.ActOnOpenMPRegionStart(DKind, Loc, getCurScope());
|
||||
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
|
||||
Actions.ActOnStartOfCompoundStmt();
|
||||
// Parse statement
|
||||
AssociatedStmt = ParseStatement();
|
||||
|
@ -269,7 +269,8 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
|||
/// if-clause | num_threads-clause | safelen-clause | default-clause |
|
||||
/// private-clause | firstprivate-clause | shared-clause | linear-clause |
|
||||
/// aligned-clause | collapse-clause | lastprivate-clause |
|
||||
/// reduction-clause | proc_bind-clause | schedule-clause
|
||||
/// reduction-clause | proc_bind-clause | schedule-clause |
|
||||
/// copyin-clause | copyprivate-clause
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause) {
|
||||
|
@ -345,6 +346,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
Clause = ParseOpenMPVarListClause(CKind);
|
||||
break;
|
||||
case OMPC_unknown:
|
||||
|
|
|
@ -68,7 +68,10 @@ public:
|
|||
OpenMPDirectiveKind DKind;
|
||||
OpenMPClauseKind CKind;
|
||||
DeclRefExpr *RefExpr;
|
||||
DSAVarData() : DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr) {}
|
||||
SourceLocation ImplicitDSALoc;
|
||||
DSAVarData()
|
||||
: DKind(OMPD_unknown), CKind(OMPC_unknown), RefExpr(nullptr),
|
||||
ImplicitDSALoc() {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -83,17 +86,20 @@ private:
|
|||
DeclSAMapTy SharingMap;
|
||||
AlignedMapTy AlignedMap;
|
||||
DefaultDataSharingAttributes DefaultAttr;
|
||||
SourceLocation DefaultAttrLoc;
|
||||
OpenMPDirectiveKind Directive;
|
||||
DeclarationNameInfo DirectiveName;
|
||||
Scope *CurScope;
|
||||
SourceLocation ConstructLoc;
|
||||
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
|
||||
Scope *CurScope)
|
||||
Scope *CurScope, SourceLocation Loc)
|
||||
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
|
||||
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope) {
|
||||
}
|
||||
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
|
||||
ConstructLoc(Loc) {}
|
||||
SharingMapTy()
|
||||
: SharingMap(), AlignedMap(), DefaultAttr(DSA_unspecified),
|
||||
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr) {}
|
||||
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
|
||||
ConstructLoc() {}
|
||||
};
|
||||
|
||||
typedef SmallVector<SharingMapTy, 64> StackTy;
|
||||
|
@ -113,8 +119,9 @@ public:
|
|||
explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
|
||||
|
||||
void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
|
||||
Scope *CurScope) {
|
||||
Stack.push_back(SharingMapTy(DKind, DirName, CurScope));
|
||||
Scope *CurScope, SourceLocation Loc) {
|
||||
Stack.push_back(SharingMapTy(DKind, DirName, CurScope, Loc));
|
||||
Stack.back().DefaultAttrLoc = Loc;
|
||||
}
|
||||
|
||||
void pop() {
|
||||
|
@ -160,13 +167,22 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Set default data sharing attribute to none.
|
||||
void setDefaultDSANone() { Stack.back().DefaultAttr = DSA_none; }
|
||||
void setDefaultDSANone(SourceLocation Loc) {
|
||||
Stack.back().DefaultAttr = DSA_none;
|
||||
Stack.back().DefaultAttrLoc = Loc;
|
||||
}
|
||||
/// \brief Set default data sharing attribute to shared.
|
||||
void setDefaultDSAShared() { Stack.back().DefaultAttr = DSA_shared; }
|
||||
void setDefaultDSAShared(SourceLocation Loc) {
|
||||
Stack.back().DefaultAttr = DSA_shared;
|
||||
Stack.back().DefaultAttrLoc = Loc;
|
||||
}
|
||||
|
||||
DefaultDataSharingAttributes getDefaultDSA() const {
|
||||
return Stack.back().DefaultAttr;
|
||||
}
|
||||
SourceLocation getDefaultDSALocation() const {
|
||||
return Stack.back().DefaultAttrLoc;
|
||||
}
|
||||
|
||||
/// \brief Checks if the specified variable is a threadprivate.
|
||||
bool isThreadPrivate(VarDecl *D) {
|
||||
|
@ -176,6 +192,7 @@ public:
|
|||
|
||||
Scope *getCurScope() const { return Stack.back().CurScope; }
|
||||
Scope *getCurScope() { return Stack.back().CurScope; }
|
||||
SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
@ -227,6 +244,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
|
|||
switch (Iter->DefaultAttr) {
|
||||
case DSA_shared:
|
||||
DVar.CKind = OMPC_shared;
|
||||
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
|
||||
return DVar;
|
||||
case DSA_none:
|
||||
return DVar;
|
||||
|
@ -235,6 +253,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter,
|
|||
// in a Construct, implicitly determined, p.2]
|
||||
// In a parallel construct, if no default clause is present, these
|
||||
// variables are shared.
|
||||
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
|
||||
if (isOpenMPParallelDirective(DVar.DKind)) {
|
||||
DVar.CKind = OMPC_shared;
|
||||
return DVar;
|
||||
|
@ -456,8 +475,8 @@ void Sema::DestroyDataSharingAttributesStack() { delete DSAStack; }
|
|||
|
||||
void Sema::StartOpenMPDSABlock(OpenMPDirectiveKind DKind,
|
||||
const DeclarationNameInfo &DirName,
|
||||
Scope *CurScope) {
|
||||
DSAStack->push(DKind, DirName, CurScope);
|
||||
Scope *CurScope, SourceLocation Loc) {
|
||||
DSAStack->push(DKind, DirName, CurScope, Loc);
|
||||
PushExpressionEvaluationContext(PotentiallyEvaluated);
|
||||
}
|
||||
|
||||
|
@ -776,8 +795,9 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
|
|||
PDSA_LoopIterVarLastprivate,
|
||||
PDSA_ConstVarShared,
|
||||
PDSA_GlobalVarShared,
|
||||
PDSA_LocalVarPrivate
|
||||
} Reason;
|
||||
PDSA_LocalVarPrivate,
|
||||
PDSA_Implicit
|
||||
} Reason = PDSA_Implicit;
|
||||
bool ReportHint = false;
|
||||
if (IsLoopIterVar) {
|
||||
if (DVar.CKind == OMPC_private)
|
||||
|
@ -794,14 +814,18 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack,
|
|||
Reason = PDSA_GlobalVarShared;
|
||||
else if (VD->getType().isConstant(SemaRef.getASTContext()))
|
||||
Reason = PDSA_ConstVarShared;
|
||||
else {
|
||||
else if (VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
|
||||
ReportHint = true;
|
||||
Reason = PDSA_LocalVarPrivate;
|
||||
}
|
||||
|
||||
SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
|
||||
<< Reason << ReportHint
|
||||
<< getOpenMPDirectiveName(Stack->getCurrentDirective());
|
||||
if (Reason != PDSA_Implicit) {
|
||||
SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa)
|
||||
<< Reason << ReportHint
|
||||
<< getOpenMPDirectiveName(Stack->getCurrentDirective());
|
||||
} else if (DVar.ImplicitDSALoc.isValid()) {
|
||||
SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
|
||||
<< getOpenMPClauseName(DVar.CKind);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -882,8 +906,7 @@ public:
|
|||
};
|
||||
} // namespace
|
||||
|
||||
void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
|
||||
Scope *CurScope) {
|
||||
void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
|
||||
switch (DKind) {
|
||||
case OMPD_parallel: {
|
||||
QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1);
|
||||
|
@ -893,42 +916,48 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, SourceLocation Loc,
|
|||
std::make_pair(".bound_tid.", KmpInt32PtrTy),
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_simd: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_for: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_sections: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_section: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_single: {
|
||||
Sema::CapturedParamNameType Params[] = {
|
||||
std::make_pair(StringRef(), QualType()) // __context with shared vars
|
||||
};
|
||||
ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP, Params);
|
||||
ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP,
|
||||
Params);
|
||||
break;
|
||||
}
|
||||
case OMPD_threadprivate:
|
||||
|
@ -1695,6 +1724,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_ordered:
|
||||
case OMPC_nowait:
|
||||
case OMPC_threadprivate:
|
||||
|
@ -1874,6 +1904,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_ordered:
|
||||
case OMPC_nowait:
|
||||
case OMPC_threadprivate:
|
||||
|
@ -1914,10 +1945,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
|
|||
}
|
||||
switch (Kind) {
|
||||
case OMPC_DEFAULT_none:
|
||||
DSAStack->setDefaultDSANone();
|
||||
DSAStack->setDefaultDSANone(KindKwLoc);
|
||||
break;
|
||||
case OMPC_DEFAULT_shared:
|
||||
DSAStack->setDefaultDSAShared();
|
||||
DSAStack->setDefaultDSAShared(KindKwLoc);
|
||||
break;
|
||||
case OMPC_DEFAULT_unknown:
|
||||
llvm_unreachable("Clause kind is not allowed.");
|
||||
|
@ -1984,6 +2015,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_ordered:
|
||||
case OMPC_nowait:
|
||||
case OMPC_threadprivate:
|
||||
|
@ -2073,6 +2105,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
|
|||
case OMPC_linear:
|
||||
case OMPC_aligned:
|
||||
case OMPC_copyin:
|
||||
case OMPC_copyprivate:
|
||||
case OMPC_default:
|
||||
case OMPC_proc_bind:
|
||||
case OMPC_threadprivate:
|
||||
|
@ -2126,6 +2159,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
|
|||
case OMPC_copyin:
|
||||
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_copyprivate:
|
||||
Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_safelen:
|
||||
|
@ -3281,4 +3317,108 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
|
|||
return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
SmallVector<Expr *, 8> Vars;
|
||||
for (auto &RefExpr : VarList) {
|
||||
assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
|
||||
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(RefExpr);
|
||||
continue;
|
||||
}
|
||||
|
||||
SourceLocation ELoc = RefExpr->getExprLoc();
|
||||
// OpenMP [2.1, C/C++]
|
||||
// A list item is a variable name.
|
||||
// OpenMP [2.14.4.1, Restrictions, p.1]
|
||||
// A list item that appears in a copyin clause must be threadprivate.
|
||||
DeclRefExpr *DE = dyn_cast<DeclRefExpr>(RefExpr);
|
||||
if (!DE || !isa<VarDecl>(DE->getDecl())) {
|
||||
Diag(ELoc, diag::err_omp_expected_var_name) << RefExpr->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
|
||||
Decl *D = DE->getDecl();
|
||||
VarDecl *VD = cast<VarDecl>(D);
|
||||
|
||||
QualType Type = VD->getType();
|
||||
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(DE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.14.4.2, Restrictions, p.2]
|
||||
// A list item that appears in a copyprivate clause may not appear in a
|
||||
// private or firstprivate clause on the single construct.
|
||||
if (!DSAStack->isThreadPrivate(VD)) {
|
||||
auto DVar = DSAStack->getTopDSA(VD);
|
||||
if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown &&
|
||||
!(DVar.CKind == OMPC_private && !DVar.RefExpr)) {
|
||||
Diag(ELoc, diag::err_omp_wrong_dsa)
|
||||
<< getOpenMPClauseName(DVar.CKind)
|
||||
<< getOpenMPClauseName(OMPC_copyprivate);
|
||||
ReportOriginalDSA(*this, DSAStack, VD, DVar);
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.11.4.2, Restrictions, p.1]
|
||||
// All list items that appear in a copyprivate clause must be either
|
||||
// threadprivate or private in the enclosing context.
|
||||
if (DVar.CKind == OMPC_unknown) {
|
||||
DVar = DSAStack->getImplicitDSA(VD);
|
||||
if (DVar.CKind == OMPC_shared) {
|
||||
Diag(ELoc, diag::err_omp_required_access)
|
||||
<< getOpenMPClauseName(OMPC_copyprivate)
|
||||
<< "threadprivate or private in the enclosing context";
|
||||
ReportOriginalDSA(*this, DSAStack, VD, DVar);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
|
||||
// A variable of class type (or array thereof) that appears in a
|
||||
// copyin clause requires an accessible, unambiguous copy assignment
|
||||
// operator for the class type.
|
||||
Type = Context.getBaseElementType(Type);
|
||||
CXXRecordDecl *RD =
|
||||
getLangOpts().CPlusPlus ? Type->getAsCXXRecordDecl() : nullptr;
|
||||
// FIXME This code must be replaced by actual assignment of the
|
||||
// threadprivate variable.
|
||||
if (RD) {
|
||||
CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
|
||||
DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
|
||||
if (MD) {
|
||||
if (CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
|
||||
MD->isDeleted()) {
|
||||
Diag(ELoc, diag::err_omp_required_method)
|
||||
<< getOpenMPClauseName(OMPC_copyprivate) << 2;
|
||||
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< VD;
|
||||
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
|
||||
continue;
|
||||
}
|
||||
MarkFunctionReferenced(ELoc, MD);
|
||||
DiagnoseUseOfDecl(MD, ELoc);
|
||||
}
|
||||
}
|
||||
|
||||
// No need to mark vars as copyprivate, they are already threadprivate or
|
||||
// implicitly private.
|
||||
Vars.push_back(DE);
|
||||
}
|
||||
|
||||
if (Vars.empty())
|
||||
return nullptr;
|
||||
|
||||
return OMPCopyprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
#undef DSAStack
|
||||
|
|
|
@ -1494,6 +1494,18 @@ public:
|
|||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'copyprivate' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPCopyprivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -6403,7 +6415,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6413,7 +6426,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSimdDirective(OMPSimdDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_simd, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6423,7 +6437,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPForDirective(OMPForDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_for, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6433,7 +6448,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSectionsDirective(OMPSectionsDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_sections, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6443,7 +6459,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSectionDirective(OMPSectionDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_section, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6453,7 +6470,8 @@ template <typename Derived>
|
|||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr);
|
||||
getDerived().getSema().StartOpenMPDSABlock(OMPD_single, DirName, nullptr,
|
||||
D->getLocStart());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
|
@ -6680,6 +6698,21 @@ TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
|
|||
C->getLParenLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPCopyprivateClause(OMPCopyprivateClause *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 nullptr;
|
||||
Vars.push_back(EVar.get());
|
||||
}
|
||||
return getDerived().RebuildOMPCopyprivateClause(
|
||||
Vars, C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expression transformation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1724,6 +1724,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_copyin:
|
||||
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
case OMPC_copyprivate:
|
||||
C = OMPCopyprivateClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
}
|
||||
Visit(C);
|
||||
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
|
||||
|
@ -1871,6 +1874,16 @@ void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
|||
C->setVarRefs(Vars);
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
unsigned NumVars = C->varlist_size();
|
||||
SmallVector<Expr *, 16> Vars;
|
||||
Vars.reserve(NumVars);
|
||||
for (unsigned i = 0; i != NumVars; ++i)
|
||||
Vars.push_back(Reader->Reader.ReadSubExpr());
|
||||
C->setVarRefs(Vars);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1782,6 +1782,13 @@ void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
|||
Writer->Writer.AddStmt(VE);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
for (auto *VE : C->varlists())
|
||||
Writer->Writer.AddStmt(VE);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -13,11 +13,11 @@ T tmain(T argc) {
|
|||
T b = argc, c, d, e, f, g;
|
||||
static T a;
|
||||
// CHECK: static T a;
|
||||
#pragma omp parallel
|
||||
#pragma omp single private(argc, b), firstprivate(c, d), nowait
|
||||
#pragma omp parallel private(g)
|
||||
#pragma omp single private(argc, b), firstprivate(c, d), nowait copyprivate(g)
|
||||
foo();
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d) nowait
|
||||
// CHECK-NEXT: #pragma omp parallel private(g)
|
||||
// CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(c,d) nowait copyprivate(g)
|
||||
// CHECK-NEXT: foo();
|
||||
return T();
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ int main(int argc, char **argv) {
|
|||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
#pragma omp parallel
|
||||
#pragma omp single private(argc, b), firstprivate(argv, c), nowait
|
||||
#pragma omp parallel private(g)
|
||||
#pragma omp single private(argc, b), firstprivate(argv, c), nowait copyprivate(g)
|
||||
foo();
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c) nowait
|
||||
// CHECK-NEXT: #pragma omp parallel private(g)
|
||||
// CHECK-NEXT: #pragma omp single private(argc,b) firstprivate(argv,c) nowait copyprivate(g)
|
||||
// CHECK-NEXT: foo();
|
||||
return (tmain<int, 5>(argc) + tmain<char, 1>(argv[0][0]));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
struct S1; // expected-note 2 {{declared here}}
|
||||
class S2 {
|
||||
mutable int a;
|
||||
|
||||
public:
|
||||
S2() : a(0) {}
|
||||
S2 &operator=(S2 &s2) { return *this; }
|
||||
};
|
||||
class S3 {
|
||||
int a;
|
||||
|
||||
public:
|
||||
S3() : a(0) {}
|
||||
S3 &operator=(S3 &s3) { return *this; }
|
||||
};
|
||||
class S4 { // expected-note 2 {{'S4' declared here}}
|
||||
int a;
|
||||
S4();
|
||||
S4 &operator=(const S4 &s4);
|
||||
|
||||
public:
|
||||
S4(int v) : a(v) {}
|
||||
};
|
||||
class S5 { // expected-note 2 {{'S5' declared here}}
|
||||
int a;
|
||||
S5() : a(0) {}
|
||||
S5 &operator=(const S5 &s5) { return *this; }
|
||||
|
||||
public:
|
||||
S5(int v) : a(v) {}
|
||||
};
|
||||
|
||||
S2 k;
|
||||
S3 h;
|
||||
S4 l(3); // expected-note 2 {{'l' defined here}}
|
||||
S5 m(4); // expected-note 2 {{'m' defined here}}
|
||||
#pragma omp threadprivate(h, k, l, m)
|
||||
|
||||
template <class T, class C>
|
||||
T tmain(T argc, C **argv) {
|
||||
T i;
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate // expected-error {{expected '(' after 'copyprivate'}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate() // expected-error {{expected expression}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(k // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(l) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(S1) // expected-error {{'S1' does not refer to a value}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(argv[1]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel // expected-note {{implicitly determined as shared}}
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(m) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}
|
||||
foo();
|
||||
#pragma omp parallel private(i)
|
||||
{
|
||||
#pragma omp single copyprivate(i)
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel shared(i) // expected-note {{defined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel private(i)
|
||||
#pragma omp parallel default(shared) // expected-note {{implicitly determined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel private(i)
|
||||
#pragma omp parallel // expected-note {{implicitly determined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp single private(i) copyprivate(i) // expected-error {{private variable cannot be copyprivate}} expected-note {{defined as private}}
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp single firstprivate(i) copyprivate(i) // expected-error {{firstprivate variable cannot be copyprivate}} expected-note {{defined as firstprivate}}
|
||||
foo();
|
||||
|
||||
return T();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate // expected-error {{expected '(' after 'copyprivate'}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate() // expected-error {{expected expression}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(k // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(l) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(S1) // expected-error {{'S1' does not refer to a value}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(argv[1]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel // expected-note {{implicitly determined as shared}}
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
#pragma omp parallel
|
||||
#pragma omp single copyprivate(m) // expected-error {{copyprivate variable must have an accessible, unambiguous copy assignment operator}}
|
||||
foo();
|
||||
#pragma omp parallel private(i)
|
||||
{
|
||||
#pragma omp single copyprivate(i)
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel shared(i) // expected-note {{defined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel private(i)
|
||||
#pragma omp parallel default(shared) // expected-note {{implicitly determined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel private(i)
|
||||
#pragma omp parallel // expected-note {{implicitly determined as shared}}
|
||||
{
|
||||
#pragma omp single copyprivate(i) // expected-error {{copyprivate variable must be threadprivate or private in the enclosing context}}
|
||||
foo();
|
||||
}
|
||||
#pragma omp parallel
|
||||
#pragma omp single private(i) copyprivate(i) // expected-error {{private variable cannot be copyprivate}} expected-note {{defined as private}}
|
||||
foo();
|
||||
#pragma omp parallel
|
||||
#pragma omp single firstprivate(i) copyprivate(i) // expected-error {{firstprivate variable cannot be copyprivate}} expected-note {{defined as firstprivate}}
|
||||
foo();
|
||||
|
||||
return tmain(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<int, char>' requested here}}
|
||||
}
|
|
@ -1989,6 +1989,10 @@ void OMPClauseEnqueue::VisitOMPAlignedClause(const OMPAlignedClause *C) {
|
|||
void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void
|
||||
OMPClauseEnqueue::VisitOMPCopyprivateClause(const OMPCopyprivateClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
}
|
||||
|
||||
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
|
||||
|
|
Loading…
Reference in New Issue