forked from OSchip/llvm-project
[OPENMP] parsing 'linear' clause (for directive 'omp simd')
Differential Revision: http://reviews.llvm.org/D3272 llvm-svn: 206891
This commit is contained in:
parent
761aa37e3e
commit
8dba66412b
|
@ -2405,6 +2405,14 @@ bool DataRecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C)
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool
|
||||
DataRecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
TraverseStmt(C->getStep());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool DataRecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
|
|
|
@ -553,6 +553,91 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'linear' in the '#pragma omp ...'
|
||||
/// directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp simd linear(a,b : 2)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp simd' has clause 'linear'
|
||||
/// with variables 'a', 'b' and linear step '2'.
|
||||
///
|
||||
class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of ':'.
|
||||
SourceLocation ColonLoc;
|
||||
|
||||
/// \brief Sets the linear step for clause.
|
||||
void setStep(Expr *Step) { *varlist_end() = Step; }
|
||||
|
||||
/// \brief Build 'linear' clause with given number of variables \a NumVars.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param ColonLoc Location of ':'.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param NumVars Number of variables.
|
||||
///
|
||||
OMPLinearClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
unsigned NumVars)
|
||||
: OMPVarListClause<OMPLinearClause>(OMPC_linear, StartLoc, LParenLoc,
|
||||
EndLoc, NumVars),
|
||||
ColonLoc(ColonLoc) {}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
/// \param NumVars Number of variables.
|
||||
///
|
||||
explicit OMPLinearClause(unsigned NumVars)
|
||||
: OMPVarListClause<OMPLinearClause>(OMPC_linear, SourceLocation(),
|
||||
SourceLocation(), SourceLocation(),
|
||||
NumVars),
|
||||
ColonLoc(SourceLocation()) {}
|
||||
|
||||
public:
|
||||
/// \brief Creates clause with a list of variables \a VL and a linear step
|
||||
/// \a Step.
|
||||
///
|
||||
/// \param C AST Context.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param ColonLoc Location of ':'.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param VL List of references to the variables.
|
||||
/// \param Step Linear step.
|
||||
static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc, SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL, Expr *Step);
|
||||
|
||||
/// \brief Creates an empty clause with the place for \a NumVars variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param NumVars Number of variables.
|
||||
///
|
||||
static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars);
|
||||
|
||||
/// \brief Sets the location of ':'.
|
||||
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
SourceLocation getColonLoc() const { return ColonLoc; }
|
||||
|
||||
/// \brief Returns linear step.
|
||||
Expr *getStep() { return *varlist_end(); }
|
||||
/// \brief Returns linear step.
|
||||
const Expr *getStep() const { return *varlist_end(); }
|
||||
|
||||
StmtRange children() {
|
||||
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end() + 1));
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_linear;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
|
|
|
@ -2442,6 +2442,13 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
TraverseStmt(C->getStep());
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
|
|
|
@ -671,6 +671,7 @@ def ASM : DiagGroup<"asm", [
|
|||
|
||||
// OpenMP warnings.
|
||||
def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
|
||||
def OpenMPClauses : DiagGroup<"openmp-clauses">;
|
||||
|
||||
// Backend warnings.
|
||||
def BackendInlineAsm : DiagGroup<"inline-asm">;
|
||||
|
|
|
@ -6928,6 +6928,16 @@ def err_omp_ambiguous_conversion : Error<
|
|||
"enumeration type">;
|
||||
def err_omp_required_access : Error<
|
||||
"%0 variable must be %1">;
|
||||
def err_omp_const_variable : Error<
|
||||
"const-qualified variable cannot be %0">;
|
||||
def err_omp_linear_incomplete_type : Error<
|
||||
"a linear variable with incomplete type %0">;
|
||||
def err_omp_linear_expected_int_or_ptr : Error<
|
||||
"argument of a linear clause should be of integral or pointer "
|
||||
"type, not %0">;
|
||||
def warn_omp_linear_step_zero : Warning<
|
||||
"zero linear step (%0 %select{|and other variables in clause }1should probably be const)">,
|
||||
InGroup<OpenMPClauses>;
|
||||
} // 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(linear, OMPLinearClause)
|
||||
OPENMP_CLAUSE(copyin, OMPCopyinClause)
|
||||
|
||||
// Clauses allowed for OpenMP directive 'parallel'.
|
||||
|
@ -55,6 +56,7 @@ OPENMP_PARALLEL_CLAUSE(copyin)
|
|||
|
||||
// FIXME: more clauses allowed for directive 'omp simd'.
|
||||
OPENMP_SIMD_CLAUSE(private)
|
||||
OPENMP_SIMD_CLAUSE(linear)
|
||||
OPENMP_SIMD_CLAUSE(safelen)
|
||||
|
||||
// Static attributes for 'default' clause.
|
||||
|
|
|
@ -7286,8 +7286,10 @@ public:
|
|||
|
||||
OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||
ArrayRef<Expr *> Vars,
|
||||
Expr *TailExpr,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'private' clause.
|
||||
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
|
||||
|
@ -7304,6 +7306,13 @@ public:
|
|||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'linear' clause.
|
||||
OMPClause *ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList,
|
||||
Expr *Step,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'copyin' clause.
|
||||
OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
|
|
|
@ -1192,6 +1192,30 @@ OMPSharedClause *OMPSharedClause::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPSharedClause(N);
|
||||
}
|
||||
|
||||
OMPLinearClause *OMPLinearClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL, Expr *Step) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * (VL.size() + 1));
|
||||
OMPLinearClause *Clause = new (Mem)
|
||||
OMPLinearClause(StartLoc, LParenLoc, ColonLoc, EndLoc, VL.size());
|
||||
Clause->setVarRefs(VL);
|
||||
Clause->setStep(Step);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPLinearClause *OMPLinearClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumVars) {
|
||||
void *Mem = C.Allocate(llvm::RoundUpToAlignment(sizeof(OMPLinearClause),
|
||||
llvm::alignOf<Expr *>()) +
|
||||
sizeof(Expr *) * (NumVars + 1));
|
||||
return new (Mem) OMPLinearClause(NumVars);
|
||||
}
|
||||
|
||||
OMPCopyinClause *OMPCopyinClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
|
|
@ -664,6 +664,18 @@ void OMPClausePrinter::VisitOMPSharedClause(OMPSharedClause *Node) {
|
|||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPLinearClause(OMPLinearClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "linear";
|
||||
VisitOMPClauseList(Node, '(');
|
||||
if (Node->getStep() != 0) {
|
||||
OS << ": ";
|
||||
Node->getStep()->printPretty(OS, 0, Policy, 0);
|
||||
}
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPCopyinClause(OMPCopyinClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "copyin";
|
||||
|
|
|
@ -297,6 +297,10 @@ void OMPClauseProfiler::VisitOMPFirstprivateClause(
|
|||
void OMPClauseProfiler::VisitOMPSharedClause(const OMPSharedClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPLinearClause(const OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
Profiler->VisitStmt(C->getStep());
|
||||
}
|
||||
void OMPClauseProfiler::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_linear:
|
||||
case OMPC_copyin:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
|
@ -110,6 +111,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_linear:
|
||||
case OMPC_copyin:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
|
|
|
@ -258,7 +258,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
|||
///
|
||||
/// clause:
|
||||
/// if-clause | num_threads-clause | safelen-clause | default-clause |
|
||||
/// private-clause | firstprivate-clause | shared-clause
|
||||
/// private-clause | firstprivate-clause | shared-clause | linear-clause
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause) {
|
||||
|
@ -301,6 +301,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_linear:
|
||||
case OMPC_copyin:
|
||||
Clause = ParseOpenMPVarListClause(CKind);
|
||||
break;
|
||||
|
@ -392,10 +393,13 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
|
|||
/// 'firstprivate' '(' list ')'
|
||||
/// shared-clause:
|
||||
/// 'shared' '(' list ')'
|
||||
/// linear-clause:
|
||||
/// 'linear' '(' list [ ':' linear-step ] ')'
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
SourceLocation LOpen = ConsumeToken();
|
||||
SourceLocation ColonLoc = SourceLocation();
|
||||
// Parse '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
|
@ -404,8 +408,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
|
|||
|
||||
SmallVector<Expr *, 5> Vars;
|
||||
bool IsComma = true;
|
||||
while (IsComma || (Tok.isNot(tok::r_paren) &&
|
||||
const bool MayHaveTail = (Kind == OMPC_linear);
|
||||
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))) {
|
||||
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
|
||||
// Parse variable
|
||||
ExprResult VarExpr = ParseAssignmentExpression();
|
||||
if (VarExpr.isUsable()) {
|
||||
|
@ -416,21 +422,34 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
|
|||
}
|
||||
// Skip ',' if any
|
||||
IsComma = Tok.is(tok::comma);
|
||||
if (IsComma) {
|
||||
if (IsComma)
|
||||
ConsumeToken();
|
||||
} else if (Tok.isNot(tok::r_paren) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
Diag(Tok, diag::err_omp_expected_punc)
|
||||
<< getOpenMPClauseName(Kind);
|
||||
}
|
||||
else if (Tok.isNot(tok::r_paren) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end) &&
|
||||
(!MayHaveTail || Tok.isNot(tok::colon)))
|
||||
Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
|
||||
}
|
||||
|
||||
// Parse ':' linear-step
|
||||
Expr *TailExpr = 0;
|
||||
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
|
||||
if (MustHaveTail) {
|
||||
ColonLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
ExprResult Tail = ParseAssignmentExpression();
|
||||
if (Tail.isUsable())
|
||||
TailExpr = Tail.take();
|
||||
else
|
||||
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
||||
StopBeforeMatch);
|
||||
}
|
||||
|
||||
// Parse ')'.
|
||||
T.consumeClose();
|
||||
if (Vars.empty())
|
||||
if (Vars.empty() || (MustHaveTail && !TailExpr))
|
||||
return 0;
|
||||
|
||||
return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
|
||||
Tok.getLocation());
|
||||
return Actions.ActOnOpenMPVarListClause(Kind, Vars, TailExpr, Loc, LOpen,
|
||||
ColonLoc, Tok.getLocation());
|
||||
}
|
||||
|
||||
|
|
|
@ -294,9 +294,10 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) {
|
|||
if (Kind != OMPD_parallel) {
|
||||
if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() &&
|
||||
(D->getStorageClass() == SC_Auto ||
|
||||
D->getStorageClass() == SC_None))
|
||||
D->getStorageClass() == SC_None)) {
|
||||
DVar.CKind = OMPC_private;
|
||||
return DVar;
|
||||
}
|
||||
}
|
||||
|
||||
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
|
||||
|
@ -774,6 +775,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_linear:
|
||||
case OMPC_copyin:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
|
@ -929,6 +931,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
|||
case OMPC_private:
|
||||
case OMPC_firstprivate:
|
||||
case OMPC_shared:
|
||||
case OMPC_linear:
|
||||
case OMPC_copyin:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
|
@ -986,8 +989,10 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
|
|||
|
||||
OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||
ArrayRef<Expr *> VarList,
|
||||
Expr *TailExpr,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc) {
|
||||
OMPClause *Res = 0;
|
||||
switch (Kind) {
|
||||
|
@ -1000,6 +1005,10 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
|||
case OMPC_shared:
|
||||
Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_linear:
|
||||
Res = ActOnOpenMPLinearClause(VarList, TailExpr, StartLoc, LParenLoc,
|
||||
ColonLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_copyin:
|
||||
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
|
@ -1382,6 +1391,135 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList,
|
|||
return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
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 linear clause.");
|
||||
if (isa<DependentScopeDeclRefExpr>(*I)) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.14.3.7, linear clause]
|
||||
// A list item that appears in a linear clause is subject to the private
|
||||
// clause semantics described in Section 2.14.3.3 on page 159 except as
|
||||
// noted. In addition, the value of the new list item on each iteration
|
||||
// of the associated loop(s) corresponds to the value of the original
|
||||
// list item before entering the construct plus the logical number of
|
||||
// the iteration times linear-step.
|
||||
|
||||
SourceLocation ELoc = (*I)->getExprLoc();
|
||||
// OpenMP [2.1, C/C++]
|
||||
// A list item is a variable name.
|
||||
// OpenMP [2.14.3.3, Restrictions, p.1]
|
||||
// A variable that is part of another variable (as an array or
|
||||
// structure element) cannot appear in a private clause.
|
||||
DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I);
|
||||
if (!DE || !isa<VarDecl>(DE->getDecl())) {
|
||||
Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
|
||||
VarDecl *VD = cast<VarDecl>(DE->getDecl());
|
||||
|
||||
// OpenMP [2.14.3.7, linear clause]
|
||||
// A list-item cannot appear in more than one linear clause.
|
||||
// A list-item that appears in a linear clause cannot appear in any
|
||||
// other data-sharing attribute clause.
|
||||
DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD);
|
||||
if (DVar.RefExpr) {
|
||||
Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
|
||||
<< getOpenMPClauseName(OMPC_linear);
|
||||
Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
|
||||
<< getOpenMPClauseName(DVar.CKind);
|
||||
continue;
|
||||
}
|
||||
|
||||
QualType QType = VD->getType();
|
||||
if (QType->isDependentType() || QType->isInstantiationDependentType()) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(DE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// A variable must not have an incomplete type or a reference type.
|
||||
if (RequireCompleteType(ELoc, QType,
|
||||
diag::err_omp_linear_incomplete_type)) {
|
||||
continue;
|
||||
}
|
||||
if (QType->isReferenceType()) {
|
||||
Diag(ELoc, diag::err_omp_clause_ref_type_arg)
|
||||
<< getOpenMPClauseName(OMPC_linear) << QType;
|
||||
bool IsDecl =
|
||||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< VD;
|
||||
continue;
|
||||
}
|
||||
|
||||
// A list item must not be const-qualified.
|
||||
if (QType.isConstant(Context)) {
|
||||
Diag(ELoc, diag::err_omp_const_variable)
|
||||
<< getOpenMPClauseName(OMPC_linear);
|
||||
bool IsDecl =
|
||||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< VD;
|
||||
continue;
|
||||
}
|
||||
|
||||
// A list item must be of integral or pointer type.
|
||||
QType = QType.getUnqualifiedType().getCanonicalType();
|
||||
const Type *Ty = QType.getTypePtrOrNull();
|
||||
if (!Ty || (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
|
||||
!Ty->isPointerType())) {
|
||||
Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << QType;
|
||||
bool IsDecl =
|
||||
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(),
|
||||
IsDecl ? diag::note_previous_decl : diag::note_defined_here)
|
||||
<< VD;
|
||||
continue;
|
||||
}
|
||||
|
||||
DSAStack->addDSA(VD, DE, OMPC_linear);
|
||||
Vars.push_back(DE);
|
||||
}
|
||||
|
||||
if (Vars.empty())
|
||||
return 0;
|
||||
|
||||
Expr *StepExpr = Step;
|
||||
if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
|
||||
!Step->isInstantiationDependent() &&
|
||||
!Step->containsUnexpandedParameterPack()) {
|
||||
SourceLocation StepLoc = Step->getLocStart();
|
||||
ExprResult Val = PerformImplicitIntegerConversion(StepLoc, Step);
|
||||
if (Val.isInvalid())
|
||||
return 0;
|
||||
StepExpr = Val.take();
|
||||
|
||||
// Warn about zero linear step (it would be probably better specified as
|
||||
// making corresponding variables 'const').
|
||||
llvm::APSInt Result;
|
||||
if (StepExpr->isIntegerConstantExpr(Result, Context) &&
|
||||
!Result.isNegative() && !Result.isStrictlyPositive())
|
||||
Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0]
|
||||
<< (Vars.size() > 1);
|
||||
}
|
||||
|
||||
return OMPLinearClause::Create(Context, StartLoc, LParenLoc, ColonLoc, EndLoc,
|
||||
Vars, StepExpr);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
|
|
@ -1382,6 +1382,19 @@ public:
|
|||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'linear' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation ColonLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPLinearClause(VarList, Step, StartLoc, LParenLoc,
|
||||
ColonLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'copyin' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -6434,6 +6447,25 @@ TreeTransform<Derived>::TransformOMPSharedClause(OMPSharedClause *C) {
|
|||
C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPLinearClause(OMPLinearClause *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.take());
|
||||
}
|
||||
ExprResult Step = getDerived().TransformExpr(C->getStep());
|
||||
if (Step.isInvalid())
|
||||
return 0;
|
||||
return getDerived().RebuildOMPLinearClause(
|
||||
Vars, Step.take(), C->getLocStart(), C->getLParenLoc(), C->getColonLoc(),
|
||||
C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPCopyinClause(OMPCopyinClause *C) {
|
||||
|
|
|
@ -1692,6 +1692,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case OMPC_shared:
|
||||
C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
case OMPC_linear:
|
||||
C = OMPLinearClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
case OMPC_copyin:
|
||||
C = OMPCopyinClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
|
@ -1755,6 +1758,18 @@ void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
C->setVarRefs(Vars);
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setColonLoc(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);
|
||||
C->setStep(Reader->Reader.ReadSubExpr());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
unsigned NumVars = C->varlist_size();
|
||||
|
|
|
@ -1716,6 +1716,15 @@ void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
|
|||
Writer->Writer.AddStmt(VE);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getColonLoc(), Record);
|
||||
for (auto *VE : C->varlists())
|
||||
Writer->Writer.AddStmt(VE);
|
||||
Writer->Writer.AddStmt(C->getStep());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
|
|
|
@ -14,8 +14,8 @@ template<class T, class N> T reduct(T* arr, N num) {
|
|||
N myind;
|
||||
T sum = (T)0;
|
||||
// CHECK: T sum = (T)0;
|
||||
#pragma omp simd private(myind, g_ind)
|
||||
// CHECK-NEXT: #pragma omp simd private(myind,g_ind)
|
||||
#pragma omp simd private(myind, g_ind), linear(ind)
|
||||
// CHECK-NEXT: #pragma omp simd private(myind,g_ind) linear(ind)
|
||||
for (i = 0; i < num; ++i) {
|
||||
myind = ind;
|
||||
T cur = arr[myind];
|
||||
|
@ -31,13 +31,16 @@ template<class T> struct S {
|
|||
T result(T *v) const {
|
||||
T res;
|
||||
T val;
|
||||
T lin = 0;
|
||||
// CHECK: T res;
|
||||
// CHECK: T val;
|
||||
#pragma omp simd private(val) safelen(7)
|
||||
// CHECK-NEXT: #pragma omp simd private(val) safelen(7)
|
||||
// CHECK: T lin = 0;
|
||||
#pragma omp simd private(val) safelen(7) linear(lin : -5)
|
||||
// CHECK-NEXT: #pragma omp simd private(val) safelen(7) linear(lin: -5)
|
||||
for (T i = 7; i < m_a; ++i) {
|
||||
val = v[i-7] + m_a;
|
||||
res = val;
|
||||
lin -= 5;
|
||||
}
|
||||
const T clen = 3;
|
||||
// CHECK: T clen = 3;
|
||||
|
@ -58,9 +61,14 @@ template<class T> struct S {
|
|||
|
||||
template<int LEN> struct S2 {
|
||||
static void func(int n, float *a, float *b, float *c) {
|
||||
#pragma omp simd safelen(LEN)
|
||||
int k1 = 0, k2 = 0;
|
||||
#pragma omp simd safelen(LEN) linear(k1,k2:LEN)
|
||||
for(int i = 0; i < n; i++) {
|
||||
c[i] = a[i] + b[i];
|
||||
c[k1] = a[k1] + b[k1];
|
||||
c[k2] = a[k2] + b[k2];
|
||||
k1 = k1 + LEN;
|
||||
k2 = k2 + LEN;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -68,9 +76,14 @@ template<int LEN> struct S2 {
|
|||
// S2<4>::func is called below in main.
|
||||
// CHECK: template <int LEN = 4> struct S2 {
|
||||
// CHECK-NEXT: static void func(int n, float *a, float *b, float *c) {
|
||||
// CHECK-NEXT: #pragma omp simd safelen(4)
|
||||
// CHECK-NEXT: int k1 = 0, k2 = 0;
|
||||
// CHECK-NEXT: #pragma omp simd safelen(4) linear(k1,k2: 4)
|
||||
// CHECK-NEXT: for (int i = 0; i < n; i++) {
|
||||
// CHECK-NEXT: c[i] = a[i] + b[i];
|
||||
// CHECK-NEXT: c[k1] = a[k1] + b[k1];
|
||||
// CHECK-NEXT: c[k2] = a[k2] + b[k2];
|
||||
// CHECK-NEXT: k1 = k1 + 4;
|
||||
// CHECK-NEXT: k2 = k2 + 4;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
@ -99,8 +112,8 @@ int main (int argc, char **argv) {
|
|||
// CHECK-NEXT: foo();
|
||||
const int CLEN = 4;
|
||||
// CHECK-NEXT: const int CLEN = 4;
|
||||
#pragma omp simd safelen(CLEN)
|
||||
// CHECK-NEXT: #pragma omp simd safelen(CLEN)
|
||||
#pragma omp simd linear(a:CLEN) safelen(CLEN)
|
||||
// CHECK-NEXT: #pragma omp simd linear(a: CLEN) safelen(CLEN)
|
||||
for (int i = 0; i < 10; ++i)foo();
|
||||
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
|
||||
// CHECK-NEXT: foo();
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
// RUN: %clang_cc1 -verify -fopenmp=libiomp5 %s
|
||||
|
||||
namespace X {
|
||||
int x;
|
||||
};
|
||||
|
||||
struct B {
|
||||
static int ib; // expected-note {{'B::ib' declared here}}
|
||||
static int bfoo() { return 8; }
|
||||
};
|
||||
|
||||
int bfoo() { return 4; }
|
||||
|
||||
int z;
|
||||
const int C1 = 1;
|
||||
const int C2 = 2;
|
||||
void test_linear_colons()
|
||||
{
|
||||
int B = 0;
|
||||
#pragma omp simd linear(B:bfoo())
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'}}
|
||||
#pragma omp simd linear(B::ib:B:bfoo())
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
// expected-error@+1 {{use of undeclared identifier 'ib'; did you mean 'B::ib'}}
|
||||
#pragma omp simd linear(B:ib)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
// expected-error@+1 {{unexpected ':' in nested name specifier; did you mean '::'?}}
|
||||
#pragma omp simd linear(z:B:ib)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
#pragma omp simd linear(B:B::bfoo())
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
#pragma omp simd linear(X::x : ::z)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
#pragma omp simd linear(B,::z, X::x)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
#pragma omp simd linear(::z)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
// expected-error@+1 {{expected variable name}}
|
||||
#pragma omp simd linear(B::bfoo())
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
#pragma omp simd linear(B::ib,B:C1+C2)
|
||||
for (int i = 0; i < 10; ++i) ;
|
||||
}
|
||||
|
||||
template<int L, class T, class N> T test_template(T* arr, N num) {
|
||||
N i;
|
||||
T sum = (T)0;
|
||||
T ind2 = - num * L; // expected-note {{'ind2' defined here}}
|
||||
// expected-error@+1 {{argument of a linear clause should be of integral or pointer type}}
|
||||
#pragma omp simd linear(ind2:L)
|
||||
for (i = 0; i < num; ++i) {
|
||||
T cur = arr[ind2];
|
||||
ind2 += L;
|
||||
sum += cur;
|
||||
}
|
||||
}
|
||||
|
||||
template<int LEN> int test_warn() {
|
||||
int ind2 = 0;
|
||||
// expected-warning@+1 {{zero linear step (ind2 should probably be const)}}
|
||||
#pragma omp simd linear(ind2:LEN)
|
||||
for (int i = 0; i < 100; i++) {
|
||||
ind2 += LEN;
|
||||
}
|
||||
return ind2;
|
||||
}
|
||||
|
||||
struct S1; // expected-note 2 {{declared here}} expected-note 2 {{forward declaration of 'S1'}}
|
||||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
public:
|
||||
S2():a(0) { }
|
||||
};
|
||||
const S2 b; // expected-note 2 {{'b' defined here}}
|
||||
const S2 ba[5];
|
||||
class S3 {
|
||||
int a;
|
||||
public:
|
||||
S3():a(0) { }
|
||||
};
|
||||
const S3 ca[5];
|
||||
class S4 {
|
||||
int a;
|
||||
S4();
|
||||
public:
|
||||
S4(int v):a(v) { }
|
||||
};
|
||||
class S5 {
|
||||
int a;
|
||||
S5():a(0) {}
|
||||
public:
|
||||
S5(int v):a(v) { }
|
||||
};
|
||||
|
||||
S3 h;
|
||||
#pragma omp threadprivate(h) // expected-note 2 {{defined as threadprivate or thread local}}
|
||||
|
||||
template<class I, class C> int foomain(I argc, C **argv) {
|
||||
I e(4);
|
||||
I g(5);
|
||||
int i;
|
||||
int &j = i; // expected-note {{'j' defined here}}
|
||||
#pragma omp simd linear // expected-error {{expected '(' after 'linear'}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear () // expected-error {{expected expression}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc : 5)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
|
||||
// expected-error@+1 {{const-qualified variable cannot be linear}}
|
||||
#pragma omp simd linear (a, b:B::ib)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(e, g)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(i)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp parallel
|
||||
{
|
||||
int v = 0;
|
||||
int i;
|
||||
#pragma omp simd linear(v:i)
|
||||
for (int k = 0; k < argc; ++k) { i = k; v += i; }
|
||||
}
|
||||
#pragma omp simd linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
int v = 0;
|
||||
#pragma omp simd linear(v:j)
|
||||
for (int k = 0; k < argc; ++k) { ++k; v += j; }
|
||||
#pragma omp simd linear(i)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
double darr[100];
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'test_template<-4, double, int>' requested here}}
|
||||
test_template<-4>(darr, 4);
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'test_warn<0>' requested here}}
|
||||
test_warn<0>();
|
||||
|
||||
S4 e(4); // expected-note {{'e' defined here}}
|
||||
S5 g(5); // expected-note {{'g' defined here}}
|
||||
int i;
|
||||
int &j = i; // expected-note {{'j' defined here}}
|
||||
#pragma omp simd linear // expected-error {{expected '(' after 'linear'}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear () // expected-error {{expected expression}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argc)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
// expected-error@+2 {{linear variable with incomplete type 'S1'}}
|
||||
// expected-error@+1 {{const-qualified variable cannot be linear}}
|
||||
#pragma omp simd linear (a, b)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear (argv[1]) // expected-error {{expected variable name}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
// expected-error@+2 {{argument of a linear clause should be of integral or pointer type, not 'S4'}}
|
||||
// expected-error@+1 {{argument of a linear clause should be of integral or pointer type, not 'S5'}}
|
||||
#pragma omp simd linear(e, g)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(h) // expected-error {{threadprivate or thread local variable cannot be linear}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp parallel
|
||||
{
|
||||
int i;
|
||||
#pragma omp simd linear(i)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(i : 4)
|
||||
for (int k = 0; k < argc; ++k) { ++k; i += 4; }
|
||||
}
|
||||
#pragma omp simd linear(j) // expected-error {{arguments of OpenMP clause 'linear' cannot be of reference type 'int &'}}
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
#pragma omp simd linear(i)
|
||||
for (int k = 0; k < argc; ++k) ++k;
|
||||
|
||||
foomain<int,char>(argc,argv);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -146,6 +146,80 @@ void test_safelen()
|
|||
for (i = 0; i < 16; ++i);
|
||||
}
|
||||
|
||||
void test_linear()
|
||||
{
|
||||
int i;
|
||||
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp simd linear(
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+2 {{expected expression}}
|
||||
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp simd linear(,
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+2 {{expected expression}}
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp simd linear(,)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp simd linear()
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp simd linear(int)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected variable name}}
|
||||
#pragma omp simd linear(0)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{use of undeclared identifier 'x'}}
|
||||
#pragma omp simd linear(x)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+2 {{use of undeclared identifier 'x'}}
|
||||
// expected-error@+1 {{use of undeclared identifier 'y'}}
|
||||
#pragma omp simd linear(x, y)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+3 {{use of undeclared identifier 'x'}}
|
||||
// expected-error@+2 {{use of undeclared identifier 'y'}}
|
||||
// expected-error@+1 {{use of undeclared identifier 'z'}}
|
||||
#pragma omp simd linear(x, y, z)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
|
||||
int x, y;
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp simd linear(x:)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected expression}} expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp simd linear(x:,)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
#pragma omp simd linear(x:1)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
#pragma omp simd linear(x:2*2)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp simd linear(x:1,y)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp simd linear(x:1,y,z:1)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
|
||||
// expected-note@+2 {{defined as linear}}
|
||||
// expected-error@+1 {{linear variable cannot be linear}}
|
||||
#pragma omp simd linear(x) linear(x)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
|
||||
// expected-note@+2 {{defined as private}}
|
||||
// expected-error@+1 {{private variable cannot be linear}}
|
||||
#pragma omp simd private(x) linear(x)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
|
||||
// expected-note@+2 {{defined as linear}}
|
||||
// expected-error@+1 {{linear variable cannot be private}}
|
||||
#pragma omp simd linear(x) private(x)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
|
||||
// expected-warning@+1 {{zero linear step (x and other variables in clause should probably be const)}}
|
||||
#pragma omp simd linear(x,y:0)
|
||||
for (i = 0; i < 16; ++i) ;
|
||||
}
|
||||
|
||||
void test_private()
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -1954,6 +1954,10 @@ void OMPClauseEnqueue::VisitOMPFirstprivateClause(
|
|||
void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPLinearClause(const OMPLinearClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
Visitor->AddStmt(C->getStep());
|
||||
}
|
||||
void OMPClauseEnqueue::VisitOMPCopyinClause(const OMPCopyinClause *C) {
|
||||
VisitOMPClauseList(C);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue