[OPENMP 5.0]Add initial support for 'allocate' directive.

Added parsing/sema analysis/serialization/deserialization support for
'allocate' directive.

llvm-svn: 355614
This commit is contained in:
Alexey Bataev 2019-03-07 17:54:44 +00:00
parent 6ca0985aa5
commit 25ed0c07c1
37 changed files with 644 additions and 33 deletions

View File

@ -127,6 +127,11 @@ public:
virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) {}
/// A declaration is marked as a variable with OpenMP allocator.
///
/// \param D the declaration marked as a variable with OpenMP allocator.
virtual void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {}
/// A definition has been made visible by being redefined locally.
///
/// \param D The definition that was previously not visible.

View File

@ -393,6 +393,11 @@ public:
Visit(D->getInit());
}
void VisitOMPAllocateDecl(const OMPAllocateDecl *D) {
for (const auto *E : D->varlists())
Visit(E);
}
template <typename SpecializationDecl>
void dumpTemplateDeclSpecialization(const SpecializationDecl *D) {
for (const auto *RedeclWithBadType : D->redecls()) {

View File

@ -405,6 +405,73 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPRequires; }
};
/// This represents '#pragma omp allocate ...' directive.
/// For example, in the following, the default allocator is used for both 'a'
/// and 'A::b':
///
/// \code
/// int a;
/// #pragma omp allocate(a)
/// struct A {
/// static int b;
/// #pragma omp allocate(b)
/// };
/// \endcode
///
class OMPAllocateDecl final
: public Decl,
private llvm::TrailingObjects<OMPAllocateDecl, Expr *> {
friend class ASTDeclReader;
friend TrailingObjects;
/// Number of variable within the allocate directive.
unsigned NumVars = 0;
virtual void anchor();
OMPAllocateDecl(Kind DK, DeclContext *DC, SourceLocation L)
: Decl(DK, DC, L) {}
ArrayRef<const Expr *> getVars() const {
return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
}
MutableArrayRef<Expr *> getVars() {
return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
}
void setVars(ArrayRef<Expr *> VL);
public:
static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<Expr *> VL);
static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned N);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
typedef llvm::iterator_range<varlist_iterator> varlist_range;
typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
unsigned varlist_size() const { return NumVars; }
bool varlist_empty() const { return NumVars == 0; }
varlist_range varlists() {
return varlist_range(varlist_begin(), varlist_end());
}
varlist_const_range varlists() const {
return varlist_const_range(varlist_begin(), varlist_end());
}
varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_iterator varlist_end() { return getVars().end(); }
varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_const_iterator varlist_end() const { return getVars().end(); }
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == OMPAllocate; }
};
} // end namespace clang
#endif

View File

@ -1613,6 +1613,12 @@ DEF_TRAVERSE_DECL(OMPDeclareMapperDecl, {
DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); })
DEF_TRAVERSE_DECL(OMPAllocateDecl, {
for (auto *I : D->varlists()) {
TRY_TO(TraverseStmt(I));
}
})
// A helper method for TemplateDecl's children.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
@ -2797,6 +2803,7 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) {
break;
#include "clang/Basic/OpenMPKinds.def"
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_uniform:
case OMPC_unknown:
break;

View File

@ -3152,6 +3152,13 @@ def OMPDeclareTargetDecl : InheritableAttr {
}];
}
def OMPAllocateDecl : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
let SemaHandler = 0;
let Documentation = [Undocumented];
}
def InternalLinkage : InheritableAttr {
let Spellings = [Clang<"internal_linkage">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;

View File

@ -98,6 +98,7 @@ def Captured : Decl, DeclContext;
def ClassScopeFunctionSpecialization : Decl;
def Import : Decl;
def OMPThreadPrivate : Decl;
def OMPAllocate : Decl;
def OMPRequires : Decl;
def Empty : Decl;

View File

@ -244,6 +244,7 @@ OPENMP_DIRECTIVE_EXT(target_teams_distribute, "target teams distribute")
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for, "target teams distribute parallel for")
OPENMP_DIRECTIVE_EXT(target_teams_distribute_parallel_for_simd, "target teams distribute parallel for simd")
OPENMP_DIRECTIVE_EXT(target_teams_distribute_simd, "target teams distribute simd")
OPENMP_DIRECTIVE(allocate)
// OpenMP clauses.
OPENMP_CLAUSE(if, OMPIfClause)

View File

@ -35,6 +35,7 @@ enum OpenMPClauseKind {
#include "clang/Basic/OpenMPKinds.def"
OMPC_threadprivate,
OMPC_uniform,
OMPC_allocate,
OMPC_unknown
};

View File

@ -8879,9 +8879,9 @@ public:
// OpenMP directives and clauses.
/// Called on correct id-expression from the '#pragma omp
/// threadprivate'.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope,
CXXScopeSpec &ScopeSpec,
const DeclarationNameInfo &Id);
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec,
const DeclarationNameInfo &Id,
OpenMPDirectiveKind Kind);
/// Called on well-formed '#pragma omp threadprivate'.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
SourceLocation Loc,
@ -8889,6 +8889,10 @@ public:
/// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
ArrayRef<Expr *> VarList);
/// Called on well-formed '#pragma omp allocate'.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
ArrayRef<Expr *> VarList,
DeclContext *Owner = nullptr);
/// Called on well-formed '#pragma omp requires'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
ArrayRef<OMPClause *> ClauseList);

