[OPENMP 4.5] Parsing/sema for 'hint' clause of 'critical' directive.

OpenMP 4.5 adds 'hint' clause to critical directive. Patch adds parsing/semantic analysis for this clause.

llvm-svn: 255625
This commit is contained in:
Alexey Bataev 2015-12-15 08:19:24 +00:00
parent cc03b49444
commit 28c75417b2
19 changed files with 369 additions and 37 deletions

View File

@ -3028,6 +3028,59 @@ public:
child_range children() { return child_range(&NumTasks, &NumTasks + 1); }
};
/// \brief This represents 'hint' clause in the '#pragma omp ...' directive.
///
/// \code
/// #pragma omp critical (name) hint(6)
/// \endcode
/// In this example directive '#pragma omp critical' has name 'name' and clause
/// 'hint' with argument '6'.
///
class OMPHintClause : public OMPClause {
friend class OMPClauseReader;
/// \brief Location of '('.
SourceLocation LParenLoc;
/// \brief Hint expression of the 'hint' clause.
Stmt *Hint;
/// \brief Set hint expression.
///
void setHint(Expr *H) { Hint = H; }
public:
/// \brief Build 'hint' clause with expression \a Hint.
///
/// \param Hint Hint expression.
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
///
OMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc),
Hint(Hint) {}
/// \brief Build an empty clause.
///
OMPHintClause()
: OMPClause(OMPC_hint, SourceLocation(), SourceLocation()),
LParenLoc(SourceLocation()), Hint(nullptr) {}
/// \brief Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
/// \brief Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }
/// \brief Returns number of threads.
Expr *getHint() const { return cast_or_null<Expr>(Hint); }
static bool classof(const OMPClause *T) {
return T->getClauseKind() == OMPC_hint;
}
child_range children() { return child_range(&Hint, &Hint + 1); }
};
} // end namespace clang
#endif // LLVM_CLANG_AST_OPENMPCLAUSE_H

View File

@ -2772,6 +2772,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNumTasksClause(
return true;
}
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPHintClause(OMPHintClause *C) {
TRY_TO(TraverseStmt(C->getHint()));
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

View File

@ -1153,18 +1153,22 @@ class OMPCriticalDirective : public OMPExecutableDirective {
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
/// \param NumClauses Number of clauses.
///
OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
SourceLocation EndLoc)
SourceLocation EndLoc, unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
StartLoc, EndLoc, 0, 1),
StartLoc, EndLoc, NumClauses, 1),
DirName(Name) {}
/// \brief Build an empty directive.
///
explicit OMPCriticalDirective()
/// \param NumClauses Number of clauses.
///
explicit OMPCriticalDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPCriticalDirectiveClass, OMPD_critical,
SourceLocation(), SourceLocation(), 0, 1),
SourceLocation(), SourceLocation(), NumClauses,
1),
DirName() {}
/// \brief Set name of the directive.
@ -1180,17 +1184,21 @@ public:
/// \param Name Name of the directive.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
/// \param AssociatedStmt Statement, associated with the directive.
///
static OMPCriticalDirective *
Create(const ASTContext &C, const DeclarationNameInfo &Name,
SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt);
SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
/// \brief Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPCriticalDirective *CreateEmpty(const ASTContext &C, EmptyShell);
static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
/// \brief Return name of the directive.
///

View File

@ -7932,6 +7932,14 @@ def err_omp_grainsize_num_tasks_mutually_exclusive : Error<
"'%0' and '%1' clause are mutually exclusive and may not appear on the same directive">;
def note_omp_previous_grainsize_num_tasks : Note<
"'%0' clause is specified here">;
def err_omp_hint_clause_no_name : Error<
"the name of the construct must be specified in presence of 'hint' clause">;
def err_omp_critical_with_hint : Error<
"constructs with the same name must have a 'hint' clause with the same value">;
def note_omp_critical_hint_here : Note<
"%select{|previous }0'hint' clause with value '%1'">;
def note_omp_critical_no_hint : Note<
"%select{|previous }0directive with no 'hint' clause specified">;
def err_omp_firstprivate_distribute_private_teams : Error<
"private variable in '#pragma omp teams' cannot be firstprivate in '#pragma omp distribute'">;
def err_omp_firstprivate_and_lastprivate_in_distribute : Error<

