OpenMP: basic support for #pragma omp parallel

llvm-svn: 186647
This commit is contained in:
Alexey Bataev
2013-07-19 03:13:43 +00:00
parent 63c5c2a0d8
commit 5ec3eb11fc
34 changed files with 1861 additions and 20 deletions

View File

@@ -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.

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -175,3 +175,7 @@ def MSDependentExistsStmt : Stmt;
// OpenCL Extensions.
def AsTypeExpr : DStmt<Expr>;
// OpenMP Directives.
def OMPExecutableDirective : Stmt<1>;
def OMPParallelDirective : DStmt<OMPExecutableDirective>;

View File

@@ -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,

View File

@@ -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.

View File

@@ -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

View File

@@ -58,3 +58,4 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
Expr **Vars = reinterpret_cast<Expr **>(this + 1);
std::copy(VL.begin(), VL.end(), Vars);
}

View File

@@ -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);
}

View File

@@ -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.
//===----------------------------------------------------------------------===//

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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());
}

View File

@@ -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.

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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
//===----------------------------------------------------------------------===//

View File

@@ -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);

View File

@@ -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
//===----------------------------------------------------------------------===//

View File

@@ -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:

View 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

View 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;
}

View 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;
}

View File

@@ -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

View File

@@ -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:

View File

@@ -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");

View File

@@ -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 } };

View File

@@ -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