View File

@ -1521,7 +1521,10 @@ namespace serialization {
/// An OMPRequiresDecl record.
DECL_OMP_REQUIRES,
/// An OMPAllocateDcl record.
DECL_OMP_ALLOCATE,
/// An EmptyDecl record.
DECL_EMPTY,

View File

@ -737,6 +737,7 @@ private:
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) override;
void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) override;
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
void AddedAttributeToRecord(const Attr *Attr,
const RecordDecl *Record) override;

View File

@ -9798,12 +9798,12 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
return false;
} else if (isa<PragmaCommentDecl>(D))
return true;
else if (isa<OMPThreadPrivateDecl>(D))
return true;
else if (isa<PragmaDetectMismatchDecl>(D))
return true;
else if (isa<OMPThreadPrivateDecl>(D))
return !D->getDeclContext()->isDependentContext();
else if (isa<OMPAllocateDecl>(D))
return !D->getDeclContext()->isDependentContext();
else if (isa<OMPDeclareReductionDecl>(D))
return !D->getDeclContext()->isDependentContext();
else if (isa<ImportDecl>(D))

View File

@ -812,6 +812,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case ObjCCategoryImpl:
case Import:
case OMPThreadPrivate:
case OMPAllocate:
case OMPRequires:
case OMPCapturedExpr:
case Empty:

View File

@ -52,6 +52,36 @@ void OMPThreadPrivateDecl::setVars(ArrayRef<Expr *> VL) {
std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
}
//===----------------------------------------------------------------------===//
// OMPAllocateDecl Implementation.
//===----------------------------------------------------------------------===//
void OMPAllocateDecl::anchor() { }
OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
ArrayRef<Expr *> VL) {
OMPAllocateDecl *D = new (C, DC, additionalSizeToAlloc<Expr *>(VL.size()))
OMPAllocateDecl(OMPAllocate, DC, L);
D->NumVars = VL.size();
D->setVars(VL);
return D;
}
OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, unsigned ID,
unsigned N) {
OMPAllocateDecl *D = new (C, ID, additionalSizeToAlloc<Expr *>(N))
OMPAllocateDecl(OMPAllocate, nullptr, SourceLocation());
D->NumVars = N;
return D;
}
void OMPAllocateDecl::setVars(ArrayRef<Expr *> VL) {
assert(VL.size() == NumVars &&
"Number of variables is not the same as the preallocated buffer");
std::uninitialized_copy(VL.begin(), VL.end(), getTrailingObjects<Expr *>());
}
//===----------------------------------------------------------------------===//
// OMPRequiresDecl Implementation.
//===----------------------------------------------------------------------===//

View File

