mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 16:31:02 +00:00
[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:
parent
cc03b49444
commit
28c75417b2
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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<
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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'.");
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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: {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user