View File

@ -75,6 +75,9 @@
#ifndef OPENMP_TASKLOOP_SIMD_CLAUSE
# define OPENMP_TASKLOOP_SIMD_CLAUSE(Name)
#endif
#ifndef OPENMP_CRITICAL_CLAUSE
# define OPENMP_CRITICAL_CLAUSE(Name)
#endif
#ifndef OPENMP_DISTRIBUTE_CLAUSE
#define OPENMP_DISTRIBUTE_CLAUSE(Name)
#endif
@ -168,6 +171,7 @@ OPENMP_CLAUSE(priority, OMPPriorityClause)
OPENMP_CLAUSE(grainsize, OMPGrainsizeClause)
OPENMP_CLAUSE(nogroup, OMPNogroupClause)
OPENMP_CLAUSE(num_tasks, OMPNumTasksClause)
OPENMP_CLAUSE(hint, OMPHintClause)
// Clauses allowed for OpenMP directive 'parallel'.
OPENMP_PARALLEL_CLAUSE(if)
@ -393,6 +397,9 @@ OPENMP_TASKLOOP_SIMD_CLAUSE(grainsize)
OPENMP_TASKLOOP_SIMD_CLAUSE(nogroup)
OPENMP_TASKLOOP_SIMD_CLAUSE(num_tasks)
// Clauses allowed for OpenMP directive 'critical'.
OPENMP_CRITICAL_CLAUSE(hint)
// Clauses allowed for OpenMP directive 'distribute'
OPENMP_DISTRIBUTE_CLAUSE(private)
OPENMP_DISTRIBUTE_CLAUSE(firstprivate)
@ -409,6 +416,7 @@ OPENMP_DISTRIBUTE_CLAUSE(collapse)
#undef OPENMP_DIRECTIVE
#undef OPENMP_DIRECTIVE_EXT
#undef OPENMP_CLAUSE
#undef OPENMP_CRITICAL_CLAUSE
#undef OPENMP_ORDERED_CLAUSE
#undef OPENMP_CANCEL_CLAUSE
#undef OPENMP_SINGLE_CLAUSE

View File

@ -7875,6 +7875,7 @@ public:
/// \brief Called on well-formed '\#pragma omp critical' after parsing of the
/// associated statement.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed '\#pragma omp parallel for' after parsing
@ -8018,6 +8019,10 @@ public:
OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// \brief Called on well-formed 'hint' clause.
OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
unsigned Argument,

View File

@ -312,22 +312,27 @@ OMPMasterDirective *OMPMasterDirective::CreateEmpty(const ASTContext &C,
OMPCriticalDirective *OMPCriticalDirective::Create(
const ASTContext &C, const DeclarationNameInfo &Name,
SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt) {
SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
llvm::alignOf<Stmt *>());
void *Mem = C.Allocate(Size + sizeof(Stmt *));
llvm::alignOf<OMPClause *>());
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *));
OMPCriticalDirective *Dir =
new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc);
new (Mem) OMPCriticalDirective(Name, StartLoc, EndLoc, Clauses.size());
Dir->setClauses(Clauses);
Dir->setAssociatedStmt(AssociatedStmt);
return Dir;
}
OMPCriticalDirective *OMPCriticalDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPCriticalDirective),
llvm::alignOf<Stmt *>());
void *Mem = C.Allocate(Size + sizeof(Stmt *));
return new (Mem) OMPCriticalDirective();
llvm::alignOf<OMPClause *>());
void *Mem =
C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *));
return new (Mem) OMPCriticalDirective(NumClauses);
}
OMPParallelForDirective *OMPParallelForDirective::Create(

View File

@ -743,6 +743,12 @@ void OMPClausePrinter::VisitOMPNumTasksClause(OMPNumTasksClause *Node) {
OS << ")";
}
void OMPClausePrinter::VisitOMPHintClause(OMPHintClause *Node) {
OS << "hint(";
Node->getHint()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}
template<typename T>
void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
for (typename T::varlist_iterator I = Node->varlist_begin(),
@ -964,6 +970,7 @@ void StmtPrinter::VisitOMPCriticalDirective(OMPCriticalDirective *Node) {
Node->getDirectiveName().printName(OS);
OS << ")";
}
OS << " ";
PrintOMPExecutableDirective(Node);
}

View File

@ -472,6 +472,9 @@ void OMPClauseProfiler::VisitOMPGrainsizeClause(const OMPGrainsizeClause *C) {
void OMPClauseProfiler::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
Profiler->VisitStmt(C->getNumTasks());
}
void OMPClauseProfiler::VisitOMPHintClause(const OMPHintClause *C) {
Profiler->VisitStmt(C->getHint());
}
}
void

View File

@ -141,6 +141,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@ -245,6 +246,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
break;
}
llvm_unreachable("Invalid OpenMP simple clause kind");
@ -433,6 +435,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
#define OPENMP_TASKLOOP_SIMD_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
default:
break;
}
break;
case OMPD_critical:
switch (CKind) {
#define OPENMP_CRITICAL_CLAUSE(Name) \
case OMPC_##Name: \
return true;
#include "clang/Basic/OpenMPKinds.def"
default:
break;
@ -452,7 +464,6 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_threadprivate:
case OMPD_section:
case OMPD_master:
case OMPD_critical:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:

View File

@ -2489,6 +2489,7 @@ static void EmitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}

View File

@ -404,7 +404,7 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
/// update-clause | capture-clause | seq_cst-clause | device-clause |
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
/// thread_limit-clause | priority-clause | grainsize-clause |
/// nogroup-clause | num_tasks-clause
/// nogroup-clause | num_tasks-clause | hint-clause
///
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind CKind, bool FirstClause) {
@ -430,6 +430,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_priority:
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_hint:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@ -541,7 +542,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// \brief Parsing of OpenMP clauses with single expressions like 'final',
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
/// 'thread_limit', 'simdlen', 'priority', 'grainsize' or 'num_tasks'.
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
///
/// final-clause:
/// 'final' '(' expression ')'
@ -567,6 +568,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
/// num_tasks-clause:
/// 'num_tasks' '(' expression ')'
///
/// hint-clause:
/// 'hint' '(' expression ')'
///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
SourceLocation Loc = ConsumeToken();

View File

@ -91,6 +91,8 @@ private:
typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy;
typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy;
typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
CriticalsWithHintsTy;
struct SharingMapTy {
DeclSAMapTy SharingMap;
@ -133,6 +135,7 @@ private:
OpenMPClauseKind ClauseKindMode;
Sema &SemaRef;
bool ForceCapturing;
CriticalsWithHintsTy Criticals;
typedef SmallVector<SharingMapTy, 8>::reverse_iterator reverse_iterator;
@ -163,6 +166,16 @@ public:
Stack.pop_back();
}
void addCriticalWithHint(OMPCriticalDirective *D, llvm::APSInt Hint) {
Criticals[D->getDirectiveName().getAsString()] = std::make_pair(D, Hint);
}
const std::pair<OMPCriticalDirective *, llvm::APSInt>
getCriticalWithHint(const DeclarationNameInfo &Name) const {
auto I = Criticals.find(Name.getAsString());
if (I != Criticals.end())
return I->second;
return std::make_pair(nullptr, llvm::APSInt());
}
/// \brief If 'aligned' declaration for given variable \a D was not seen yet,
/// add it and return NULL; otherwise return previous occurrence's expression
/// for diagnostics.
@ -2521,9 +2534,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
break;
case OMPD_critical:
assert(ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp critical' directive");
Res = ActOnOpenMPCriticalDirective(DirName, AStmt, StartLoc, EndLoc);
Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
StartLoc, EndLoc);
break;
case OMPD_parallel_for:
Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
@ -4301,19 +4313,62 @@ StmtResult Sema::ActOnOpenMPMasterDirective(Stmt *AStmt,
return OMPMasterDirective::Create(Context, StartLoc, EndLoc, AStmt);
}
StmtResult
Sema::ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc) {
StmtResult Sema::ActOnOpenMPCriticalDirective(
const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
if (!AStmt)
return StmtError();
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
bool ErrorFound = false;
llvm::APSInt Hint;
SourceLocation HintLoc;
bool DependentHint = false;
for (auto *C : Clauses) {
if (C->getClauseKind() == OMPC_hint) {
if (!DirName.getName()) {
Diag(C->getLocStart(), diag::err_omp_hint_clause_no_name);
ErrorFound = true;
}
Expr *E = cast<OMPHintClause>(C)->getHint();
if (E->isTypeDependent() || E->isValueDependent() ||
E->isInstantiationDependent())
DependentHint = true;
else {
Hint = E->EvaluateKnownConstInt(Context);
HintLoc = C->getLocStart();
}
}
}
if (ErrorFound)
return StmtError();
auto Pair = DSAStack->getCriticalWithHint(DirName);
if (Pair.first && DirName.getName() && !DependentHint) {
if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
Diag(StartLoc, diag::err_omp_critical_with_hint);
if (HintLoc.isValid()) {
Diag(HintLoc, diag::note_omp_critical_hint_here)
<< 0 << Hint.toString(/*Radix=*/10, /*Signed=*/false);
} else
Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
if (auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
Diag(C->getLocStart(), diag::note_omp_critical_hint_here)
<< 1
<< C->getHint()->EvaluateKnownConstInt(Context).toString(
/*Radix=*/10, /*Signed=*/false);
} else
Diag(Pair.first->getLocStart(), diag::note_omp_critical_no_hint) << 1;
}
}
getCurFunction()->setHasBranchProtectedScope();
return OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
AStmt);
auto *Dir = OMPCriticalDirective::Create(Context, DirName, StartLoc, EndLoc,
Clauses, AStmt);
if (!Pair.first && DirName.getName() && !DependentHint)
DSAStack->addCriticalWithHint(Dir, Hint);
return Dir;
}
StmtResult Sema::ActOnOpenMPParallelForDirective(
@ -5507,6 +5562,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_num_tasks:
Res = ActOnOpenMPNumTasksClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_hint:
Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_if:
case OMPC_default:
case OMPC_proc_bind:
@ -5814,6 +5872,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -5950,6 +6009,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -6090,6 +6150,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_priority:
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -6230,6 +6291,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_grainsize:
case OMPC_nogroup:
case OMPC_num_tasks:
case OMPC_hint:
case OMPC_unknown:
llvm_unreachable("Clause is not allowed.");
}
@ -8228,3 +8290,16 @@ OMPClause *Sema::ActOnOpenMPNumTasksClause(Expr *NumTasks,
return new (Context) OMPNumTasksClause(ValExpr, StartLoc, LParenLoc, EndLoc);
}
OMPClause *Sema::ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
// OpenMP [2.13.2, critical construct, Description]
// ... where hint-expression is an integer constant expression that evaluates
// to a valid lock hint.
ExprResult HintExpr = VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint);
if (HintExpr.isInvalid())
return nullptr;
return new (Context)
OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
}