@ -99,6 +99,7 @@ namespace {
void VisitUsingDecl(UsingDecl *D);
void VisitUsingShadowDecl(UsingShadowDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPAllocateDecl(OMPAllocateDecl *D);
void VisitOMPRequiresDecl(OMPRequiresDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
@ -424,7 +425,8 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
// FIXME: Need to be able to tell the DeclPrinter when
const char *Terminator = nullptr;
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||
isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D))
isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||
isa<OMPAllocateDecl>(*D))
Terminator = nullptr;
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
Terminator = nullptr;
@ -1546,6 +1548,20 @@ void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
}
}
void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
Out << "#pragma omp allocate";
if (!D->varlist_empty()) {
for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),
E = D->varlist_end();
I != E; ++I) {
Out << (I == D->varlist_begin() ? '(' : ',');
NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
ND->printQualifiedName(Out);
}
Out << ")";
}
}
void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
Out << "#pragma omp requires ";
if (!D->clauselist_empty()) {

View File

@ -84,6 +84,7 @@ const OMPClauseWithPreInit *OMPClauseWithPreInit::get(const OMPClause *C) {
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:
@ -155,6 +156,7 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C)
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:

View File

@ -71,6 +71,8 @@ const char *clang::getOpenMPClauseName(OpenMPClauseKind Kind) {
return "uniform";
case OMPC_threadprivate:
return "threadprivate or thread local";
case OMPC_allocate:
return "allocate";
}
llvm_unreachable("Invalid OpenMP clause kind");
}
@ -147,6 +149,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind,
.Default(OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@ -328,6 +331,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
llvm_unreachable("Invalid OpenMP 'atomic_default_mem_order' clause type");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_if:
case OMPC_final:
case OMPC_num_threads:
@ -810,6 +814,7 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind,
case OMPD_end_declare_target:
case OMPD_unknown:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_section:
case OMPD_master:
case OMPD_taskyield:
@ -1033,6 +1038,7 @@ void clang::getOpenMPCaptureRegions(
CaptureRegions.push_back(OMPD_unknown);
break;
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:

View File

@ -103,6 +103,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::Label: // __label__ x;
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPAllocate:
case Decl::OMPCapturedExpr:
case Decl::OMPRequires:
case Decl::Empty:

View File

@ -8215,6 +8215,7 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:
@ -8638,6 +8639,7 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:
@ -9156,6 +9158,7 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:

View File

@ -743,7 +743,7 @@ static const Stmt *getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body) {
isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
isa<UsingDirectiveDecl>(D) ||
isa<OMPDeclareReductionDecl>(D) ||
isa<OMPThreadPrivateDecl>(D))
isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
return true;
const auto *VD = dyn_cast<VarDecl>(D);
if (!VD)
@ -835,6 +835,7 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:
@ -904,6 +905,7 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx,
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:
@ -1055,6 +1057,7 @@ static bool hasNestedLightweightDirective(ASTContext &Ctx,
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:
@ -1129,6 +1132,7 @@ static bool supportsLightweightRuntime(ASTContext &Ctx,
case OMPD_cancellation_point:
case OMPD_ordered:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
case OMPD_simd:
case OMPD_sections:

View File

@ -3963,6 +3963,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_nowait:
case OMPC_untied:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_depend:
case OMPC_mergeable:
case OMPC_device:

View File

@ -5062,6 +5062,9 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitOMPThreadPrivateDecl(cast<OMPThreadPrivateDecl>(D));
break;
case Decl::OMPAllocate:
break;
case Decl::OMPDeclareReduction:
EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(D));
break;

View File

@ -103,6 +103,7 @@ public:
const ObjCInterfaceDecl *IFD) override;
void DeclarationMarkedUsed(const Decl *D) override;
void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) override;
void DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) override;
void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override;
@ -208,6 +209,11 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate(
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
}
void MultiplexASTMutationListener::DeclarationMarkedOpenMPAllocate(
const Decl *D, const Attr *A) {
for (ASTMutationListener *L : Listeners)
L->DeclarationMarkedOpenMPAllocate(D, A);
}
void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget(
const Decl *D, const Attr *Attr) {
for (auto *L : Listeners)

View File

@ -1734,7 +1734,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
/// [C++11] attribute-specifier-seq decl-specifier-seq[opt]
/// init-declarator-list ';'
///[C90/C++]init-declarator-list ';' [TODO]
/// [OMP] threadprivate-directive [TODO]
/// [OMP] threadprivate-directive
/// [OMP] allocate-directive [TODO]
///
/// for-range-declaration: [C++11 6.5p1: stmt.ranged]
/// attribute-specifier-seq[opt] type-specifier-seq declarator

View File

@ -44,15 +44,17 @@ enum OpenMPDirectiveKindEx {
OMPD_mapper,
};
class ThreadprivateListParserHelper final {
class DeclDirectiveListParserHelper final {
SmallVector<Expr *, 4> Identifiers;
Parser *P;
OpenMPDirectiveKind Kind;
public:
ThreadprivateListParserHelper(Parser *P) : P(P) {}
DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
: P(P), Kind(Kind) {}
void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
ExprResult Res =
P->getActions().ActOnOpenMPIdExpression(P->getCurScope(), SS, NameInfo);
ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
P->getCurScope(), SS, NameInfo, Kind);
if (Res.isUsable())
Identifiers.push_back(Res.get());
}
@ -839,6 +841,10 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
/// annot_pragma_openmp 'threadprivate' simple-variable-list
/// annot_pragma_openmp_end
///
/// allocate-directive:
/// annot_pragma_openmp 'allocate' simple-variable-list
/// annot_pragma_openmp_end
///
/// declare-reduction-directive:
/// annot_pragma_openmp 'declare' 'reduction' [...]
/// annot_pragma_openmp_end
@ -869,13 +875,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
switch (DKind) {
case OMPD_threadprivate: {
ConsumeToken();
ThreadprivateListParserHelper Helper(this);
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, true)) {
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/true)) {
// 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);
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
// Skip the last annot_pragma_openmp_end.
@ -885,6 +892,24 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
}
break;
}
case OMPD_allocate: {
ConsumeToken();
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/true)) {
// 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(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
// Skip the last annot_pragma_openmp_end.
ConsumeAnnotationToken();
return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers());
}
break;
}
case OMPD_requires: {
SourceLocation StartLoc = ConsumeToken();
SmallVector<OMPClause *, 5> Clauses;
@ -1098,6 +1123,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// annot_pragma_openmp 'threadprivate' simple-variable-list
/// annot_pragma_openmp_end
///
/// allocate-directive:
/// annot_pragma_openmp 'allocate' simple-variable-list
/// annot_pragma_openmp_end
///
/// declare-reduction-directive:
/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
/// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
@ -1157,13 +1186,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
<< getOpenMPDirectiveName(DKind) << 0;
}
ConsumeToken();
ThreadprivateListParserHelper Helper(this);
if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper, false)) {
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/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);
<< getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
@ -1173,6 +1203,31 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
SkipUntil(tok::annot_pragma_openmp_end);
break;
}
case OMPD_allocate: {
// FIXME: Should this be permitted in C++?
if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
}
ConsumeToken();
DeclDirectiveListParserHelper Helper(this, DKind);
if (!ParseOpenMPSimpleVarList(DKind, Helper,
/*AllowScopeSpecifier=*/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(DKind);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
}
DeclGroupPtrTy Res =
Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers());
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
}
SkipUntil(tok::annot_pragma_openmp_end);
break;
}
case OMPD_declare_reduction:
ConsumeToken();
if (DeclGroupPtrTy Res =
@ -1602,6 +1657,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_uniform:
if (!WrongDirective)
Diag(Tok, diag::err_omp_unexpected_clause)

View File

@ -913,7 +913,8 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) {
/// declaration: [C99 6.7]
/// declaration-specifiers init-declarator-list[opt] ';'
/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
/// [OMP] threadprivate-directive [TODO]
/// [OMP] threadprivate-directive
/// [OMP] allocate-directive [TODO]
///
Parser::DeclGroupPtrTy
Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs,

View File

@ -1908,7 +1908,8 @@ public:
explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
if (ND && (isa<VarDecl>(ND) || isa<FunctionDecl>(ND))) {
if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
isa<FunctionDecl>(ND))) {
return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
SemaRef.getCurScope());
}
@ -1920,7 +1921,8 @@ public:
ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
CXXScopeSpec &ScopeSpec,
const DeclarationNameInfo &Id) {
const DeclarationNameInfo &Id,
OpenMPDirectiveKind Kind) {
LookupResult Lookup(*this, Id, LookupOrdinaryName);
LookupParsedName(Lookup, CurScope, &ScopeSpec, true);
@ -1953,9 +1955,9 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// OpenMP [2.9.2, Syntax, C/C++]
// Variables must be file-scope, namespace-scope, or static block-scope.
if (!VD->hasGlobalStorage()) {
if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
Diag(Id.getLoc(), diag::err_omp_global_var_arg)
<< getOpenMPDirectiveName(OMPD_threadprivate) << !VD->isStaticLocal();
<< getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@ -1972,7 +1974,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
!getCurLexicalContext()->isTranslationUnit()) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
<< getOpenMPDirectiveName(Kind) << VD;
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@ -1987,7 +1989,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
if (CanonicalVD->isStaticDataMember() &&
!CanonicalVD->getDeclContext()->Equals(getCurLexicalContext())) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
<< getOpenMPDirectiveName(Kind) << VD;
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@ -2003,7 +2005,7 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
(!getCurLexicalContext()->isFileContext() ||
!getCurLexicalContext()->Encloses(CanonicalVD->getDeclContext()))) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
<< getOpenMPDirectiveName(Kind) << VD;
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@ -2014,10 +2016,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// OpenMP [2.9.2, Restrictions, C/C++, p.6]
// A threadprivate directive for static block-scope variables must appear
// in the scope of the variable and not in a nested scope.
if (CanonicalVD->isStaticLocal() && CurScope &&
if (CanonicalVD->isLocalVarDecl() && CurScope &&
!isDeclInScope(ND, getCurLexicalContext(), CurScope)) {
Diag(Id.getLoc(), diag::err_omp_var_scope)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
<< getOpenMPDirectiveName(Kind) << VD;
bool IsDecl =
VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
Diag(VD->getLocation(),
@ -2029,9 +2031,10 @@ ExprResult Sema::ActOnOpenMPIdExpression(Scope *CurScope,
// OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
// A threadprivate directive must lexically precede all references to any
// of the variables in its list.
if (VD->isUsed() && !DSAStack->isThreadPrivate(VD)) {
if (Kind == OMPD_threadprivate && VD->isUsed() &&
!DSAStack->isThreadPrivate(VD)) {
Diag(Id.getLoc(), diag::err_omp_var_used)
<< getOpenMPDirectiveName(OMPD_threadprivate) << VD;
<< getOpenMPDirectiveName(Kind) << VD;
return ExprError();
}
@ -2163,6 +2166,41 @@ Sema::CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef<Expr *> VarList) {
return D;
}
Sema::DeclGroupPtrTy
Sema::ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef<Expr *> VarList,
DeclContext *Owner) {
SmallVector<Expr *, 8> Vars;
for (Expr *RefExpr : VarList) {
auto *DE = cast<DeclRefExpr>(RefExpr);
auto *VD = cast<VarDecl>(DE->getDecl());
// Check if this is a TLS variable or global register.
if (VD->getTLSKind() != VarDecl::TLS_None ||
VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
(VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
!VD->isLocalVarDecl()))
continue;
// Do not apply for parameters.
if (isa<ParmVarDecl>(VD))
continue;
Vars.push_back(RefExpr);
VD->addAttr(
OMPAllocateDeclAttr::CreateImplicit(Context, DE->getSourceRange()));
if (ASTMutationListener *ML = Context.getASTMutationListener())
ML->DeclarationMarkedOpenMPAllocate(VD,
VD->getAttr<OMPAllocateDeclAttr>());
}
if (Vars.empty())
return nullptr;
if (!Owner)
Owner = getCurLexicalContext();
OMPAllocateDecl *D = OMPAllocateDecl::Create(Context, Owner, Loc, Vars);
D->setAccess(AS_public);
Owner->addDecl(D);
return DeclGroupPtrTy::make(DeclGroupRef(D));
}
Sema::DeclGroupPtrTy
Sema::ActOnOpenMPRequiresDirective(SourceLocation Loc,
ArrayRef<OMPClause *> ClauseList) {
@ -2863,6 +2901,7 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) {
break;
}
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -3719,6 +3758,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
case OMPD_declare_target:
case OMPD_end_declare_target:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_declare_reduction:
case OMPD_declare_mapper:
case OMPD_declare_simd:
@ -8398,6 +8438,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:
@ -8482,6 +8523,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
// Do not capture if-clause expressions.
break;
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8549,6 +8591,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_taskloop:
case OMPD_taskloop_simd:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8617,6 +8660,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8682,6 +8726,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_target_parallel_for:
case OMPD_target_parallel_for_simd:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8748,6 +8793,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_parallel:
case OMPD_parallel_sections:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8813,6 +8859,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_parallel:
case OMPD_parallel_sections:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8877,6 +8924,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_taskyield:
case OMPD_barrier:
case OMPD_taskwait:
@ -8928,6 +8976,7 @@ static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:
@ -9251,6 +9300,7 @@ OMPClause *Sema::ActOnOpenMPSimpleClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:
@ -9428,6 +9478,7 @@ OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_read:
case OMPC_write:
@ -9645,6 +9696,7 @@ OMPClause *Sema::ActOnOpenMPClause(OpenMPClauseKind Kind,
case OMPC_default:
case OMPC_proc_bind:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_flush:
case OMPC_depend:
case OMPC_device:
@ -9841,6 +9893,7 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
case OMPC_untied:
case OMPC_mergeable:
case OMPC_threadprivate:
case OMPC_allocate:
case OMPC_read:
case OMPC_write:
case OMPC_update:

View File

@ -2876,6 +2876,21 @@ Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
return TD;
}
Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
SmallVector<Expr *, 5> Vars;
for (auto *I : D->varlists()) {
Expr *Var = SemaRef.SubstExpr(I, TemplateArgs).get();
assert(isa<DeclRefExpr>(Var) && "allocate arg is not a DeclRefExpr");
Vars.push_back(Var);
}
Sema::DeclGroupPtrTy Res =
SemaRef.ActOnOpenMPAllocateDirective(D->getLocation(), Vars, Owner);
if (Res.get().isNull())
return nullptr;
return Res.get().getSingleDecl();
}
Decl *TemplateDeclInstantiator::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
llvm_unreachable(
"Requires directive cannot be instantiated within a dependent context");

View File

@ -387,6 +387,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPAllocate:
case Decl::OMPRequires:
case Decl::OMPCapturedExpr:
case Decl::OMPDeclareReduction:

View File

@ -38,6 +38,7 @@ enum DeclUpdateKind {
UPD_MANGLING_NUMBER,
UPD_STATIC_LOCAL_NUMBER,
UPD_DECL_MARKED_OPENMP_THREADPRIVATE,
UPD_DECL_MARKED_OPENMP_ALLOCATE,
UPD_DECL_MARKED_OPENMP_DECLARETARGET,
UPD_DECL_EXPORTED,
UPD_ADDED_ATTR_TO_RECORD

View File

@ -444,6 +444,7 @@ namespace clang {
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPAllocateDecl(OMPAllocateDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
void VisitOMPRequiresDecl(OMPRequiresDecl *D);
@ -2633,6 +2634,17 @@ void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
D->setVars(Vars);
}
void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
VisitDecl(D);
unsigned NumVars = D->varlist_size();
SmallVector<Expr *, 16> Vars;
Vars.reserve(NumVars);
for (unsigned i = 0; i != NumVars; ++i) {
Vars.push_back(Record.readExpr());
}
D->setVars(Vars);
}
void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) {
VisitDecl(D);
unsigned NumClauses = D->clauselist_size();
@ -2795,7 +2807,7 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
isa<PragmaDetectMismatchDecl>(D))
return true;
if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) ||
isa<OMPDeclareMapperDecl>(D))
isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D))
return !D->getDeclContext()->isFunctionOrMethod();
if (const auto *Var = dyn_cast<VarDecl>(D))
return Var->isFileVarDecl() &&
@ -3866,6 +3878,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_OMP_THREADPRIVATE:
D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_OMP_ALLOCATE:
D = OMPAllocateDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
case DECL_OMP_REQUIRES:
D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
break;
@ -4465,6 +4480,11 @@ void ASTDeclReader::UpdateDecl(Decl *D,
ReadSourceRange()));
break;
case UPD_DECL_MARKED_OPENMP_ALLOCATE:
D->addAttr(OMPAllocateDeclAttr::CreateImplicit(Reader.getContext(),
ReadSourceRange()));
break;
case UPD_DECL_EXPORTED: {
unsigned SubmoduleID = readSubmoduleID();
auto *Exported = cast<NamedDecl>(D);

View File

@ -1298,6 +1298,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_PRAGMA_COMMENT);
RECORD(DECL_PRAGMA_DETECT_MISMATCH);
RECORD(DECL_OMP_DECLARE_REDUCTION);
RECORD(DECL_OMP_ALLOCATE);
// Statements and Exprs can occur in the Decls and Types block.
AddStmtsExprs(Stream, Record);
@ -5287,6 +5288,10 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
D->getAttr<OMPThreadPrivateDeclAttr>()->getRange());
break;
case UPD_DECL_MARKED_OPENMP_ALLOCATE:
Record.AddSourceRange(D->getAttr<OMPAllocateDeclAttr>()->getRange());
break;
case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType());
Record.AddSourceRange(
@ -6404,6 +6409,15 @@ void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));
}
void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {
if (Chain && Chain->isProcessingUpdateRecords()) return;
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
return;
DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_ALLOCATE, A));
}
void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
const Attr *Attr) {
if (Chain && Chain->isProcessingUpdateRecords()) return;

View File

@ -144,6 +144,7 @@ namespace clang {
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
void VisitOMPAllocateDecl(OMPAllocateDecl *D);
void VisitOMPRequiresDecl(OMPRequiresDecl *D);
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
@ -1744,10 +1745,18 @@ void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
Code = serialization::DECL_OMP_THREADPRIVATE;
}
void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
Record.push_back(D->varlist_size());
VisitDecl(D);
for (auto *I : D->varlists())
Record.AddStmt(I);
Code = serialization::DECL_OMP_ALLOCATE;
}
void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
Record.push_back(D->clauselist_size());
VisitDecl(D);
OMPClauseWriter ClauseWriter(Record);
OMPClauseWriter ClauseWriter(Record);
for (OMPClause *C : D->clauselists())
ClauseWriter.writeClause(C);
Code = serialization::DECL_OMP_REQUIRES;

