forked from OSchip/llvm-project
parent
79cfed55fc
commit
d48bcd8a46
|
@ -2405,6 +2405,12 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool DataRecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
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
|
||||
|
|
|
@ -95,7 +95,7 @@ protected:
|
|||
llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())));
|
||||
}
|
||||
|
||||
/// \brief Build clause with number of variables \a N.
|
||||
/// \brief Build a clause with \a N variables
|
||||
///
|
||||
/// \param K Kind of the clause.
|
||||
/// \param StartLoc Starting location of the clause (the clause keyword).
|
||||
|
@ -553,6 +553,65 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel copyin(a,b)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel' has clause 'copyin'
|
||||
/// with the variables 'a' and 'b'.
|
||||
///
|
||||
class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
|
||||
/// \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.
|
||||
///
|
||||
OMPCopyinClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc,
|
||||
EndLoc, N) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
///
|
||||
explicit OMPCopyinClause(unsigned N)
|
||||
: OMPVarListClause<OMPCopyinClause>(OMPC_copyin, 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 OMPCopyinClause *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 OMPCopyinClause *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_copyin;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2442,6 +2442,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
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
|
||||
|
|
|
@ -6915,6 +6915,8 @@ def note_omp_conversion_here : Note<
|
|||
def err_omp_ambiguous_conversion : Error<
|
||||
"ambiguous conversion from type %0 to an integral or unscoped "
|
||||
"enumeration type">;
|
||||
def err_omp_required_access : Error<
|
||||
"%0 variable must be %1">;
|
||||
} // end of OpenMP category
|
||||
|
||||
let CategoryName = "Related Result Type Issue" in {
|
||||
|
|
|
@ -42,6 +42,7 @@ OPENMP_CLAUSE(default, OMPDefaultClause)
|
|||
OPENMP_CLAUSE(private, OMPPrivateClause)
|
||||
OPENMP_CLAUSE(firstprivate, OMPFirstprivateClause)
|
||||
OPENMP_CLAUSE(shared, OMPSharedClause)
|
||||
OPENMP_CLAUSE(copyin, OMPCopyinClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
OPENMP_PARALLEL_CLAUSE(if)
|
||||
|
@ -50,6 +51,7 @@ OPENMP_PARALLEL_CLAUSE(default)
|
|||
OPENMP_PARALLEL_CLAUSE(private)
|
||||
OPENMP_PARALLEL_CLAUSE(firstprivate)
|
||||
OPENMP_PARALLEL_CLAUSE(shared)
|
||||
OPENMP_PARALLEL_CLAUSE(copyin)
|
||||
|
||||
// FIXME: more clauses allowed for directive 'omp simd'.
|
||||
OPENMP_SIMD_CLAUSE(private)
|
||||
|
|
|
@ -7210,6 +7210,11 @@ public:
|
|||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'copyin' clause.
|
||||
OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// \brief The kind of conversion being performed.
|
||||
enum CheckedConversionKind {
|
||||
|
|
|
@ -1192,6 +1192,28 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPSharedClause(N);
|
||||
}
|
||||
|
||||
OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * VL.size());
|
||||
OMPCopyinClause *Clause = new (Mem) OMPCopyinClause(StartLoc, LParenLoc,
|
||||
EndLoc, VL.size());
|
||||
Clause->setVarRefs(VL);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPCopyinClause *OMPCopyinClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned N) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPCopyinClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * N);
|
||||
return new (Mem) OMPCopyinClause(N);
|
||||
}
|
||||
|
||||
void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
|
||||
assert(Clauses.size() == getNumClauses() &&
|
||||
"Number of clauses is not the same as the preallocated buffer");
|
||||
|
|
|
@ -629,9 +629,15 @@ template<typename T>
|
|||
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
|
||||
for (typename T::varlist_iterator I = Node->varlist_begin(),
|
||||
E = Node->varlist_end();
|
||||
I != E; ++I)
|
||||
OS << (I == Node->varlist_begin() ? StartSym : ',')
|
||||
<< *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
|
||||
I != E; ++I) {
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*I)) {
|
||||
OS << (I == Node->varlist_begin() ? StartSym : ',');
|
||||
cast<NamedDecl>(DRE->getDecl())->printQualifiedName(OS);
|
||||
} else {
|
||||
OS << (I == Node->varlist_begin() ? StartSym : ',');
|
||||
(*I)->printPretty(OS, 0, Policy, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
|
||||
|
@ -658,6 +664,14 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
|
|||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "copyin";
|
||||
VisitOMPClauseList(Node, '(');
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -297,6 +297,9 @@ void OMPClauseProfiler::VisitOMPFirstprivateClause(
|
|||
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_copyin:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
}
|
||||
|
@ -109,6 +110,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_copyin:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_copyin:
|
||||
Clause = ParseOpenMPVarListClause(CKind);
|
||||
break;
|
||||
case OMPC_unknown:
|
||||
|
|
|
@ -111,7 +111,6 @@ public:
|
|||
DSAVarData hasDSA(VarDecl *D, OpenMPClauseKind CKind,
|
||||
OpenMPDirectiveKind DKind = OMPD_unknown);
|
||||
|
||||
|
||||
/// \brief Returns currently analyzed directive.
|
||||
OpenMPDirectiveKind getCurrentDirective() const {
|
||||
return Stack.back().Directive;
|
||||
|
@ -126,6 +125,13 @@ public:
|
|||
return Stack.back().DefaultAttr;
|
||||
}
|
||||
|
||||
/// \brief Checks if the spewcified variable is threadprivate.
|
||||
bool isThreadPrivate(VarDecl *D) {
|
||||
DSAVarData DVar = getTopDSA(D);
|
||||
return (DVar.CKind == OMPC_threadprivate || DVar.CKind == OMPC_copyin);
|
||||
}
|
||||
|
||||
Scope *getCurScope() const { return Stack.back().CurScope; }
|
||||
Scope *getCurScope() { return Stack.back().CurScope; }
|
||||
};
|
||||
} // end anonymous namespace.
|
||||
|
@ -245,7 +251,8 @@ void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
|
|||
}
|
||||
}
|
||||
|
||||
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
|
||||
bool
|
||||
DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
|
||||
if (Stack.size() > 2) {
|
||||
reverse_iterator I = Iter, E = Stack.rend() - 1;
|
||||
Scope *TopScope = 0;
|
||||
|
@ -611,7 +618,7 @@ public:
|
|||
DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD);
|
||||
if (DVar.CKind != OMPC_unknown) {
|
||||
if (DKind == OMPD_task && DVar.CKind != OMPC_shared &&
|
||||
DVar.CKind != OMPC_threadprivate && !DVar.RefExpr)
|
||||
!Stack->isThreadPrivate(VD) && !DVar.RefExpr)
|
||||
ImplicitFirstprivate.push_back(DVar.RefExpr);
|
||||
return;
|
||||
}
|
||||
|
@ -768,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_copyin:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
|
@ -922,6 +930,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_copyin:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
|
@ -992,6 +1001,9 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
|||
case OMPC_shared:
|
||||
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_copyin:
|
||||
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_if:
|
||||
case OMPC_num_threads:
|
||||
case OMPC_safelen:
|
||||
|
@ -1371,4 +1383,84 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
|
|||
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
SmallVector<Expr *, 8> Vars;
|
||||
for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
|
||||
I != E; ++I) {
|
||||
assert(*I && "NULL expr in OpenMP copyin clause.");
|
||||
if (isa<DependentScopeDeclRefExpr>(*I)) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
SourceLocation ELoc = (*I)->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>(*I);
|
||||
if (!DE || !isa<VarDecl>(DE->getDecl())) {
|
||||
Diag(ELoc, diag::err_omp_expected_var_name)
|
||||
<< (*I)->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.1, Restrictions, C/C++, p.1]
|
||||
// A list item that appears in a copyin clause must be threadprivate.
|
||||
if (!DSAStack->isThreadPrivate(VD)) {
|
||||
Diag(ELoc, diag::err_omp_required_access)
|
||||
<< getOpenMPClauseName(OMPC_copyin)
|
||||
<< getOpenMPDirectiveName(OMPD_threadprivate);
|
||||
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 accesible, unambiguous copy assignment
|
||||
// operator for the class type.
|
||||
Type = Context.getBaseElementType(Type);
|
||||
CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
|
||||
Type->getAsCXXRecordDecl() : 0;
|
||||
if (RD) {
|
||||
CXXMethodDecl *MD = LookupCopyingAssignment(RD, 0, false, 0);
|
||||
DeclAccessPair FoundDecl = DeclAccessPair::make(MD, MD->getAccess());
|
||||
if (!MD ||
|
||||
CheckMemberAccess(ELoc, RD, FoundDecl) == AR_inaccessible ||
|
||||
MD->isDeleted()) {
|
||||
Diag(ELoc, diag::err_omp_required_method)
|
||||
<< getOpenMPClauseName(OMPC_copyin) << 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);
|
||||
}
|
||||
|
||||
DSAStack->addDSA(VD, DE, OMPC_copyin);
|
||||
Vars.push_back(DE);
|
||||
}
|
||||
|
||||
if (Vars.empty()) return 0;
|
||||
|
||||
return OMPCopyinClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
#undef DSAStack
|
||||
|
|
|
@ -1382,6 +1382,18 @@ public:
|
|||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'copyin' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPCopyinClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -6422,6 +6434,25 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
|
|||
C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
|
||||
llvm::SmallVector<Expr *, 16> Vars;
|
||||
Vars.reserve(C->varlist_size());
|
||||
for (OMPCopyinClause::varlist_iterator I = C->varlist_begin(),
|
||||
E = C->varlist_end();
|
||||
I != E; ++I) {
|
||||
ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
|
||||
if (EVar.isInvalid())
|
||||
return 0;
|
||||
Vars.push_back(EVar.take());
|
||||
}
|
||||
return getDerived().RebuildOMPCopyinClause(Vars,
|
||||
C->getLocStart(),
|
||||
C->getLParenLoc(),
|
||||
C->getLocEnd());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expression transformation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1692,6 +1692,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_shared:
|
||||
C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
case OMPC_copyin:
|
||||
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
}
|
||||
Visit(C);
|
||||
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
|
||||
|
@ -1752,6 +1755,16 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
C->setVarRefs(Vars);
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1716,6 +1716,15 @@ void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
Writer->Writer.AddStmt(I);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
for (OMPCopyinClause::varlist_iterator I = C->varlist_begin(),
|
||||
E = C->varlist_end();
|
||||
I != E; ++I)
|
||||
Writer->Writer.AddStmt(*I);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -11,8 +11,23 @@ void foo() {}
|
|||
template <class T>
|
||||
struct S {
|
||||
operator T() {return T();}
|
||||
static T TS;
|
||||
#pragma omp threadprivate(TS)
|
||||
};
|
||||
|
||||
// CHECK: template <class T = int> struct S {
|
||||
// CHECK: static int TS;
|
||||
// CHECK-NEXT: #pragma omp threadprivate(S<int>::TS)
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: template <class T = long> struct S {
|
||||
// CHECK: static long TS;
|
||||
// CHECK-NEXT: #pragma omp threadprivate(S<long>::TS)
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: template <class T> struct S {
|
||||
// CHECK: static T TS;
|
||||
// CHECK-NEXT: #pragma omp threadprivate(S::TS)
|
||||
// CHECK: };
|
||||
|
||||
template <typename T, int C>
|
||||
T tmain(T argc, T *argv) {
|
||||
T b = argc, c, d, e, f, g;
|
||||
|
@ -20,19 +35,20 @@ T tmain(T argc, T *argv) {
|
|||
S<T> s;
|
||||
#pragma omp parallel
|
||||
a=2;
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C)
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) shared (d) if (argc > 0) num_threads(C) copyin(S<T>::TS)
|
||||
foo();
|
||||
#pragma omp parallel if (C) num_threads(s)
|
||||
foo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK: template <typename T = int, int C = 5> int tmain(int argc, int *argv) {
|
||||
// CHECK-NEXT: int b = argc, c, d, e, f, g;
|
||||
// CHECK-NEXT: static int a;
|
||||
// CHECK-NEXT: S<int> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(5) copyin(S<int>::TS)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(5) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
|
@ -42,7 +58,7 @@ T tmain(T argc, T *argv) {
|
|||
// CHECK-NEXT: S<long> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(1) copyin(S<long>::TS)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(1) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
|
@ -52,7 +68,7 @@ T tmain(T argc, T *argv) {
|
|||
// CHECK-NEXT: S<T> s;
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
// CHECK-NEXT: a = 2;
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) num_threads(C) copyin(S<T>::TS)
|
||||
// CHECK-NEXT: foo()
|
||||
// CHECK-NEXT: #pragma omp parallel if(C) num_threads(s)
|
||||
// CHECK-NEXT: foo()
|
||||
|
@ -63,14 +79,15 @@ int main (int argc, char **argv) {
|
|||
long x;
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
#pragma omp threadprivate(a)
|
||||
Enum ee;
|
||||
// CHECK: Enum ee;
|
||||
#pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
a=2;
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee)
|
||||
#pragma omp parallel default(none), private(argc,b) firstprivate(argv) if (argc > 0) num_threads(ee) copyin(a)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b) firstprivate(argv) if(argc > 0) num_threads(ee) copyin(a)
|
||||
foo();
|
||||
// CHECK-NEXT: foo();
|
||||
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 -o - %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{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 {{'S4' declared here}}
|
||||
int a;
|
||||
S4();
|
||||
S4 &operator =(const S4 &s4);
|
||||
public:
|
||||
S4(int v):a(v) { }
|
||||
};
|
||||
class S5 { // expected-note {{'S5' declared here}}
|
||||
int a;
|
||||
S5():a(0) {}
|
||||
S5 &operator =(const S5 &s5) { return *this; }
|
||||
public:
|
||||
S5(int v):a(v) { }
|
||||
};
|
||||
template <class T>
|
||||
class ST {
|
||||
public:
|
||||
static T s;
|
||||
};
|
||||
|
||||
|
||||
S2 k;
|
||||
S3 h;
|
||||
S4 l(3); // expected-note {{'l' defined here}}
|
||||
S5 m(4); // expected-note {{'m' defined here}}
|
||||
#pragma omp threadprivate(h, k, l, m)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
#pragma omp parallel copyin // expected-error {{expected '(' after 'copyin'}}
|
||||
#pragma omp parallel copyin ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel copyin () // expected-error {{expected expression}}
|
||||
#pragma omp parallel copyin (k // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel copyin (h, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel copyin (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel copyin (l) // expected-error {{copyin variable must have an accessible, unambiguous copy assignment operator}}
|
||||
#pragma omp parallel copyin (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
#pragma omp parallel copyin (argv[1]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel copyin(i) // expected-error {{copyin variable must be threadprivate}}
|
||||
#pragma omp parallel copyin(m) // expected-error {{copyin variable must have an accessible, unambiguous copy assignment operator}}
|
||||
#pragma omp parallel copyin(ST<int>::s) // expected-error {{copyin variable must be threadprivate}}
|
||||
foo();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1954,6 +1954,9 @@ void OMPClauseEnqueue::VisitOMPFirstprivateClause(
|
|||
void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
}
|
||||
|
||||
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
|
||||
|
|
Loading…
Reference in New Issue