View File

@ -1722,6 +1722,16 @@ public:
EndLoc);
}
/// \brief Build a new OpenMP 'hint' clause.
///
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
OMPClause *RebuildOMPHintClause(Expr *Hint, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc) {
return getSema().ActOnOpenMPHintClause(Hint, StartLoc, LParenLoc, EndLoc);
}
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@ -7843,6 +7853,15 @@ TreeTransform<Derived>::TransformOMPNumTasksClause(OMPNumTasksClause *C) {
E.get(), C->getLocStart(), C->getLParenLoc(), C->getLocEnd());
}
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPHintClause(OMPHintClause *C) {
ExprResult E = getDerived().TransformExpr(C->getHint());
if (E.isInvalid())
return nullptr;
return getDerived().RebuildOMPHintClause(E.get(), C->getLocStart(),
C->getLParenLoc(), C->getLocEnd());
}
//===----------------------------------------------------------------------===//
// Expression transformation
//===----------------------------------------------------------------------===//

View File

@ -1868,6 +1868,9 @@ OMPClause *OMPClauseReader::readClause() {
case OMPC_num_tasks:
C = new (Context) OMPNumTasksClause();
break;
case OMPC_hint:
C = new (Context) OMPHintClause();
break;
}
Visit(C);
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
@ -2219,6 +2222,11 @@ void OMPClauseReader::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
void OMPClauseReader::VisitOMPHintClause(OMPHintClause *C) {
C->setHint(Reader->Reader.ReadSubExpr());
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@ -2328,6 +2336,8 @@ void ASTStmtReader::VisitOMPMasterDirective(OMPMasterDirective *D) {
void ASTStmtReader::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
++Idx;
VisitOMPExecutableDirective(D);
ReadDeclarationNameInfo(D->DirName, Record, Idx);
}
@ -2991,7 +3001,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_CRITICAL_DIRECTIVE:
S = OMPCriticalDirective::CreateEmpty(Context, Empty);
S = OMPCriticalDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_PARALLEL_FOR_DIRECTIVE: {

View File

@ -2028,6 +2028,11 @@ void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
Writer->Writer.AddStmt(C->getHint());
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
}
//===----------------------------------------------------------------------===//
// OpenMP Directives.
//===----------------------------------------------------------------------===//
@ -2134,6 +2139,7 @@ void ASTStmtWriter::VisitOMPMasterDirective(OMPMasterDirective *D) {
void ASTStmtWriter::VisitOMPCriticalDirective(OMPCriticalDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Writer.AddDeclarationNameInfo(D->getDirectiveName(), Record);
Code = serialization::STMT_OMP_CRITICAL_DIRECTIVE;

View File

@ -8,6 +8,26 @@
void foo() {}
// CHECK: template <typename T, int N> int tmain(T argc, char **argv)
template <typename T, int N>
int tmain (T argc, char **argv) {
T b = argc, c, d, e, f, g;
static int a;
// CHECK: static int a;
#pragma omp critical
a=2;
// CHECK-NEXT: #pragma omp critical
// CHECK-NEXT: a = 2;
// CHECK-NEXT: ++a;
++a;
#pragma omp critical (the_name) hint(N)
foo();
// CHECK-NEXT: #pragma omp critical (the_name) hint(N)
// CHECK-NEXT: foo();
// CHECK-NEXT: return N;
return N;
}
int main (int argc, char **argv) {
int b = argc, c, d, e, f, g;
static int a;
@ -18,12 +38,12 @@ int main (int argc, char **argv) {
// CHECK-NEXT: a = 2;
// CHECK-NEXT: ++a;
++a;
#pragma omp critical (the_name)
#pragma omp critical (the_name1) hint(23)
foo();
// CHECK-NEXT: #pragma omp critical (the_name)
// CHECK-NEXT: #pragma omp critical (the_name1) hint(23)
// CHECK-NEXT: foo();
// CHECK-NEXT: return 0;
return 0;
// CHECK-NEXT: return tmain<int, 4>(a, argv);
return tmain<int, 4>(a, argv);
}
#endif

View File

@ -2,20 +2,21 @@
int foo();
int main() {
template<typename T, int N>
int tmain(int argc, char **argv) { // expected-note {{declared here}}
#pragma omp critical
;
#pragma omp critical untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp critical'}}
#pragma omp critical unknown // expected-warning {{extra tokens at the end of '#pragma omp critical' are ignored}}
#pragma omp critical ( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical ( + // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical (name // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical (name2 // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical (name1)
foo();
{
#pragma omp critical
} // expected-error {{expected statement}}
#pragma omp critical (name) // expected-note {{previous 'critical' region starts here}}
#pragma omp critical (name2) // expected-note {{previous 'critical' region starts here}}
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
@ -23,11 +24,11 @@ int main() {
#pragma omp for
for (int j = 0; j < 10; j++) {
foo();
#pragma omp critical(name) // expected-error {{cannot nest 'critical' regions having the same name 'name'}}
#pragma omp critical(name2) // expected-error {{cannot nest 'critical' regions having the same name 'name2'}}
foo();
}
}
#pragma omp critical (name)
#pragma omp critical (name2)
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
@ -38,7 +39,7 @@ int main() {
foo();
}
}
#pragma omp critical (name)
#pragma omp critical (name2)
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
@ -50,9 +51,86 @@ int main() {
}
}
#pragma omp critical (name2) hint // expected-error {{expected '(' after 'hint'}}
foo();
#pragma omp critical (name2) hint( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
foo();
#pragma omp critical (name2) hint(+ // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
foo();
#pragma omp critical (name2) hint(argc) // expected-error {{expression is not an integral constant expression}} expected-note {{read of non-const variable 'argc' is not allowed in a constant expression}}
foo();
#pragma omp critical (name) hint(N) // expected-error {{argument to 'hint' clause must be a strictly positive integer value}} expected-error {{constructs with the same name must have a 'hint' clause with the same value}} expected-note {{'hint' clause with value '4'}}
foo();
#pragma omp critical hint(N) // expected-error {{the name of the construct must be specified in presence of 'hint' clause}}
foo();
return 0;
}
int main(int argc, char **argv) { // expected-note {{declared here}}
#pragma omp critical
;
#pragma omp critical untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp critical'}}
#pragma omp critical unknown // expected-warning {{extra tokens at the end of '#pragma omp critical' are ignored}}
#pragma omp critical ( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical ( + // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical (name2 // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp critical (name1)
foo();
{
#pragma omp critical
} // expected-error {{expected statement}}
#pragma omp critical (name2) // expected-note {{previous 'critical' region starts here}}
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp parallel
#pragma omp for
for (int j = 0; j < 10; j++) {
foo();
#pragma omp critical(name2) // expected-error {{cannot nest 'critical' regions having the same name 'name2'}}
foo();
}
}
#pragma omp critical (name2)
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp parallel
#pragma omp for
for (int j = 0; j < 10; j++) {
#pragma omp critical
foo();
}
}
#pragma omp critical (name2)
#pragma omp critical
for (int i = 0; i < 10; ++i) {
foo();
#pragma omp parallel
#pragma omp for
for (int j = 0; j < 10; j++) {
#pragma omp critical (nam)
foo();
}
}
#pragma omp critical (name2) hint // expected-error {{expected '(' after 'hint'}}
foo();
#pragma omp critical (name2) hint( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
foo();
#pragma omp critical (name2) hint(+ // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
foo();
#pragma omp critical (name2) hint(argc) // expected-error {{expression is not an integral constant expression}} expected-note {{read of non-const variable 'argc' is not allowed in a constant expression}}
foo();
#pragma omp critical (name) hint(23) // expected-note {{previous 'hint' clause with value '23'}}
foo();
#pragma omp critical hint(-5) // expected-error {{argument to 'hint' clause must be a strictly positive integer value}}
foo();
#pragma omp critical hint(1) // expected-error {{the name of the construct must be specified in presence of 'hint' clause}}
foo();
return tmain<int, 4>(argc, argv) + tmain<float, -5>(argc, argv); // expected-note {{in instantiation of function template specialization 'tmain<float, -5>' requested here}} expected-note {{in instantiation of function template specialization 'tmain<int, 4>' requested here}}
}
int foo() {
L1:
foo();
@ -69,4 +147,4 @@ int foo() {
}
return 0;
}
}

View File

@ -2100,6 +2100,10 @@ void OMPClauseEnqueue::VisitOMPNumTasksClause(const OMPNumTasksClause *C) {
Visitor->AddStmt(C->getNumTasks());
}
void OMPClauseEnqueue::VisitOMPHintClause(const OMPHintClause *C) {
Visitor->AddStmt(C->getHint());
}
template<typename T>
void OMPClauseEnqueue::VisitOMPClauseList(T *Node) {
for (const auto *I : Node->varlists()) {