View File

@ -0,0 +1,79 @@
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -triple x86_64-apple-darwin10.6.0 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -fnoopenmp-use-tls -triple x86_64-unknown-linux-gnu -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
struct St{
int a;
};
struct St1{
int a;
static int b;
// CHECK: static int b;
#pragma omp allocate(b)
// CHECK-NEXT: #pragma omp allocate(St1::b){{$}}
} d;
int a, b;
// CHECK: int a;
// CHECK: int b;
#pragma omp allocate(a)
#pragma omp allocate(a)
// CHECK-NEXT: #pragma omp allocate(a)
// CHECK-NEXT: #pragma omp allocate(a)
#pragma omp allocate(d, b)
// CHECK-NEXT: #pragma omp allocate(d,b)
template <class T>
struct ST {
static T m;
#pragma omp allocate(m)
};
template <class T> T foo() {
T v;
#pragma omp allocate(v)
v = ST<T>::m;
return v;
}
//CHECK: template <class T> T foo() {
//CHECK-NEXT: T v;
//CHECK-NEXT: #pragma omp allocate(v)
//CHECK: template<> int foo<int>() {
//CHECK-NEXT: int v;
//CHECK-NEXT: #pragma omp allocate(v)
namespace ns{
int a;
}
// CHECK: namespace ns {
// CHECK-NEXT: int a;
// CHECK-NEXT: }
#pragma omp allocate(ns::a)
// CHECK-NEXT: #pragma omp allocate(ns::a)
int main () {
static int a;
// CHECK: static int a;
#pragma omp allocate(a)
// CHECK-NEXT: #pragma omp allocate(a)
a=2;
return (foo<int>());
}
extern template int ST<int>::m;
#endif

