mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 13:35:38 +08:00
OpenMP: basic support for #pragma omp parallel
llvm-svn: 186647
This commit is contained in:
@@ -2062,7 +2062,11 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_DeclStmt = 231,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_DeclStmt,
|
||||
/** \brief OpenMP parallel directive.
|
||||
*/
|
||||
CXCursor_OMPParallelDirective = 232,
|
||||
|
||||
CXCursor_LastStmt = CXCursor_OMPParallelDirective,
|
||||
|
||||
/**
|
||||
* \brief Cursor that represents the translation unit itself.
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
@@ -417,6 +418,10 @@ private:
|
||||
bool TraverseDeclContextHelper(DeclContext *DC);
|
||||
bool TraverseFunctionHelper(FunctionDecl *D);
|
||||
bool TraverseVarHelper(VarDecl *D);
|
||||
bool TraverseOMPClause(OMPClause *C);
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
bool Visit##Class(Class *C);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
struct EnqueueJob {
|
||||
Stmt *S;
|
||||
@@ -2298,6 +2303,48 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
|
||||
// Traverse OpenCL: AsType, Convert.
|
||||
DEF_TRAVERSE_STMT(AsTypeExpr, { })
|
||||
|
||||
// OpenMP directives.
|
||||
DEF_TRAVERSE_STMT(OMPParallelDirective, {
|
||||
ArrayRef<OMPClause *> Clauses = S->clauses();
|
||||
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
|
||||
I != E; ++I)
|
||||
if (!TraverseOMPClause(*I)) return false;
|
||||
})
|
||||
|
||||
// OpenMP clauses.
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
if (!C) return true;
|
||||
switch (C->getClauseKind()) {
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
case OMPC_##Name: \
|
||||
return getDerived().Visit##Class(static_cast<Class*>(C));
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define PROCESS_OMP_CLAUSE_LIST(Class, Node) \
|
||||
for (OMPVarList<Class>::varlist_iterator I = Node->varlist_begin(), \
|
||||
E = Node->varlist_end(); \
|
||||
I != E; ++I) \
|
||||
TraverseStmt(*I);
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(
|
||||
OMPPrivateClause *C) {
|
||||
PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, C)
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef PROCESS_OMP_CLAUSE_LIST
|
||||
|
||||
// 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
|
||||
|
||||
410
clang/include/clang/AST/StmtOpenMP.h
Normal file
410
clang/include/clang/AST/StmtOpenMP.h
Normal file
@@ -0,0 +1,410 @@
|
||||
//===- StmtOpenMP.h - Classes for OpenMP directives and clauses --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// \brief This file defines OpenMP AST classes for executable directives and
|
||||
/// clauses.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_STMTOPENMP_H
|
||||
#define LLVM_CLANG_AST_STMTOPENMP_H
|
||||
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AST classes for clauses.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief This is a basic class for representing single OpenMP clause.
|
||||
///
|
||||
class OMPClause {
|
||||
/// \brief Starting location of the clause (the clause keyword).
|
||||
SourceLocation StartLoc;
|
||||
/// \brief Ending location of the clause.
|
||||
SourceLocation EndLoc;
|
||||
/// \brief Kind of the clause.
|
||||
OpenMPClauseKind Kind;
|
||||
protected:
|
||||
OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc)
|
||||
: StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {}
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Returns the starting location of the clause.
|
||||
SourceLocation getLocStart() const { return StartLoc; }
|
||||
/// \brief Returns the ending location of the clause.
|
||||
SourceLocation getLocEnd() const { return EndLoc; }
|
||||
|
||||
/// \brief Sets the starting location of the clause.
|
||||
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
|
||||
/// \brief Sets the ending location of the clause.
|
||||
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
|
||||
|
||||
/// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.).
|
||||
OpenMPClauseKind getClauseKind() const { return Kind; }
|
||||
|
||||
bool isImplicit() const { return StartLoc.isInvalid();}
|
||||
|
||||
StmtRange children();
|
||||
ConstStmtRange children() const {
|
||||
return const_cast<OMPClause *>(this)->children();
|
||||
}
|
||||
static bool classof(const OMPClause *T) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clauses with the list of variables like 'private',
|
||||
/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the
|
||||
/// '#pragma omp ...' directives.
|
||||
template <class T>
|
||||
class OMPVarList {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
/// \brief Number of variables in the list.
|
||||
unsigned NumVars;
|
||||
protected:
|
||||
/// \brief Fetches list of variables associated with this clause.
|
||||
llvm::MutableArrayRef<Expr *> getVarRefs() {
|
||||
return llvm::MutableArrayRef<Expr *>(
|
||||
reinterpret_cast<Expr **>(static_cast<T *>(this) + 1),
|
||||
NumVars);
|
||||
}
|
||||
|
||||
/// \brief Sets the list of variables for this clause.
|
||||
void setVarRefs(ArrayRef<Expr *> VL) {
|
||||
assert(VL.size() == NumVars &&
|
||||
"Number of variables is not the same as the preallocated buffer");
|
||||
std::copy(VL.begin(), VL.end(),
|
||||
reinterpret_cast<Expr **>(static_cast<T *>(this) + 1));
|
||||
}
|
||||
|
||||
/// \brief Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param N Number of the variables in the clause.
|
||||
///
|
||||
OMPVarList(SourceLocation LParenLoc, unsigned N)
|
||||
: LParenLoc(LParenLoc), NumVars(N) { }
|
||||
public:
|
||||
typedef llvm::MutableArrayRef<Expr *>::iterator varlist_iterator;
|
||||
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
|
||||
|
||||
unsigned varlist_size() const { return NumVars; }
|
||||
bool varlist_empty() const { return NumVars == 0; }
|
||||
varlist_iterator varlist_begin() { return getVarRefs().begin(); }
|
||||
varlist_iterator varlist_end() { return getVarRefs().end(); }
|
||||
varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); }
|
||||
varlist_const_iterator varlist_end() const { return getVarRefs().end(); }
|
||||
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// \brief Fetches list of all variables in the clause.
|
||||
ArrayRef<const Expr *> getVarRefs() const {
|
||||
return ArrayRef<const Expr *>(
|
||||
reinterpret_cast<const Expr *const *>(static_cast<const T *>(this) + 1),
|
||||
NumVars);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents 'default' clause in the '#pragma omp ...' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel default(shared)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel' has simple 'default'
|
||||
/// clause with kind 'shared'.
|
||||
///
|
||||
class OMPDefaultClause : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
/// \brief Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
/// \brief A kind of the 'default' clause.
|
||||
OpenMPDefaultClauseKind Kind;
|
||||
/// \brief Start location of the kind in source code.
|
||||
SourceLocation KindKwLoc;
|
||||
|
||||
/// \brief Set kind of the clauses.
|
||||
///
|
||||
/// \param K Argument of clause.
|
||||
///
|
||||
void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; }
|
||||
|
||||
/// \brief Set argument location.
|
||||
///
|
||||
/// \param KLoc Argument location.
|
||||
///
|
||||
void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; }
|
||||
public:
|
||||
/// \brief Build 'default' clause with argument \a A ('none' or 'shared').
|
||||
///
|
||||
/// \param A Argument of the clause ('none' or 'shared').
|
||||
/// \param ALoc Starting location of the argument.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
///
|
||||
OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Kind(A), KindKwLoc(ALoc) { }
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
OMPDefaultClause()
|
||||
: OMPClause(OMPC_default, SourceLocation(), SourceLocation()),
|
||||
LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown),
|
||||
KindKwLoc(SourceLocation()) { }
|
||||
|
||||
/// \brief Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
/// \brief Returns the location of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// \brief Returns kind of the clause.
|
||||
OpenMPDefaultClauseKind getDefaultKind() const { return Kind; }
|
||||
|
||||
/// \brief Returns location of clause kind.
|
||||
SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; }
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_default;
|
||||
}
|
||||
|
||||
StmtRange children() {
|
||||
return StmtRange();
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents clause 'private' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel private(a,b)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel' has clause 'private'
|
||||
/// with the variables 'a' and 'b'.
|
||||
///
|
||||
class OMPPrivateClause : public OMPClause, public OMPVarList<OMPPrivateClause> {
|
||||
/// \brief Build clause with number of variables \a N.
|
||||
///
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param N Number of the variables in the clause.
|
||||
///
|
||||
OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, unsigned N)
|
||||
: OMPClause(OMPC_private, StartLoc, EndLoc),
|
||||
OMPVarList<OMPPrivateClause>(LParenLoc, N) { }
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
/// \param N Number of variables.
|
||||
///
|
||||
explicit OMPPrivateClause(unsigned N)
|
||||
: OMPClause(OMPC_private, SourceLocation(), SourceLocation()),
|
||||
OMPVarList<OMPPrivateClause>(SourceLocation(), N) { }
|
||||
public:
|
||||
/// \brief Creates clause with a list of variables \a VL.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param VL List of references to the variables.
|
||||
///
|
||||
static OMPPrivateClause *Create(ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL);
|
||||
/// \brief Creates an empty clause with the place for \a N variables.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of variables.
|
||||
///
|
||||
static OMPPrivateClause *CreateEmpty(ASTContext &C, unsigned N);
|
||||
|
||||
StmtRange children() {
|
||||
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
|
||||
reinterpret_cast<Stmt **>(varlist_end()));
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_private;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AST classes for directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief This is a basic class for representing single OpenMP executable
|
||||
/// directive.
|
||||
///
|
||||
class OMPExecutableDirective : public Stmt {
|
||||
friend class ASTStmtReader;
|
||||
/// \brief Kind of the directive.
|
||||
OpenMPDirectiveKind Kind;
|
||||
/// \brief Starting location of the directive (directive keyword).
|
||||
SourceLocation StartLoc;
|
||||
/// \brief Ending location of the directive.
|
||||
SourceLocation EndLoc;
|
||||
/// \brief Pointer to the list of clauses.
|
||||
llvm::MutableArrayRef<OMPClause *> Clauses;
|
||||
/// \brief Associated statement (if any) and expressions.
|
||||
llvm::MutableArrayRef<Stmt *> StmtAndExpressions;
|
||||
protected:
|
||||
/// \brief Build instance of directive of class \a K.
|
||||
///
|
||||
/// \param SC Statement class.
|
||||
/// \param K Kind of OpenMP directive.
|
||||
/// \brief StartLoc Starting location of the directive (directive keyword).
|
||||
/// \param EndLocL Ending location of the directive.
|
||||
/// \param Clauses A list of clauses.
|
||||
///
|
||||
template <typename T>
|
||||
OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K,
|
||||
SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned NumClauses, unsigned NumberOfExpressions)
|
||||
: Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc),
|
||||
Clauses(reinterpret_cast<OMPClause **>(static_cast<T *>(this) + 1),
|
||||
NumClauses),
|
||||
StmtAndExpressions(reinterpret_cast<Stmt **>(Clauses.end()),
|
||||
NumberOfExpressions) { }
|
||||
|
||||
/// \brief Sets the list of variables for this clause.
|
||||
///
|
||||
/// \param Clauses The list of clauses for the directive.
|
||||
///
|
||||
void setClauses(ArrayRef<OMPClause *> Clauses);
|
||||
|
||||
/// \brief Set the associated statement for the directive.
|
||||
///
|
||||
/// /param S Associated statement.
|
||||
///
|
||||
void setAssociatedStmt(Stmt *S) {
|
||||
StmtAndExpressions[0] = S;
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief Returns starting location of directive kind.
|
||||
SourceLocation getLocStart() const { return StartLoc; }
|
||||
/// \brief Returns ending location of directive.
|
||||
SourceLocation getLocEnd() const { return EndLoc; }
|
||||
|
||||
/// \brief Set starting location of directive kind.
|
||||
///
|
||||
/// \param Loc New starting location of directive.
|
||||
///
|
||||
void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
|
||||
/// \brief Set ending location of directive.
|
||||
///
|
||||
/// \param Loc New ending location of directive.
|
||||
///
|
||||
void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
|
||||
|
||||
/// \brief Get number of clauses.
|
||||
unsigned getNumClauses() const { return Clauses.size(); }
|
||||
|
||||
/// \brief Returns specified clause.
|
||||
///
|
||||
/// \param i Number of clause.
|
||||
///
|
||||
OMPClause *getClause(unsigned i) const {
|
||||
assert(i < Clauses.size() && "index out of bound!");
|
||||
return Clauses[i];
|
||||
}
|
||||
|
||||
/// \brief Returns statement associated with the directive.
|
||||
Stmt *getAssociatedStmt() const {
|
||||
return StmtAndExpressions[0];
|
||||
}
|
||||
|
||||
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
|
||||
|
||||
static bool classof(const Stmt *S) {
|
||||
return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
|
||||
S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
return child_range(StmtAndExpressions.begin(), StmtAndExpressions.end());
|
||||
}
|
||||
|
||||
ArrayRef<OMPClause *> clauses() { return Clauses; }
|
||||
|
||||
ArrayRef<OMPClause *> clauses() const { return Clauses; }
|
||||
};
|
||||
|
||||
/// \brief This represents '#pragma omp parallel' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp parallel private(a,b) reduction(+: c,d)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp parallel' has clauses 'private'
|
||||
/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
|
||||
/// variables 'c' and 'd'.
|
||||
///
|
||||
class OMPParallelDirective : public OMPExecutableDirective {
|
||||
/// \brief Build directive with the given start and end location.
|
||||
///
|
||||
/// \brief StartLoc Starting location of the directive (directive keyword).
|
||||
/// \param EndLoc Ending Location of the directive.
|
||||
///
|
||||
OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned N)
|
||||
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
|
||||
StartLoc, EndLoc, N, 1) { }
|
||||
|
||||
/// \brief Build an empty directive.
|
||||
///
|
||||
/// \param N Number of clauses.
|
||||
///
|
||||
explicit OMPParallelDirective(unsigned N)
|
||||
: OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel,
|
||||
SourceLocation(), SourceLocation(), N, 1) { }
|
||||
public:
|
||||
/// \brief Creates directive with a list of \a Clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \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 OMPParallelDirective *Create(ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt);
|
||||
|
||||
/// \brief Creates an empty directive with the place for \a N clauses.
|
||||
///
|
||||
/// \param C AST context.
|
||||
/// \param N The number of clauses.
|
||||
///
|
||||
static OMPParallelDirective *CreateEmpty(ASTContext &C, unsigned N,
|
||||
EmptyShell);
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPParallelDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
@@ -184,6 +185,41 @@ template<typename ImplClass, typename RetTy=void>
|
||||
class ConstStmtVisitor
|
||||
: public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
|
||||
|
||||
/// \brief This class implements a simple visitor for OMPClause
|
||||
/// subclasses.
|
||||
template<class ImplClass, template <typename> class Ptr, typename RetTy>
|
||||
class OMPClauseVisitorBase {
|
||||
public:
|
||||
#define PTR(CLASS) typename Ptr<CLASS>::type
|
||||
#define DISPATCH(CLASS) \
|
||||
return static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<PTR(CLASS)>(S))
|
||||
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); }
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
RetTy Visit(PTR(OMPClause) S) {
|
||||
// Top switch clause: visit each OMPClause.
|
||||
switch (S->getClauseKind()) {
|
||||
default: llvm_unreachable("Unknown clause kind!");
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
case OMPC_ ## Name : return Visit ## Class(static_cast<PTR(Class)>(S));
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
}
|
||||
// Base case, ignore it. :)
|
||||
RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); }
|
||||
#undef PTR
|
||||
#undef DISPATCH
|
||||
};
|
||||
|
||||
template<class ImplClass, typename RetTy = void>
|
||||
class OMPClauseVisitor :
|
||||
public OMPClauseVisitorBase <ImplClass, make_ptr, RetTy> {};
|
||||
template<class ImplClass, typename RetTy = void>
|
||||
class ConstOMPClauseVisitor :
|
||||
public OMPClauseVisitorBase <ImplClass, make_const_ptr, RetTy> {};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
||||
@@ -837,6 +837,16 @@ def err_omp_unknown_directive : Error <
|
||||
"expected an OpenMP directive">;
|
||||
def err_omp_unexpected_directive : Error <
|
||||
"unexpected OpenMP directive '#pragma omp %0'">;
|
||||
def err_omp_expected_var : Error <
|
||||
"expected '#pragma omp %0' argument to be a variable name">;
|
||||
def err_omp_expected_punc : Error <
|
||||
"expected ',' or ')' in %select{'#pragma omp %1'|'%1' clause}0">;
|
||||
def err_omp_unknown_clause : Error <
|
||||
"expected OpenMP clause for directive '#pragma omp %0' or end of directive">;
|
||||
def err_omp_unexpected_clause : Error <
|
||||
"unexpected OpenMP clause '%0' in directive '#pragma omp %1'">;
|
||||
def err_omp_more_one_clause : Error <
|
||||
"directive '#pragma omp %0' cannot contain more than one '%1' clause">;
|
||||
} // end of Parse Issue category.
|
||||
|
||||
let CategoryName = "Modules Issue" in {
|
||||
|
||||
@@ -6485,13 +6485,25 @@ def err_omp_expected_var_arg_suggest : Error<
|
||||
def err_omp_global_var_arg : Error<
|
||||
"arguments of '#pragma omp %0' must have %select{global storage|static storage duration}1">;
|
||||
def err_omp_ref_type_arg : Error<
|
||||
"arguments of '#pragma omp %0' cannot be of reference type">;
|
||||
"arguments of '#pragma omp %0' cannot be of reference type %1">;
|
||||
def err_omp_var_scope : Error<
|
||||
"'#pragma omp %0' must appear in the scope of the %q1 variable declaration">;
|
||||
def err_omp_var_used : Error<
|
||||
"'#pragma omp %0' must precede all references to variable %q1">;
|
||||
def err_omp_var_thread_local : Error<
|
||||
"variable %0 cannot be threadprivate because it is thread-local">;
|
||||
def err_omp_private_incomplete_type : Error<
|
||||
"a private variable with incomplete type %0">;
|
||||
def err_omp_directive_nonblock : Error<
|
||||
"directive '#pragma omp %0' bound to nonblock statement">;
|
||||
def err_omp_unexpected_clause_value : Error <
|
||||
"expected %0 in OpenMP clause '%1'">;
|
||||
def err_omp_expected_var_name : Error <
|
||||
"expected variable name">;
|
||||
def err_omp_required_method : Error <
|
||||
"%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
|
||||
def err_omp_clause_ref_type_arg : Error<
|
||||
"arguments of OpenMP clause '%0' cannot be of reference type %1">;
|
||||
def err_omp_threadprivate_incomplete_type : Error<
|
||||
"threadprivate variable with incomplete type %0">;
|
||||
} // end of OpenMP category
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// \brief This file defines the list of supported OpenMP directives and
|
||||
/// \brief This file defines the list of supported OpenMP directives and
|
||||
/// clauses.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -15,9 +15,34 @@
|
||||
#ifndef OPENMP_DIRECTIVE
|
||||
# define OPENMP_DIRECTIVE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_CLAUSE
|
||||
# define OPENMP_CLAUSE(Name, Class)
|
||||
#endif
|
||||
#ifndef OPENMP_PARALLEL_CLAUSE
|
||||
# define OPENMP_PARALLEL_CLAUSE(Name)
|
||||
#endif
|
||||
#ifndef OPENMP_DEFAULT_KIND
|
||||
# define OPENMP_DEFAULT_KIND(Name)
|
||||
#endif
|
||||
|
||||
// OpenMP directives.
|
||||
OPENMP_DIRECTIVE(threadprivate)
|
||||
OPENMP_DIRECTIVE(parallel)
|
||||
OPENMP_DIRECTIVE(task)
|
||||
|
||||
// OpenMP clauses.
|
||||
OPENMP_CLAUSE(default, OMPDefaultClause)
|
||||
OPENMP_CLAUSE(private, OMPPrivateClause)
|
||||
|
||||
// Clauses allowed for OpenMP directives.
|
||||
OPENMP_PARALLEL_CLAUSE(default)
|
||||
OPENMP_PARALLEL_CLAUSE(private)
|
||||
|
||||
// Static attributes for 'default' clause.
|
||||
OPENMP_DEFAULT_KIND(none)
|
||||
OPENMP_DEFAULT_KIND(shared)
|
||||
|
||||
#undef OPENMP_DEFAULT_KIND
|
||||
#undef OPENMP_DIRECTIVE
|
||||
#undef OPENMP_CLAUSE
|
||||
#undef OPENMP_PARALLEL_CLAUSE
|
||||
|
||||
@@ -28,9 +28,37 @@ enum OpenMPDirectiveKind {
|
||||
NUM_OPENMP_DIRECTIVES
|
||||
};
|
||||
|
||||
/// \brief OpenMP clauses.
|
||||
enum OpenMPClauseKind {
|
||||
OMPC_unknown = 0,
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
OMPC_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPC_threadprivate,
|
||||
NUM_OPENMP_CLAUSES
|
||||
};
|
||||
|
||||
/// \brief OpenMP attributes for 'default' clause.
|
||||
enum OpenMPDefaultClauseKind {
|
||||
OMPC_DEFAULT_unknown = 0,
|
||||
#define OPENMP_DEFAULT_KIND(Name) \
|
||||
OMPC_DEFAULT_##Name,
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
NUM_OPENMP_DEFAULT_KINDS
|
||||
};
|
||||
|
||||
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str);
|
||||
const char *getOpenMPDirectiveName(OpenMPDirectiveKind Kind);
|
||||
|
||||
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str);
|
||||
const char *getOpenMPClauseName(OpenMPClauseKind Kind);
|
||||
|
||||
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str);
|
||||
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
|
||||
|
||||
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -175,3 +175,7 @@ def MSDependentExistsStmt : Stmt;
|
||||
|
||||
// OpenCL Extensions.
|
||||
def AsTypeExpr : DStmt<Expr>;
|
||||
|
||||
// OpenMP Directives.
|
||||
def OMPExecutableDirective : Stmt<1>;
|
||||
def OMPParallelDirective : DStmt<OMPExecutableDirective>;
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace clang {
|
||||
class InMessageExpressionRAIIObject;
|
||||
class PoisonSEHIdentifiersRAIIObject;
|
||||
class VersionTuple;
|
||||
class OMPClause;
|
||||
|
||||
/// Parser - This implements a parser for the C family of languages. After
|
||||
/// parsing units of the grammar, productions are invoked to handle whatever has
|
||||
@@ -2155,6 +2156,32 @@ private:
|
||||
bool ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||
SmallVectorImpl<Expr *> &VarList,
|
||||
bool AllowScopeSpecifier);
|
||||
/// \brief Parses declarative or executable directive.
|
||||
StmtResult ParseOpenMPDeclarativeOrExecutableDirective();
|
||||
/// \brief Parses clause of kind \a CKind for directive of a kind \a Kind.
|
||||
///
|
||||
/// \param DKind Kind of current directive.
|
||||
/// \param CKind Kind of current clause.
|
||||
/// \param FirstClause true, if this is the first clause of a kind \a CKind
|
||||
/// in current directive.
|
||||
///
|
||||
OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause);
|
||||
/// \brief Parses clause with a single expression of a kind \a Kind.
|
||||
///
|
||||
/// \param Kind Kind of current clause.
|
||||
///
|
||||
OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind);
|
||||
/// \brief Parses simple clause of a kind \a Kind.
|
||||
///
|
||||
/// \param Kind Kind of current clause.
|
||||
///
|
||||
OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind);
|
||||
/// \brief Parses clause with the list of variables of a kind \a Kind.
|
||||
///
|
||||
/// \param Kind Kind of current clause.
|
||||
///
|
||||
OMPClause *ParseOpenMPVarListClause(OpenMPClauseKind Kind);
|
||||
public:
|
||||
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
|
||||
bool AllowDestructorName,
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include "clang/AST/MangleNumberingContext.h"
|
||||
#include "clang/AST/NSAPI.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/Basic/ExpressionTraits.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TemplateKinds.h"
|
||||
#include "clang/Basic/TypeTraits.h"
|
||||
@@ -4807,6 +4809,9 @@ public:
|
||||
const PartialDiagnostic &PDiag,
|
||||
QualType objectType = QualType());
|
||||
AccessResult CheckFriendAccess(NamedDecl *D);
|
||||
AccessResult CheckMemberAccess(SourceLocation UseLoc,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NamedDecl *D);
|
||||
AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
|
||||
Expr *ObjectExpr,
|
||||
Expr *ArgExpr,
|
||||
@@ -6781,6 +6786,42 @@ public:
|
||||
SourceLocation Loc,
|
||||
ArrayRef<Expr *> VarList);
|
||||
|
||||
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed '\#pragma omp parallel' after parsing
|
||||
/// of the associated statement.
|
||||
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||
unsigned Argument,
|
||||
SourceLocation ArgumentLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'default' clause.
|
||||
OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
|
||||
SourceLocation KindLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||
ArrayRef<Expr *> Vars,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// \brief Called on well-formed 'private' clause.
|
||||
OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// \brief The kind of conversion being performed.
|
||||
enum CheckedConversionKind {
|
||||
/// \brief An implicit conversion.
|
||||
|
||||
@@ -1054,7 +1054,7 @@ namespace clang {
|
||||
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
|
||||
/// \brief An ImportDecl recording a module import.
|
||||
DECL_IMPORT,
|
||||
/// \brief A OMPThreadPrivateDecl record.
|
||||
/// \brief An OMPThreadPrivateDecl record.
|
||||
DECL_OMP_THREADPRIVATE,
|
||||
/// \brief An EmptyDecl record.
|
||||
DECL_EMPTY
|
||||
@@ -1319,7 +1319,10 @@ namespace clang {
|
||||
STMT_SEH_EXCEPT, // SEHExceptStmt
|
||||
STMT_SEH_FINALLY, // SEHFinallyStmt
|
||||
STMT_SEH_TRY, // SEHTryStmt
|
||||
|
||||
|
||||
// OpenMP drectives
|
||||
STMT_OMP_PARALLEL_DIRECTIVE,
|
||||
|
||||
// ARC
|
||||
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
|
||||
|
||||
|
||||
@@ -58,3 +58,4 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
|
||||
Expr **Vars = reinterpret_cast<Expr **>(this + 1);
|
||||
std::copy(VL.begin(), VL.end(), Vars);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/CharInfo.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
@@ -1118,3 +1119,54 @@ bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OMPPrivateClause *OMPPrivateClause::Create(ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<Expr *> VL) {
|
||||
void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * VL.size(),
|
||||
llvm::alignOf<OMPPrivateClause>());
|
||||
OMPPrivateClause *Clause = new (Mem) OMPPrivateClause(StartLoc, LParenLoc,
|
||||
EndLoc, VL.size());
|
||||
Clause->setVarRefs(VL);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPPrivateClause *OMPPrivateClause::CreateEmpty(ASTContext &C,
|
||||
unsigned N) {
|
||||
void *Mem = C.Allocate(sizeof(OMPPrivateClause) + sizeof(Expr *) * N,
|
||||
llvm::alignOf<OMPPrivateClause>());
|
||||
return new (Mem) OMPPrivateClause(N);
|
||||
}
|
||||
|
||||
void OMPExecutableDirective::setClauses(ArrayRef<OMPClause *> Clauses) {
|
||||
assert(Clauses.size() == this->Clauses.size() &&
|
||||
"Number of clauses is not the same as the preallocated buffer");
|
||||
std::copy(Clauses.begin(), Clauses.end(), this->Clauses.begin());
|
||||
}
|
||||
|
||||
OMPParallelDirective *OMPParallelDirective::Create(
|
||||
ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AssociatedStmt) {
|
||||
void *Mem = C.Allocate(sizeof(OMPParallelDirective) +
|
||||
sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *),
|
||||
llvm::alignOf<OMPParallelDirective>());
|
||||
OMPParallelDirective *Dir = new (Mem) OMPParallelDirective(StartLoc, EndLoc,
|
||||
Clauses.size());
|
||||
Dir->setClauses(Clauses);
|
||||
Dir->setAssociatedStmt(AssociatedStmt);
|
||||
return Dir;
|
||||
}
|
||||
|
||||
OMPParallelDirective *OMPParallelDirective::CreateEmpty(ASTContext &C,
|
||||
unsigned N,
|
||||
EmptyShell) {
|
||||
void *Mem = C.Allocate(sizeof(OMPParallelDirective) +
|
||||
sizeof(OMPClause *) * N + sizeof(Stmt *),
|
||||
llvm::alignOf<OMPParallelDirective>());
|
||||
return new (Mem) OMPParallelDirective(N);
|
||||
}
|
||||
|
||||
@@ -579,6 +579,67 @@ void StmtPrinter::VisitSEHFinallyStmt(SEHFinallyStmt *Node) {
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP clauses printing methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class OMPClausePrinter : public OMPClauseVisitor<OMPClausePrinter> {
|
||||
raw_ostream &OS;
|
||||
public:
|
||||
OMPClausePrinter(raw_ostream &OS) : OS(OS) { }
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
void Visit##Class(Class *S);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
};
|
||||
|
||||
void OMPClausePrinter::VisitOMPDefaultClause(OMPDefaultClause *Node) {
|
||||
OS << "default("
|
||||
<< getOpenMPSimpleClauseTypeName(OMPC_default, Node->getDefaultKind())
|
||||
<< ")";
|
||||
}
|
||||
|
||||
#define PROCESS_OMP_CLAUSE_LIST(Class, Node, StartSym) \
|
||||
for (OMPVarList<Class>::varlist_iterator I = Node->varlist_begin(), \
|
||||
E = Node->varlist_end(); \
|
||||
I != E; ++I) \
|
||||
OS << (I == Node->varlist_begin() ? StartSym : ',') \
|
||||
<< *cast<NamedDecl>(cast<DeclRefExpr>(*I)->getDecl());
|
||||
|
||||
void OMPClausePrinter::VisitOMPPrivateClause(OMPPrivateClause *Node) {
|
||||
if (!Node->varlist_empty()) {
|
||||
OS << "private";
|
||||
PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, Node, '(')
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
#undef PROCESS_OMP_CLAUSE_LIST
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP directives printing methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void StmtPrinter::VisitOMPParallelDirective(OMPParallelDirective *Node) {
|
||||
Indent() << "#pragma omp parallel ";
|
||||
|
||||
OMPClausePrinter Printer(OS);
|
||||
ArrayRef<OMPClause *> Clauses = Node->clauses();
|
||||
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
|
||||
I != E; ++I)
|
||||
if (*I && !(*I)->isImplicit()) {
|
||||
Printer.Visit(*I);
|
||||
OS << ' ';
|
||||
}
|
||||
OS << "\n";
|
||||
if (Node->getAssociatedStmt()) {
|
||||
assert(isa<CapturedStmt>(Node->getAssociatedStmt()) &&
|
||||
"Expected captured statement!");
|
||||
Stmt *CS = cast<CapturedStmt>(Node->getAssociatedStmt())->getCapturedStmt();
|
||||
PrintStmt(CS);
|
||||
}
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expr printing methods.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -252,6 +252,40 @@ StmtProfiler::VisitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt *S) {
|
||||
VisitStmt(S);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class OMPClauseProfiler : public ConstOMPClauseVisitor<OMPClauseProfiler> {
|
||||
StmtProfiler *Profiler;
|
||||
public:
|
||||
OMPClauseProfiler(StmtProfiler *P) : Profiler(P) { }
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
void Visit##Class(const Class *C);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
};
|
||||
|
||||
void OMPClauseProfiler::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
#define PROCESS_OMP_CLAUSE_LIST(Class, Node) \
|
||||
for (OMPVarList<Class>::varlist_const_iterator I = Node->varlist_begin(), \
|
||||
E = Node->varlist_end(); \
|
||||
I != E; ++I) \
|
||||
Profiler->VisitStmt(*I);
|
||||
|
||||
void OMPClauseProfiler::VisitOMPPrivateClause(const OMPPrivateClause *C) {
|
||||
PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, C)
|
||||
}
|
||||
#undef PROCESS_OMP_CLAUSE_LIST
|
||||
}
|
||||
|
||||
void
|
||||
StmtProfiler::VisitOMPParallelDirective(const OMPParallelDirective *S) {
|
||||
VisitStmt(S);
|
||||
OMPClauseProfiler P(this);
|
||||
ArrayRef<OMPClause *> Clauses = S->clauses();
|
||||
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
|
||||
I != E; ++I)
|
||||
if (*I)
|
||||
P.Visit(*I);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitExpr(const Expr *S) {
|
||||
VisitStmt(S);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,94 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) {
|
||||
#define OPENMP_DIRECTIVE(Name) \
|
||||
case OMPD_##Name : return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
default:
|
||||
case NUM_OPENMP_DIRECTIVES:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP directive kind");
|
||||
}
|
||||
|
||||
OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) {
|
||||
return llvm::StringSwitch<OpenMPClauseKind>(Str)
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
.Case(#Name, OMPC_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_unknown);
|
||||
}
|
||||
|
||||
const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
|
||||
assert(Kind < NUM_OPENMP_CLAUSES);
|
||||
switch (Kind) {
|
||||
case OMPC_unknown:
|
||||
return "unknown";
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
case OMPC_##Name : return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
case OMPC_threadprivate:
|
||||
return "threadprivate or thread local";
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP clause kind");
|
||||
}
|
||||
|
||||
unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
|
||||
StringRef Str) {
|
||||
switch (Kind) {
|
||||
case OMPC_default:
|
||||
return llvm::StringSwitch<OpenMPDefaultClauseKind>(Str)
|
||||
#define OPENMP_DEFAULT_KIND(Name) \
|
||||
.Case(#Name, OMPC_DEFAULT_##Name)
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
.Default(OMPC_DEFAULT_unknown);
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_private:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP simple clause kind");
|
||||
}
|
||||
|
||||
const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||
unsigned Type) {
|
||||
switch (Kind) {
|
||||
case OMPC_default:
|
||||
switch (Type) {
|
||||
case OMPC_DEFAULT_unknown:
|
||||
return "unknown";
|
||||
#define OPENMP_DEFAULT_KIND(Name) \
|
||||
case OMPC_DEFAULT_##Name : return #Name;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP 'default' clause type");
|
||||
case OMPC_unknown:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_private:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
break;
|
||||
}
|
||||
llvm_unreachable("Invalid OpenMP simple clause kind");
|
||||
}
|
||||
|
||||
bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind) {
|
||||
assert(DKind < NUM_OPENMP_DIRECTIVES);
|
||||
assert(CKind < NUM_OPENMP_CLAUSES);
|
||||
switch (DKind) {
|
||||
case OMPD_parallel:
|
||||
switch (CKind) {
|
||||
#define OPENMP_PARALLEL_CLAUSE(Name) \
|
||||
case OMPC_##Name: return true;
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OMPD_unknown:
|
||||
case OMPD_threadprivate:
|
||||
case OMPD_task:
|
||||
case NUM_OPENMP_DIRECTIVES:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
|
||||
case Stmt::SEHExceptStmtClass:
|
||||
case Stmt::SEHFinallyStmtClass:
|
||||
case Stmt::MSDependentExistsStmtClass:
|
||||
case Stmt::OMPParallelDirectiveClass:
|
||||
llvm_unreachable("invalid statement class to emit generically");
|
||||
case Stmt::NullStmtClass:
|
||||
case Stmt::CompoundStmtClass:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/Parse/ParseDiagnostic.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
@@ -57,7 +58,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
|
||||
case OMPD_unknown:
|
||||
Diag(Tok, diag::err_omp_unknown_directive);
|
||||
break;
|
||||
default:
|
||||
case OMPD_parallel:
|
||||
case OMPD_task:
|
||||
case NUM_OPENMP_DIRECTIVES:
|
||||
Diag(Tok, diag::err_omp_unexpected_directive)
|
||||
<< getOpenMPDirectiveName(DKind);
|
||||
break;
|
||||
@@ -66,6 +69,111 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
|
||||
return DeclGroupPtrTy();
|
||||
}
|
||||
|
||||
/// \brief Parsing of declarative or executable OpenMP directives.
|
||||
///
|
||||
/// threadprivate-directive:
|
||||
/// annot_pragma_openmp 'threadprivate' simple-variable-list
|
||||
/// annot_pragma_openmp_end
|
||||
///
|
||||
/// parallel-directive:
|
||||
/// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end
|
||||
///
|
||||
StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
|
||||
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
||||
SmallVector<Expr *, 5> Identifiers;
|
||||
SmallVector<OMPClause *, 5> Clauses;
|
||||
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES>
|
||||
FirstClauses(NUM_OPENMP_CLAUSES);
|
||||
const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope;
|
||||
SourceLocation Loc = ConsumeToken(), EndLoc;
|
||||
OpenMPDirectiveKind DKind = Tok.isAnnotation() ?
|
||||
OMPD_unknown :
|
||||
getOpenMPDirectiveKind(PP.getSpelling(Tok));
|
||||
StmtResult Directive = StmtError();
|
||||
|
||||
switch (DKind) {
|
||||
case OMPD_threadprivate:
|
||||
ConsumeToken();
|
||||
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
|
||||
// The last seen token is annot_pragma_openmp_end - need to check for
|
||||
// extra tokens.
|
||||
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
||||
<< getOpenMPDirectiveName(OMPD_threadprivate);
|
||||
SkipUntil(tok::annot_pragma_openmp_end, false, true);
|
||||
}
|
||||
DeclGroupPtrTy Res =
|
||||
Actions.ActOnOpenMPThreadprivateDirective(Loc,
|
||||
Identifiers);
|
||||
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
||||
}
|
||||
SkipUntil(tok::annot_pragma_openmp_end, false);
|
||||
break;
|
||||
case OMPD_parallel: {
|
||||
ConsumeToken();
|
||||
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
OpenMPClauseKind CKind = Tok.isAnnotation() ?
|
||||
OMPC_unknown :
|
||||
getOpenMPClauseKind(PP.getSpelling(Tok));
|
||||
OMPClause *Clause = ParseOpenMPClause(DKind, CKind,
|
||||
!FirstClauses[CKind].getInt());
|
||||
FirstClauses[CKind].setInt(true);
|
||||
if (Clause) {
|
||||
FirstClauses[CKind].setPointer(Clause);
|
||||
Clauses.push_back(Clause);
|
||||
}
|
||||
|
||||
// Skip ',' if any.
|
||||
if (Tok.is(tok::comma))
|
||||
ConsumeToken();
|
||||
}
|
||||
// End location of the directive.
|
||||
EndLoc = Tok.getLocation();
|
||||
// Consume final annot_pragma_openmp_end.
|
||||
ConsumeToken();
|
||||
|
||||
StmtResult AssociatedStmt;
|
||||
bool CreateDirective = true;
|
||||
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
||||
{
|
||||
// The body is a block scope like in Lambdas and Blocks.
|
||||
Sema::CompoundScopeRAII CompoundScope(Actions);
|
||||
Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default, 1);
|
||||
Actions.ActOnStartOfCompoundStmt();
|
||||
// Parse statement
|
||||
AssociatedStmt = ParseStatement();
|
||||
Actions.ActOnFinishOfCompoundStmt();
|
||||
if (!AssociatedStmt.isUsable()) {
|
||||
Actions.ActOnCapturedRegionError();
|
||||
CreateDirective = false;
|
||||
} else {
|
||||
AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take());
|
||||
CreateDirective = AssociatedStmt.isUsable();
|
||||
}
|
||||
}
|
||||
if (CreateDirective)
|
||||
Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses,
|
||||
AssociatedStmt.take(),
|
||||
Loc, EndLoc);
|
||||
|
||||
// Exit scope.
|
||||
OMPDirectiveScope.Exit();
|
||||
}
|
||||
break;
|
||||
case OMPD_unknown:
|
||||
Diag(Tok, diag::err_omp_unknown_directive);
|
||||
SkipUntil(tok::annot_pragma_openmp_end, false);
|
||||
break;
|
||||
case OMPD_task:
|
||||
case NUM_OPENMP_DIRECTIVES:
|
||||
Diag(Tok, diag::err_omp_unexpected_directive)
|
||||
<< getOpenMPDirectiveName(DKind);
|
||||
SkipUntil(tok::annot_pragma_openmp_end, false);
|
||||
break;
|
||||
}
|
||||
return Directive;
|
||||
}
|
||||
|
||||
/// \brief Parses list of simple variables for '#pragma omp threadprivate'
|
||||
/// directive.
|
||||
///
|
||||
@@ -78,9 +186,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||
VarList.clear();
|
||||
// Parse '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
bool LParen = !T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
getOpenMPDirectiveName(Kind));
|
||||
bool IsCorrect = LParen;
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
getOpenMPDirectiveName(Kind)))
|
||||
return true;
|
||||
bool IsCorrect = true;
|
||||
bool NoIdentIsFound = true;
|
||||
|
||||
// Read tokens while ')' or annot_pragma_openmp_end is not found.
|
||||
@@ -128,8 +237,130 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
|
||||
}
|
||||
|
||||
// Parse ')'.
|
||||
IsCorrect = ((LParen || Tok.is(tok::r_paren)) && !T.consumeClose())
|
||||
&& IsCorrect;
|
||||
IsCorrect = !T.consumeClose() && IsCorrect;
|
||||
|
||||
return !IsCorrect && VarList.empty();
|
||||
}
|
||||
|
||||
/// \brief Parsing of OpenMP clauses.
|
||||
///
|
||||
/// clause:
|
||||
/// default-clause|private-clause
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
OpenMPClauseKind CKind, bool FirstClause) {
|
||||
OMPClause *Clause = 0;
|
||||
bool ErrorFound = false;
|
||||
// Check if clause is allowed for the given directive.
|
||||
if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
|
||||
Diag(Tok, diag::err_omp_unexpected_clause)
|
||||
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
||||
ErrorFound = true;
|
||||
}
|
||||
|
||||
switch (CKind) {
|
||||
case OMPC_default:
|
||||
// OpenMP [2.9.3.1, Restrictions]
|
||||
// Only a single default clause may be specified on a parallel or task
|
||||
// directive.
|
||||
if (!FirstClause) {
|
||||
Diag(Tok, diag::err_omp_more_one_clause)
|
||||
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind);
|
||||
}
|
||||
|
||||
Clause = ParseOpenMPSimpleClause(CKind);
|
||||
break;
|
||||
case OMPC_private:
|
||||
Clause = ParseOpenMPVarListClause(CKind);
|
||||
break;
|
||||
case OMPC_unknown:
|
||||
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
||||
<< getOpenMPDirectiveName(DKind);
|
||||
SkipUntil(tok::annot_pragma_openmp_end, false, true);
|
||||
break;
|
||||
case OMPC_threadprivate:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
Diag(Tok, diag::err_omp_unexpected_clause)
|
||||
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
||||
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, false, true);
|
||||
break;
|
||||
}
|
||||
return ErrorFound ? 0 : Clause;
|
||||
}
|
||||
|
||||
/// \brief Parsing of simple OpenMP clauses like 'default'.
|
||||
///
|
||||
/// default-clause:
|
||||
/// 'default' '(' 'none' | 'shared' ')
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
SourceLocation LOpen = ConsumeToken();
|
||||
// Parse '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
getOpenMPClauseName(Kind)))
|
||||
return 0;
|
||||
|
||||
unsigned Type = Tok.isAnnotation() ?
|
||||
OMPC_DEFAULT_unknown :
|
||||
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
|
||||
SourceLocation TypeLoc = Tok.getLocation();
|
||||
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))
|
||||
ConsumeAnyToken();
|
||||
|
||||
// Parse ')'.
|
||||
T.consumeClose();
|
||||
|
||||
return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
|
||||
Tok.getLocation());
|
||||
}
|
||||
|
||||
/// \brief Parsing of OpenMP clause 'private', 'firstprivate',
|
||||
/// 'shared', 'copyin', or 'reduction'.
|
||||
///
|
||||
/// private-clause:
|
||||
/// 'private' '(' list ')'
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
|
||||
SourceLocation Loc = Tok.getLocation();
|
||||
SourceLocation LOpen = ConsumeToken();
|
||||
// Parse '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
||||
getOpenMPClauseName(Kind)))
|
||||
return 0;
|
||||
|
||||
SmallVector<Expr *, 5> Vars;
|
||||
bool IsComma = true;
|
||||
while (IsComma || (Tok.isNot(tok::r_paren) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end))) {
|
||||
// Parse variable
|
||||
ExprResult VarExpr = ParseAssignmentExpression();
|
||||
if (VarExpr.isUsable()) {
|
||||
Vars.push_back(VarExpr.take());
|
||||
} else {
|
||||
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
||||
false, true);
|
||||
}
|
||||
// Skip ',' if any
|
||||
IsComma = Tok.is(tok::comma);
|
||||
if (IsComma) {
|
||||
ConsumeToken();
|
||||
} else if (Tok.isNot(tok::r_paren) &&
|
||||
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
||||
Diag(Tok, diag::err_omp_expected_punc)
|
||||
<< 1 << getOpenMPClauseName(Kind);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse ')'.
|
||||
T.consumeClose();
|
||||
if (Vars.empty())
|
||||
return 0;
|
||||
|
||||
return Actions.ActOnOpenMPVarListClause(Kind, Vars, Loc, LOpen,
|
||||
Tok.getLocation());
|
||||
}
|
||||
|
||||
|
||||
@@ -306,9 +306,8 @@ Retry:
|
||||
return HandlePragmaCaptured();
|
||||
|
||||
case tok::annot_pragma_openmp:
|
||||
SourceLocation DeclStart = Tok.getLocation();
|
||||
DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective();
|
||||
return Actions.ActOnDeclStmt(Res, DeclStart, Tok.getLocation());
|
||||
return ParseOpenMPDeclarativeOrExecutableDirective();
|
||||
|
||||
}
|
||||
|
||||
// If we reached this code, the statement must end in a semicolon.
|
||||
|
||||
@@ -1710,6 +1710,21 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
|
||||
return CheckAccess(*this, OpLoc, Entity);
|
||||
}
|
||||
|
||||
/// \brief Checks access to a member.
|
||||
Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc,
|
||||
CXXRecordDecl *NamingClass,
|
||||
NamedDecl *D) {
|
||||
if (!getLangOpts().AccessControl ||
|
||||
!NamingClass ||
|
||||
D->getAccess() == AS_public)
|
||||
return AR_accessible;
|
||||
|
||||
AccessTarget Entity(Context, AccessTarget::Member, NamingClass,
|
||||
DeclAccessPair::make(D, D->getAccess()), QualType());
|
||||
|
||||
return CheckAccess(*this, UseLoc, Entity);
|
||||
}
|
||||
|
||||
/// Checks access to an overloaded member operator, including
|
||||
/// conversion operators.
|
||||
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
|
||||
|
||||
@@ -14,10 +14,17 @@
|
||||
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclOpenMP.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Sema/Initialization.h"
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
@@ -165,7 +172,8 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
|
||||
// A threadprivate variable must not have a reference type.
|
||||
if (VD->getType()->isReferenceType()) {
|
||||
Diag(ILoc, diag::err_omp_ref_type_arg)
|
||||
<< getOpenMPDirectiveName(OMPD_threadprivate);
|
||||
<< getOpenMPDirectiveName(OMPD_threadprivate)
|
||||
<< VD->getType();
|
||||
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
|
||||
@@ -191,3 +199,215 @@ OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl(
|
||||
Loc, Vars);
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
StmtResult Res = StmtError();
|
||||
switch (Kind) {
|
||||
case OMPD_parallel:
|
||||
Res = ActOnOpenMPParallelDirective(Clauses, AStmt, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_threadprivate:
|
||||
case OMPD_task:
|
||||
llvm_unreachable("OpenMP Directive is not allowed");
|
||||
case OMPD_unknown:
|
||||
case NUM_OPENMP_DIRECTIVES:
|
||||
llvm_unreachable("Unknown OpenMP directive");
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
return Owned(OMPParallelDirective::Create(Context, StartLoc, EndLoc,
|
||||
Clauses, AStmt));
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
|
||||
unsigned Argument,
|
||||
SourceLocation ArgumentLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
OMPClause *Res = 0;
|
||||
switch (Kind) {
|
||||
case OMPC_default:
|
||||
Res = ActOnOpenMPDefaultClause(
|
||||
static_cast<OpenMPDefaultClauseKind>(Argument),
|
||||
ArgumentLoc, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_private:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind,
|
||||
SourceLocation KindKwLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
if (Kind == OMPC_DEFAULT_unknown) {
|
||||
std::string Values;
|
||||
std::string Sep(NUM_OPENMP_DEFAULT_KINDS > 1 ? ", " : "");
|
||||
for (unsigned i = OMPC_DEFAULT_unknown + 1;
|
||||
i < NUM_OPENMP_DEFAULT_KINDS; ++i) {
|
||||
Values += "'";
|
||||
Values += getOpenMPSimpleClauseTypeName(OMPC_default, i);
|
||||
Values += "'";
|
||||
switch (i) {
|
||||
case NUM_OPENMP_DEFAULT_KINDS - 2:
|
||||
Values += " or ";
|
||||
break;
|
||||
case NUM_OPENMP_DEFAULT_KINDS - 1:
|
||||
break;
|
||||
default:
|
||||
Values += Sep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
|
||||
<< Values << getOpenMPClauseName(OMPC_default);
|
||||
return 0;
|
||||
}
|
||||
return new (Context) OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
|
||||
ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
OMPClause *Res = 0;
|
||||
switch (Kind) {
|
||||
case OMPC_private:
|
||||
Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_default:
|
||||
case OMPC_threadprivate:
|
||||
case OMPC_unknown:
|
||||
case NUM_OPENMP_CLAUSES:
|
||||
llvm_unreachable("Clause is not allowed.");
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
SmallVector<Expr *, 8> Vars;
|
||||
for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end();
|
||||
I != E; ++I) {
|
||||
if (*I && isa<DependentScopeDeclRefExpr>(*I)) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
SourceLocation ELoc = (*I)->getExprLoc();
|
||||
// OpenMP [2.1, C/C++]
|
||||
// A list item is a variable name.
|
||||
// OpenMP [2.9.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_or_null<DeclRefExpr>(*I);
|
||||
if (!DE || !isa<VarDecl>(DE->getDecl())) {
|
||||
Diag(ELoc, diag::err_omp_expected_var_name)
|
||||
<< (*I)->getSourceRange();
|
||||
continue;
|
||||
}
|
||||
Decl *D = DE->getDecl();
|
||||
VarDecl *VD = cast<VarDecl>(D);
|
||||
|
||||
QualType Type = VD->getType();
|
||||
if (Type->isDependentType() || Type->isInstantiationDependentType()) {
|
||||
// It will be analyzed later.
|
||||
Vars.push_back(DE);
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
|
||||
// A variable that appears in a private clause must not have an incomplete
|
||||
// type or a reference type.
|
||||
if (RequireCompleteType(ELoc, Type,
|
||||
diag::err_omp_private_incomplete_type)) {
|
||||
continue;
|
||||
}
|
||||
if (Type->isReferenceType()) {
|
||||
Diag(ELoc, diag::err_omp_clause_ref_type_arg)
|
||||
<< getOpenMPClauseName(OMPC_private) << Type;
|
||||
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
|
||||
diag::note_defined_here) << VD;
|
||||
continue;
|
||||
}
|
||||
|
||||
// OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
|
||||
// A variable of class type (or array thereof) that appears in a private
|
||||
// clause requires an accesible, unambiguous default constructor for the
|
||||
// class type.
|
||||
while (Type.getNonReferenceType()->isArrayType()) {
|
||||
Type = cast<ArrayType>(
|
||||
Type.getNonReferenceType().getTypePtr())->getElementType();
|
||||
}
|
||||
CXXRecordDecl *RD = getLangOpts().CPlusPlus ?
|
||||
Type.getNonReferenceType()->getAsCXXRecordDecl() : 0;
|
||||
if (RD) {
|
||||
CXXConstructorDecl *CD = LookupDefaultConstructor(RD);
|
||||
PartialDiagnostic PD =
|
||||
PartialDiagnostic(PartialDiagnostic::NullDiagnostic());
|
||||
if (!CD ||
|
||||
CheckConstructorAccess(ELoc, CD,
|
||||
InitializedEntity::InitializeTemporary(Type),
|
||||
CD->getAccess(), PD) == AR_inaccessible ||
|
||||
CD->isDeleted()) {
|
||||
Diag(ELoc, diag::err_omp_required_method)
|
||||
<< getOpenMPClauseName(OMPC_private) << 0;
|
||||
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
|
||||
diag::note_defined_here) << VD;
|
||||
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
|
||||
continue;
|
||||
}
|
||||
MarkFunctionReferenced(ELoc, CD);
|
||||
DiagnoseUseOfDecl(CD, ELoc);
|
||||
|
||||
CXXDestructorDecl *DD = RD->getDestructor();
|
||||
if (DD) {
|
||||
if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible ||
|
||||
DD->isDeleted()) {
|
||||
Diag(ELoc, diag::err_omp_required_method)
|
||||
<< getOpenMPClauseName(OMPC_private) << 4;
|
||||
bool IsDecl = VD->isThisDeclarationADefinition(Context) ==
|
||||
VarDecl::DeclarationOnly;
|
||||
Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl :
|
||||
diag::note_defined_here) << VD;
|
||||
Diag(RD->getLocation(), diag::note_previous_decl) << RD;
|
||||
continue;
|
||||
}
|
||||
MarkFunctionReferenced(ELoc, DD);
|
||||
DiagnoseUseOfDecl(DD, ELoc);
|
||||
}
|
||||
}
|
||||
|
||||
Vars.push_back(DE);
|
||||
}
|
||||
|
||||
if (Vars.empty()) return 0;
|
||||
|
||||
return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Sema/Designator.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
@@ -313,6 +314,16 @@ public:
|
||||
/// \returns the transformed statement.
|
||||
StmtResult TransformStmt(Stmt *S);
|
||||
|
||||
/// \brief Transform the given statement.
|
||||
///
|
||||
/// By default, this routine transforms a statement by delegating to the
|
||||
/// appropriate TransformOMPXXXClause function to transform a specific kind
|
||||
/// of clause. Subclasses may override this function to transform statements
|
||||
/// using some other mechanism.
|
||||
///
|
||||
/// \returns the transformed OpenMP clause.
|
||||
OMPClause *TransformOMPClause(OMPClause *S);
|
||||
|
||||
/// \brief Transform the given expression.
|
||||
///
|
||||
/// By default, this routine transforms an expression by delegating to the
|
||||
@@ -594,6 +605,10 @@ public:
|
||||
#define ABSTRACT_STMT(Stmt)
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
OMPClause *Transform ## Class(Class *S);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
/// \brief Build a new pointer type given its pointee type.
|
||||
///
|
||||
/// By default, performs semantic analysis when building the pointer type.
|
||||
@@ -1255,6 +1270,43 @@ public:
|
||||
return getSema().BuildObjCAtThrowStmt(AtLoc, Operand);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP parallel directive.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
StmtResult RebuildOMPParallelDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPParallelDirective(Clauses, AStmt,
|
||||
StartLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'default' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPDefaultClause(OpenMPDefaultClauseKind Kind,
|
||||
SourceLocation KindKwLoc,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPDefaultClause(Kind, KindKwLoc,
|
||||
StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Build a new OpenMP 'private' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPPrivateClause(ArrayRef<Expr *> VarList,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
/// \brief Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
@@ -2600,6 +2652,23 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) {
|
||||
return SemaRef.Owned(S);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPClause(OMPClause *S) {
|
||||
if (!S)
|
||||
return S;
|
||||
|
||||
switch (S->getClauseKind()) {
|
||||
default: break;
|
||||
// Transform individual clause nodes
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
case OMPC_ ## Name : \
|
||||
return getDerived().Transform ## Class(cast<Class>(S));
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
}
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
|
||||
template<typename Derived>
|
||||
ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) {
|
||||
@@ -6178,6 +6247,67 @@ TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) {
|
||||
return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPParallelDirective(OMPParallelDirective *D) {
|
||||
// Transform the clauses
|
||||
llvm::SmallVector<OMPClause *, 5> TClauses;
|
||||
ArrayRef<OMPClause *> Clauses = D->clauses();
|
||||
TClauses.reserve(Clauses.size());
|
||||
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
|
||||
I != E; ++I) {
|
||||
if (*I) {
|
||||
OMPClause *Clause = getDerived().TransformOMPClause(*I);
|
||||
if (!Clause)
|
||||
return StmtError();
|
||||
TClauses.push_back(Clause);
|
||||
}
|
||||
else {
|
||||
TClauses.push_back(0);
|
||||
}
|
||||
}
|
||||
if (!D->getAssociatedStmt())
|
||||
return StmtError();
|
||||
StmtResult AssociatedStmt =
|
||||
getDerived().TransformStmt(D->getAssociatedStmt());
|
||||
if (AssociatedStmt.isInvalid())
|
||||
return StmtError();
|
||||
|
||||
return getDerived().RebuildOMPParallelDirective(TClauses,
|
||||
AssociatedStmt.take(),
|
||||
D->getLocStart(),
|
||||
D->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPDefaultClause(OMPDefaultClause *C) {
|
||||
return getDerived().RebuildOMPDefaultClause(C->getDefaultKind(),
|
||||
C->getDefaultKindKwLoc(),
|
||||
C->getLocStart(),
|
||||
C->getLParenLoc(),
|
||||
C->getLocEnd());
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPPrivateClause(OMPPrivateClause *C) {
|
||||
llvm::SmallVector<Expr *, 5> Vars;
|
||||
Vars.reserve(C->varlist_size());
|
||||
for (OMPVarList<OMPPrivateClause>::varlist_iterator I = C->varlist_begin(),
|
||||
E = C->varlist_end();
|
||||
I != E; ++I) {
|
||||
ExprResult EVar = getDerived().TransformExpr(cast<Expr>(*I));
|
||||
if (EVar.isInvalid())
|
||||
return 0;
|
||||
Vars.push_back(EVar.take());
|
||||
}
|
||||
return getDerived().RebuildOMPPrivateClause(Vars,
|
||||
C->getLocStart(),
|
||||
C->getLParenLoc(),
|
||||
C->getLocEnd());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Expression transformation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -25,6 +25,7 @@ using namespace clang::serialization;
|
||||
namespace clang {
|
||||
|
||||
class ASTStmtReader : public StmtVisitor<ASTStmtReader> {
|
||||
friend class OMPClauseReader;
|
||||
typedef ASTReader::RecordData RecordData;
|
||||
|
||||
ASTReader &Reader;
|
||||
@@ -382,6 +383,7 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) {
|
||||
|
||||
void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) {
|
||||
VisitStmt(S);
|
||||
++Idx;
|
||||
S->setCapturedDecl(ReadDeclAs<CapturedDecl>(Record, Idx));
|
||||
S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record[Idx++]));
|
||||
S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>(Record, Idx));
|
||||
@@ -1655,6 +1657,81 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) {
|
||||
E->SrcExpr = Reader.ReadSubExpr();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Clauses.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> {
|
||||
ASTStmtReader *Reader;
|
||||
ASTContext &Context;
|
||||
const ASTReader::RecordData &Record;
|
||||
unsigned &Idx;
|
||||
public:
|
||||
OMPClauseReader(ASTStmtReader *R, ASTContext &C,
|
||||
const ASTReader::RecordData &Record, unsigned &Idx)
|
||||
: Reader(R), Context(C), Record(Record), Idx(Idx) { }
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
void Visit##Class(Class *S);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
OMPClause *readClause();
|
||||
};
|
||||
}
|
||||
|
||||
OMPClause *OMPClauseReader::readClause() {
|
||||
OMPClause *C;
|
||||
switch (Record[Idx++]) {
|
||||
case OMPC_default:
|
||||
C = new (Context) OMPDefaultClause();
|
||||
break;
|
||||
case OMPC_private:
|
||||
C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]);
|
||||
break;
|
||||
}
|
||||
Visit(C);
|
||||
C->setLocStart(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setLocEnd(Reader->ReadSourceLocation(Record, Idx));
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
C->setDefaultKind(
|
||||
static_cast<OpenMPDefaultClauseKind>(Record[Idx++]));
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx));
|
||||
unsigned NumVars = C->varlist_size();
|
||||
SmallVector<Expr *, 16> Vars;
|
||||
Vars.reserve(NumVars);
|
||||
for (unsigned i = 0; i != NumVars; ++i)
|
||||
Vars.push_back(Reader->Reader.ReadSubExpr());
|
||||
C->setVarRefs(Vars);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
|
||||
VisitStmt(E);
|
||||
++Idx;
|
||||
E->setLocStart(ReadSourceLocation(Record, Idx));
|
||||
E->setLocEnd(ReadSourceLocation(Record, Idx));
|
||||
OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx);
|
||||
SmallVector<OMPClause *, 5> Clauses;
|
||||
for (unsigned i = 0; i < E->getNumClauses(); ++i)
|
||||
Clauses.push_back(ClauseReader.readClause());
|
||||
E->setClauses(Clauses);
|
||||
E->setAssociatedStmt(Reader.ReadSubStmt());
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
|
||||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ASTReader Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -1821,7 +1898,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
|
||||
case STMT_CAPTURED:
|
||||
S = CapturedStmt::CreateDeserialized(Context,
|
||||
Record[ASTStmtReader::NumExprFields]);
|
||||
Record[ASTStmtReader::NumStmtFields]);
|
||||
break;
|
||||
|
||||
case EXPR_PREDEFINED:
|
||||
@@ -2121,6 +2198,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
DeclarationNameInfo(),
|
||||
0);
|
||||
break;
|
||||
case STMT_OMP_PARALLEL_DIRECTIVE:
|
||||
S =
|
||||
OMPParallelDirective::CreateEmpty(Context,
|
||||
Record[ASTStmtReader::NumStmtFields],
|
||||
Empty);
|
||||
break;
|
||||
|
||||
case EXPR_CXX_OPERATOR_CALL:
|
||||
S = new (Context) CXXOperatorCallExpr(Context, Empty);
|
||||
|
||||
@@ -26,7 +26,9 @@ using namespace clang;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> {
|
||||
friend class OMPClauseWriter;
|
||||
ASTWriter &Writer;
|
||||
ASTWriter::RecordData &Record;
|
||||
|
||||
@@ -1658,6 +1660,66 @@ void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) {
|
||||
Code = serialization::STMT_SEH_TRY;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Clauses.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {
|
||||
ASTStmtWriter *Writer;
|
||||
ASTWriter::RecordData &Record;
|
||||
public:
|
||||
OMPClauseWriter(ASTStmtWriter *W, ASTWriter::RecordData &Record)
|
||||
: Writer(W), Record(Record) { }
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
void Visit##Class(Class *S);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
void writeClause(OMPClause *C);
|
||||
};
|
||||
}
|
||||
|
||||
void OMPClauseWriter::writeClause(OMPClause *C) {
|
||||
Record.push_back(C->getClauseKind());
|
||||
Visit(C);
|
||||
Writer->Writer.AddSourceLocation(C->getLocStart(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getLocEnd(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
Record.push_back(C->getDefaultKind());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record);
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record);
|
||||
for (OMPVarList<OMPPrivateClause>::varlist_iterator I = C->varlist_begin(),
|
||||
E = C->varlist_end();
|
||||
I != E; ++I)
|
||||
Writer->Writer.AddStmt(*I);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// OpenMP Directives.
|
||||
//===----------------------------------------------------------------------===//
|
||||
void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) {
|
||||
VisitStmt(E);
|
||||
Record.push_back(E->getNumClauses());
|
||||
Writer.AddSourceLocation(E->getLocStart(), Record);
|
||||
Writer.AddSourceLocation(E->getLocEnd(), Record);
|
||||
OMPClauseWriter ClauseWriter(this, Record);
|
||||
for (unsigned i = 0; i < E->getNumClauses(); ++i) {
|
||||
ClauseWriter.writeClause(E->getClause(i));
|
||||
}
|
||||
Writer.AddStmt(E->getAssociatedStmt());
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
|
||||
VisitOMPExecutableDirective(D);
|
||||
Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ASTWriter Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -665,6 +665,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||
case Stmt::WhileStmtClass:
|
||||
case Expr::MSDependentExistsStmtClass:
|
||||
case Stmt::CapturedStmtClass:
|
||||
case Stmt::OMPParallelDirectiveClass:
|
||||
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
|
||||
|
||||
case Stmt::ObjCSubscriptRefExprClass:
|
||||
|
||||
26
clang/test/OpenMP/parallel_ast_print.cpp
Normal file
26
clang/test/OpenMP/parallel_ast_print.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
void foo() {}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
int b = argc, c, d, e, f, g;
|
||||
static int a;
|
||||
// CHECK: static int a;
|
||||
#pragma omp parallel
|
||||
// CHECK-NEXT: #pragma omp parallel
|
||||
a=2;
|
||||
// CHECK-NEXT: a = 2;
|
||||
#pragma omp parallel default(none), private(argc,b)
|
||||
// CHECK-NEXT: #pragma omp parallel default(none) private(argc,b)
|
||||
foo();
|
||||
// CHECK-NEXT: foo();
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
15
clang/test/OpenMP/parallel_default_messages.cpp
Normal file
15
clang/test/OpenMP/parallel_default_messages.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -o - %s
|
||||
|
||||
void foo();
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#pragma omp parallel default // expected-error {{expected '(' after 'default'}}
|
||||
#pragma omp parallel default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
|
||||
#pragma omp parallel default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel default (shared), default(shared) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'default' clause}}
|
||||
#pragma omp parallel default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
|
||||
foo();
|
||||
|
||||
return 0;
|
||||
}
|
||||
69
clang/test/OpenMP/parallel_private_messages.cpp
Normal file
69
clang/test/OpenMP/parallel_private_messages.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
void foo() {
|
||||
}
|
||||
|
||||
bool foobool(int argc) {
|
||||
return argc;
|
||||
}
|
||||
|
||||
struct S1; // expected-note {{declared here}} expected-note{{forward declaration of 'S1'}}
|
||||
extern S1 a;
|
||||
class S2 {
|
||||
mutable int a;
|
||||
public:
|
||||
S2():a(0) { }
|
||||
static float S2s;
|
||||
};
|
||||
const S2 b;
|
||||
const S2 ba[5];
|
||||
class S3 {
|
||||
int a;
|
||||
public:
|
||||
S3():a(0) { }
|
||||
};
|
||||
const S3 c;
|
||||
const S3 ca[5];
|
||||
extern const int f;
|
||||
class S4 { // expected-note {{'S4' declared here}}
|
||||
int a;
|
||||
S4();
|
||||
public:
|
||||
S4(int v):a(v) { }
|
||||
};
|
||||
class S5 { // expected-note {{'S5' declared here}}
|
||||
int a;
|
||||
S5():a(0) {}
|
||||
public:
|
||||
S5(int v):a(v) { }
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const int d = 5;
|
||||
const int da[5] = { 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 parallel private // expected-error {{expected '(' after 'private'}}
|
||||
#pragma omp parallel private ( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel private () // expected-error {{expected expression}}
|
||||
#pragma omp parallel private (argc // expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel private (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp parallel private (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel private (argc argv) // expected-error {{expected ',' or ')' in 'private' clause}}
|
||||
#pragma omp parallel private (S1) // expected-error {{'S1' does not refer to a value}}
|
||||
#pragma omp parallel private (a, b, c, d, f) // expected-error {{a private variable with incomplete type 'S1'}}
|
||||
#pragma omp parallel private (argv[1]) // expected-error {{expected variable name}}
|
||||
#pragma omp parallel private(ba)
|
||||
#pragma omp parallel private(ca)
|
||||
#pragma omp parallel private(da)
|
||||
#pragma omp parallel private(S2::S2s)
|
||||
#pragma omp parallel private(e, g) // expected-error 2 {{private variable must have an accessible, unambiguous default constructor}}
|
||||
foo();
|
||||
#pragma omp parallel private(i)
|
||||
#pragma omp parallel private(j) // expected-error {{arguments of OpenMP clause 'private' cannot be of reference type 'int &'}}
|
||||
foo();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t
|
||||
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
struct St{
|
||||
int a;
|
||||
};
|
||||
@@ -41,3 +46,5 @@ int main () {
|
||||
a=2;
|
||||
return (foo<int>());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 %s
|
||||
|
||||
#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}} expected-error {{expected identifier}}
|
||||
#pragma omp threadprivate // expected-error {{expected '(' after 'threadprivate'}}
|
||||
#pragma omp threadprivate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
||||
#pragma omp threadprivate() // expected-error {{expected identifier}}
|
||||
#pragma omp threadprivate(1) // expected-error {{expected unqualified-id}}
|
||||
@@ -24,7 +24,7 @@ int foo() { // expected-note {{declared here}}
|
||||
return (a);
|
||||
}
|
||||
|
||||
#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'a'}}
|
||||
#pragma omp threadprivate a // expected-error {{expected '(' after 'threadprivate'}}
|
||||
#pragma omp threadprivate(d // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}}
|
||||
#pragma omp threadprivate(d)) // expected-error {{'#pragma omp threadprivate' must precede all references to variable 'd'}} expected-warning {{extra tokens at the end of '#pragma omp threadprivate' are ignored}}
|
||||
int x, y;
|
||||
@@ -44,7 +44,7 @@ extern IncompleteSt e;
|
||||
#pragma omp threadprivate (e) // expected-error {{threadprivate variable with incomplete type 'IncompleteSt'}}
|
||||
|
||||
int &f = a; // expected-note {{'f' defined here}}
|
||||
#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type}}
|
||||
#pragma omp threadprivate (f) // expected-error {{arguments of '#pragma omp threadprivate' cannot be of reference type 'int &'}}
|
||||
|
||||
class Class {
|
||||
private:
|
||||
|
||||
@@ -1802,6 +1802,7 @@ public:
|
||||
}
|
||||
};
|
||||
class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> {
|
||||
friend class OMPClauseEnqueue;
|
||||
VisitorWorkList &WL;
|
||||
CXCursor Parent;
|
||||
public:
|
||||
@@ -1853,6 +1854,8 @@ public:
|
||||
void VisitPseudoObjectExpr(const PseudoObjectExpr *E);
|
||||
void VisitOpaqueValueExpr(const OpaqueValueExpr *E);
|
||||
void VisitLambdaExpr(const LambdaExpr *E);
|
||||
void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
|
||||
void VisitOMPParallelDirective(const OMPParallelDirective *D);
|
||||
|
||||
private:
|
||||
void AddDeclarationNameInfo(const Stmt *S);
|
||||
@@ -1863,6 +1866,7 @@ private:
|
||||
void AddDecl(const Decl *D, bool isFirst = true);
|
||||
void AddTypeLoc(TypeSourceInfo *TI);
|
||||
void EnqueueChildren(const Stmt *S);
|
||||
void EnqueueChildren(const OMPClause *S);
|
||||
};
|
||||
} // end anonyous namespace
|
||||
|
||||
@@ -1911,6 +1915,39 @@ void EnqueueVisitor::EnqueueChildren(const Stmt *S) {
|
||||
VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
|
||||
std::reverse(I, E);
|
||||
}
|
||||
namespace {
|
||||
class OMPClauseEnqueue : public ConstOMPClauseVisitor<OMPClauseEnqueue> {
|
||||
EnqueueVisitor *Visitor;
|
||||
public:
|
||||
OMPClauseEnqueue(EnqueueVisitor *Visitor) : Visitor(Visitor) { }
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
void Visit##Class(const Class *C);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
};
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { }
|
||||
#define PROCESS_OMP_CLAUSE_LIST(Class, Node) \
|
||||
for (OMPVarList<Class>::varlist_const_iterator I = Node->varlist_begin(), \
|
||||
E = Node->varlist_end(); \
|
||||
I != E; ++I) \
|
||||
Visitor->AddStmt(*I);
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) {
|
||||
PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, C)
|
||||
}
|
||||
#undef PROCESS_OMP_CLAUSE_LIST
|
||||
}
|
||||
void EnqueueVisitor::EnqueueChildren(const OMPClause *S) {
|
||||
unsigned size = WL.size();
|
||||
OMPClauseEnqueue Visitor(this);
|
||||
Visitor.Visit(S);
|
||||
if (size == WL.size())
|
||||
return;
|
||||
// Now reverse the entries we just added. This will match the DFS
|
||||
// ordering performed by the worklist.
|
||||
VisitorWorkList::iterator I = WL.begin() + size, E = WL.end();
|
||||
std::reverse(I, E);
|
||||
}
|
||||
void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) {
|
||||
WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent));
|
||||
}
|
||||
@@ -2189,6 +2226,19 @@ void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
|
||||
Visit(E->getSyntacticForm());
|
||||
}
|
||||
|
||||
void EnqueueVisitor::VisitOMPExecutableDirective(
|
||||
const OMPExecutableDirective *D) {
|
||||
EnqueueChildren(D);
|
||||
for (ArrayRef<OMPClause *>::iterator I = D->clauses().begin(),
|
||||
E = D->clauses().end();
|
||||
I != E; ++I)
|
||||
EnqueueChildren(*I);
|
||||
}
|
||||
|
||||
void EnqueueVisitor::VisitOMPParallelDirective(const OMPParallelDirective *D) {
|
||||
VisitOMPExecutableDirective(D);
|
||||
}
|
||||
|
||||
void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) {
|
||||
EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S);
|
||||
}
|
||||
@@ -3766,6 +3816,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||
return cxstring::createRef("CXXAccessSpecifier");
|
||||
case CXCursor_ModuleImportDecl:
|
||||
return cxstring::createRef("ModuleImport");
|
||||
case CXCursor_OMPParallelDirective:
|
||||
return cxstring::createRef("OMPParallelDirective");
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled CXCursorKind");
|
||||
|
||||
@@ -505,6 +505,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||
case Stmt::MSDependentExistsStmtClass:
|
||||
K = CXCursor_UnexposedStmt;
|
||||
break;
|
||||
case Stmt::OMPParallelDirectiveClass:
|
||||
K = CXCursor_OMPParallelDirective;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
CXCursor C = { K, 0, { Parent, S, TU } };
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/AST/StmtObjC.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
#include "clang/AST/Type.h"
|
||||
@@ -404,6 +405,10 @@ private:
|
||||
bool TraverseDeclContextHelper(DeclContext *DC);
|
||||
bool TraverseFunctionHelper(FunctionDecl *D);
|
||||
bool TraverseVarHelper(VarDecl *D);
|
||||
bool TraverseOMPClause(OMPClause *C);
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
bool Visit##Class(Class *C);
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
|
||||
typedef SmallVector<Stmt *, 16> StmtsTy;
|
||||
typedef SmallVector<StmtsTy *, 4> QueuesTy;
|
||||
@@ -2202,6 +2207,47 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
|
||||
// Traverse OpenCL: AsType, Convert.
|
||||
DEF_TRAVERSE_STMT(AsTypeExpr, { })
|
||||
|
||||
// OpenMP directives.
|
||||
DEF_TRAVERSE_STMT(OMPParallelDirective, {
|
||||
ArrayRef<OMPClause *> Clauses = S->clauses();
|
||||
for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
|
||||
I != E; ++I)
|
||||
if (!TraverseOMPClause(*I)) return false;
|
||||
})
|
||||
|
||||
// OpenMP clauses.
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
|
||||
if (!C) return true;
|
||||
switch (C->getClauseKind()) {
|
||||
#define OPENMP_CLAUSE(Name, Class) \
|
||||
case OMPC_##Name: \
|
||||
return getDerived().Visit##Class(static_cast<Class*>(C));
|
||||
#include "clang/Basic/OpenMPKinds.def"
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define PROCESS_OMP_CLAUSE_LIST(Class, Node) \
|
||||
for (OMPVarList<Class>::varlist_iterator I = Node->varlist_begin(), \
|
||||
E = Node->varlist_end(); \
|
||||
I != E; ++I) \
|
||||
TraverseStmt(*I);
|
||||
|
||||
template<typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
PROCESS_OMP_CLAUSE_LIST(OMPPrivateClause, C)
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef PROCESS_OMP_CLAUSE_LIST
|
||||
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user