View File

@ -0,0 +1,149 @@
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp -ferror-limit 100 -emit-llvm -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -fnoopenmp-use-tls -ferror-limit 100 -emit-llvm -o - %s
// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify -fopenmp-simd -ferror-limit 100 -emit-llvm -o - %s
#pragma omp allocate // expected-error {{expected '(' after 'allocate'}}
#pragma omp allocate( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp allocate() // expected-error {{expected identifier}}
#pragma omp allocate(1) // expected-error {{expected unqualified-id}}
struct CompleteSt {
int a;
};
struct CompleteSt1 {
#pragma omp allocate(1) // expected-error {{expected unqualified-id}}
int a;
} d; // expected-note {{'d' defined here}}
int a; // expected-note {{'a' defined here}}
#pragma omp allocate(a)
#pragma omp allocate(u) // expected-error {{use of undeclared identifier 'u'}}
#pragma omp allocate(d, a)
int foo() { // expected-note {{declared here}}
static int l;
#pragma omp allocate(l)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
return (a);
}
#pragma omp allocate(a)(
// expected-warning@-1 {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a)[ // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a) { // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a)] // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a) } // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate a // expected-error {{expected '(' after 'allocate'}}
#pragma omp allocate(d // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp allocate(d)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
int x, y;
#pragma omp allocate(x)) // expected-warning {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(y)),
// expected-warning@-1 {{extra tokens at the end of '#pragma omp allocate' are ignored}}
#pragma omp allocate(a, d)
#pragma omp allocate(d.a) // expected-error {{expected identifier}}
#pragma omp allocate((float)a) // expected-error {{expected unqualified-id}}
int foa; // expected-note {{'foa' declared here}}
#pragma omp allocate(faa) // expected-error {{use of undeclared identifier 'faa'; did you mean 'foa'?}}
#pragma omp allocate(foo) // expected-error {{'foo' is not a global variable, static local variable or static data member}}
#pragma omp allocate(int a = 2) // expected-error {{expected unqualified-id}}
struct IncompleteSt;
extern IncompleteSt e;
#pragma omp allocate(e)
int &f = a;
#pragma omp allocate(f)
class TestClass {
private:
int a; // expected-note {{declared here}}
static int b; // expected-note {{'b' declared here}}
TestClass() : a(0) {}
public:
TestClass(int aaa) : a(aaa) {}
#pragma omp allocate(b, a) // expected-error {{'a' is not a global variable, static local variable or static data member}}
} g(10);
#pragma omp allocate(b) // expected-error {{use of undeclared identifier 'b'}}
#pragma omp allocate(TestClass::b) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'TestClass::b' variable declaration}}
#pragma omp allocate(g)
namespace ns {
int m;
#pragma omp allocate(m, m)
} // namespace ns
#pragma omp allocate(m) // expected-error {{use of undeclared identifier 'm'}}
#pragma omp allocate(ns::m)
#pragma omp allocate(ns \
: m) // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}}
const int h = 12;
const volatile int i = 10;
#pragma omp allocate(h, i)
template <class T>
class TempClass {
private:
T a;
TempClass() : a() {}
public:
TempClass(T aaa) : a(aaa) {}
static T s;
#pragma omp allocate(s)
};
#pragma omp allocate(s) // expected-error {{use of undeclared identifier 's'}}
static __thread int t;
#pragma omp allocate(t)
// Register "0" is currently an invalid register for global register variables.
// Use "esp" instead of "0".
// register int reg0 __asm__("0");
register int reg0 __asm__("esp");
#pragma omp allocate(reg0)
int o; // expected-note {{candidate found by name lookup is 'o'}}
#pragma omp allocate(o)
namespace {
int o; // expected-note {{candidate found by name lookup is '(anonymous namespace)::o'}}
#pragma omp allocate(o)
#pragma omp allocate(o)
} // namespace
#pragma omp allocate(o) // expected-error {{reference to 'o' is ambiguous}}
#pragma omp allocate(::o)
int main(int argc, char **argv) {
int x, y = argc;
static double d1;
static double d2;
static double d3; // expected-note {{'d3' defined here}}
static double d4;
static TestClass LocalClass(y);
#pragma omp allocate(LocalClass)
d.a = a;
d2++;
;
#pragma omp allocate(argc + y) // expected-error {{expected identifier}}
#pragma omp allocate(argc, y)
#pragma omp allocate(d2)
#pragma omp allocate(d1)
{
++a;
d2 = 0;
#pragma omp allocate(d3) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'd3' variable declaration}}
}
#pragma omp allocate(d3)
label:
#pragma omp allocate(d4) // expected-error {{'#pragma omp allocate' cannot be an immediate substatement}}
#pragma omp allocate(a) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'a' variable declaration}}
return (y);
#pragma omp allocate(d) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'd' variable declaration}}
}

View File

@ -0,0 +1,36 @@
// no PCH
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -ast-print -include %s -include %s %s -o - | FileCheck %s
// with PCH
// RUN: %clang_cc1 -fopenmp -fnoopenmp-use-tls -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s
// no PCH
// RUN: %clang_cc1 -fopenmp -ast-print -include %s -include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-1
// RUN: %clang_cc1 -fopenmp -ast-print -include %s -include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-2
// with PCH
// RUN: %clang_cc1 -fopenmp -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-1
// RUN: %clang_cc1 -fopenmp -ast-print -chain-include %s -chain-include %s %s -o - | FileCheck %s -check-prefix=CHECK-ALLOC-2
#if !defined(PASS1)
#define PASS1
int a;
// CHECK: int a;
#elif !defined(PASS2)
#define PASS2
#pragma omp allocate(a)
// CHECK: #pragma omp allocate(a)
#else
// CHECK-LABEL: foo
// CHECK-ALLOC-LABEL: foo
int foo() {
return a;
// CHECK: return a;
// CHECK-ALLOC-1: return a;
}
// CHECK-ALLOC-2: return a;
#endif

View File

@ -6233,6 +6233,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::CXXDeductionGuide:
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPAllocate:
case Decl::OMPDeclareReduction:
case Decl::OMPDeclareMapper:
case Decl::OMPRequires: