forked from OSchip/llvm-project
Initial parsing/sema for 'align' clause
Added basic parsing/sema/serialization support for 'align' clause for use with 'allocate' directive.
This commit is contained in:
parent
b702276ad0
commit
b0de656bdf
|
@ -322,6 +322,81 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// This represents the 'align' clause in the '#pragma omp allocate'
|
||||
/// directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp allocate(a) allocator(omp_default_mem_alloc) align(8)
|
||||
/// \endcode
|
||||
/// In this example directive '#pragma omp allocate' has simple 'allocator'
|
||||
/// clause with the allocator 'omp_default_mem_alloc' and align clause with
|
||||
/// value of 8.
|
||||
class OMPAlignClause final : public OMPClause {
|
||||
friend class OMPClauseReader;
|
||||
|
||||
/// Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
/// Alignment specified with align clause.
|
||||
Stmt *Alignment = nullptr;
|
||||
|
||||
/// Set alignment value.
|
||||
void setAlignment(Expr *A) { Alignment = A; }
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
|
||||
/// Build 'align' clause with the given alignment
|
||||
///
|
||||
/// \param A Alignment value.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
OMPAlignClause(Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc)
|
||||
: OMPClause(llvm::omp::OMPC_align, StartLoc, EndLoc),
|
||||
LParenLoc(LParenLoc), Alignment(A) {}
|
||||
|
||||
/// Build an empty clause.
|
||||
OMPAlignClause()
|
||||
: OMPClause(llvm::omp::OMPC_align, SourceLocation(), SourceLocation()) {}
|
||||
|
||||
public:
|
||||
/// Build 'align' clause with the given alignment
|
||||
///
|
||||
/// \param A Alignment value.
|
||||
/// \param StartLoc Starting location of the clause.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Ending location of the clause.
|
||||
static OMPAlignClause *Create(const ASTContext &C, Expr *A,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
|
||||
/// Returns the location of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// Returns alignment
|
||||
Expr *getAlignment() const { return cast_or_null<Expr>(Alignment); }
|
||||
|
||||
child_range children() { return child_range(&Alignment, &Alignment + 1); }
|
||||
|
||||
const_child_range children() const {
|
||||
return const_child_range(&Alignment, &Alignment + 1);
|
||||
}
|
||||
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == llvm::omp::OMPC_align;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents clause 'allocate' in the '#pragma omp ...' directives.
|
||||
///
|
||||
/// \code
|
||||
|
|
|
@ -3093,6 +3093,12 @@ RecursiveASTVisitor<Derived>::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPAlignClause(OMPAlignClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getAlignment()));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPSafelenClause(OMPSafelenClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getSafelen()));
|
||||
|
|
|
@ -3683,7 +3683,8 @@ def OMPAllocateDecl : InheritableAttr {
|
|||
"OMPCGroupMemAlloc", "OMPPTeamMemAlloc", "OMPThreadMemAlloc",
|
||||
"OMPUserDefinedMemAlloc"
|
||||
]>,
|
||||
ExprArgument<"Allocator">
|
||||
ExprArgument<"Allocator">,
|
||||
ExprArgument<"Alignment">
|
||||
];
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
|
|
@ -11034,6 +11034,10 @@ public:
|
|||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed 'align' clause.
|
||||
OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed 'safelen' clause.
|
||||
OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
|
||||
SourceLocation StartLoc,
|
||||
|
|
|
@ -1662,10 +1662,11 @@ void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
|
|||
Out << ")";
|
||||
}
|
||||
if (!D->clauselist_empty()) {
|
||||
Out << " ";
|
||||
OMPClausePrinter Printer(Out, Policy);
|
||||
for (OMPClause *C : D->clauselists())
|
||||
for (OMPClause *C : D->clauselists()) {
|
||||
Out << " ";
|
||||
Printer.Visit(C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -629,6 +629,13 @@ OMPAlignedClause *OMPAlignedClause::CreateEmpty(const ASTContext &C,
|
|||
return new (Mem) OMPAlignedClause(NumVars);
|
||||
}
|
||||
|
||||
OMPAlignClause *OMPAlignClause::Create(const ASTContext &C, Expr *A,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return new (C) OMPAlignClause(A, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
void OMPCopyinClause::setSourceExprs(ArrayRef<Expr *> SrcExprs) {
|
||||
assert(SrcExprs.size() == varlist_size() && "Number of source expressions is "
|
||||
"not the same as the "
|
||||
|
@ -1622,6 +1629,12 @@ void OMPClausePrinter::VisitOMPNumThreadsClause(OMPNumThreadsClause *Node) {
|
|||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPAlignClause(OMPAlignClause *Node) {
|
||||
OS << "align(";
|
||||
Node->getAlignment()->printPretty(OS, nullptr, Policy, 0);
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPSafelenClause(OMPSafelenClause *Node) {
|
||||
OS << "safelen(";
|
||||
Node->getSafelen()->printPretty(OS, nullptr, Policy, 0);
|
||||
|
|
|
@ -452,6 +452,11 @@ void OMPClauseProfiler::VisitOMPNumThreadsClause(const OMPNumThreadsClause *C) {
|
|||
Profiler->VisitStmt(C->getNumThreads());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPAlignClause(const OMPAlignClause *C) {
|
||||
if (C->getAlignment())
|
||||
Profiler->VisitStmt(C->getAlignment());
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPSafelenClause(const OMPSafelenClause *C) {
|
||||
if (C->getSafelen())
|
||||
Profiler->VisitStmt(C->getSafelen());
|
||||
|
|
|
@ -5993,6 +5993,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
|
|||
case OMPC_append_args:
|
||||
case OMPC_memory_order:
|
||||
case OMPC_bind:
|
||||
case OMPC_align:
|
||||
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3105,6 +3105,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|||
case OMPC_nocontext:
|
||||
case OMPC_filter:
|
||||
case OMPC_partial:
|
||||
case OMPC_align:
|
||||
// OpenMP [2.5, Restrictions]
|
||||
// At most one num_threads clause can appear on the directive.
|
||||
// OpenMP [2.8.1, simd construct, Restrictions]
|
||||
|
@ -3362,6 +3363,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
|
|||
/// detach-clause:
|
||||
/// 'detach' '(' event-handler-expression ')'
|
||||
///
|
||||
/// align-clause
|
||||
/// 'align' '(' positive-integer-constant ')'
|
||||
///
|
||||
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
||||
bool ParseOnly) {
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
|
|
|
@ -3130,16 +3130,22 @@ static bool checkPreviousOMPAllocateAttribute(
|
|||
static void
|
||||
applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
|
||||
OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
|
||||
Expr *Allocator, SourceRange SR) {
|
||||
Expr *Allocator, Expr *Alignment, SourceRange SR) {
|
||||
if (VD->hasAttr<OMPAllocateDeclAttr>())
|
||||
return;
|
||||
if (Alignment &&
|
||||
(Alignment->isTypeDependent() || Alignment->isValueDependent() ||
|
||||
Alignment->isInstantiationDependent() ||
|
||||
Alignment->containsUnexpandedParameterPack()))
|
||||
// Apply later when we have a usable value.
|
||||
return;
|
||||
if (Allocator &&
|
||||
(Allocator->isTypeDependent() || Allocator->isValueDependent() ||
|
||||
Allocator->isInstantiationDependent() ||
|
||||
Allocator->containsUnexpandedParameterPack()))
|
||||
return;
|
||||
auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
|
||||
Allocator, SR);
|
||||
Allocator, Alignment, SR);
|
||||
VD->addAttr(A);
|
||||
if (ASTMutationListener *ML = S.Context.getASTMutationListener())
|
||||
ML->DeclarationMarkedOpenMPAllocate(VD, A);
|
||||
|
@ -3148,7 +3154,8 @@ applyOMPAllocateAttribute(Sema &S, VarDecl *VD,
|
|||
Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective(
|
||||
SourceLocation Loc, ArrayRef<Expr *> VarList,
|
||||
ArrayRef<OMPClause *> Clauses, DeclContext *Owner) {
|
||||
assert(Clauses.size() <= 1 && "Expected at most one clause.");
|
||||
assert(Clauses.size() <= 2 && "Expected at most two clauses.");
|
||||
Expr *Alignment = nullptr;
|
||||
Expr *Allocator = nullptr;
|
||||
if (Clauses.empty()) {
|
||||
// OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
|
||||
|
@ -3159,7 +3166,13 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective(
|
|||
!DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
|
||||
targetDiag(Loc, diag::err_expected_allocator_clause);
|
||||
} else {
|
||||
Allocator = cast<OMPAllocatorClause>(Clauses.back())->getAllocator();
|
||||
for (const OMPClause *C : Clauses)
|
||||
if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
|
||||
Allocator = AC->getAllocator();
|
||||
else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
|
||||
Alignment = AC->getAlignment();
|
||||
else
|
||||
llvm_unreachable("Unexpected clause on allocate directive");
|
||||
}
|
||||
OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
|
||||
getAllocatorKind(*this, DSAStack, Allocator);
|
||||
|
@ -3200,7 +3213,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective(
|
|||
}
|
||||
|
||||
Vars.push_back(RefExpr);
|
||||
applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator,
|
||||
applyOMPAllocateAttribute(*this, VD, AllocatorKind, Allocator, Alignment,
|
||||
DE->getSourceRange());
|
||||
}
|
||||
if (Vars.empty())
|
||||
|
@ -5228,8 +5241,10 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
|
|||
if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
|
||||
AllocatorKind, AC->getAllocator()))
|
||||
continue;
|
||||
// Placeholder until allocate clause supports align modifier.
|
||||
Expr *Alignment = nullptr;
|
||||
applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
|
||||
E->getSourceRange());
|
||||
Alignment, E->getSourceRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13415,6 +13430,9 @@ OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
|
|||
case OMPC_partial:
|
||||
Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_align:
|
||||
Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
|
||||
break;
|
||||
case OMPC_device:
|
||||
case OMPC_if:
|
||||
case OMPC_default:
|
||||
|
@ -14528,7 +14546,7 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
|
|||
<< E->getSourceRange();
|
||||
return ExprError();
|
||||
}
|
||||
if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
|
||||
if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
|
||||
Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
|
||||
<< E->getSourceRange();
|
||||
return ExprError();
|
||||
|
@ -14953,6 +14971,17 @@ OMPClause *Sema::ActOnOpenMPPartialClause(Expr *FactorExpr,
|
|||
FactorExpr);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPAlignClause(Expr *A, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
ExprResult AlignVal;
|
||||
AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
|
||||
if (AlignVal.isInvalid())
|
||||
return nullptr;
|
||||
return OMPAlignClause::Create(Context, AlignVal.get(), StartLoc, LParenLoc,
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *Sema::ActOnOpenMPSingleExprWithArgClause(
|
||||
OpenMPClauseKind Kind, ArrayRef<unsigned> Argument, Expr *Expr,
|
||||
SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
|
|
|
@ -3371,12 +3371,23 @@ Decl *TemplateDeclInstantiator::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
|
|||
SmallVector<OMPClause *, 4> Clauses;
|
||||
// Copy map clauses from the original mapper.
|
||||
for (OMPClause *C : D->clauselists()) {
|
||||
auto *AC = cast<OMPAllocatorClause>(C);
|
||||
ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs);
|
||||
if (!NewE.isUsable())
|
||||
continue;
|
||||
OMPClause *IC = SemaRef.ActOnOpenMPAllocatorClause(
|
||||
NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc());
|
||||
OMPClause *IC = nullptr;
|
||||
if (auto *AC = dyn_cast<OMPAllocatorClause>(C)) {
|
||||
ExprResult NewE = SemaRef.SubstExpr(AC->getAllocator(), TemplateArgs);
|
||||
if (!NewE.isUsable())
|
||||
continue;
|
||||
IC = SemaRef.ActOnOpenMPAllocatorClause(
|
||||
NewE.get(), AC->getBeginLoc(), AC->getLParenLoc(), AC->getEndLoc());
|
||||
} else if (auto *AC = dyn_cast<OMPAlignClause>(C)) {
|
||||
ExprResult NewE = SemaRef.SubstExpr(AC->getAlignment(), TemplateArgs);
|
||||
if (!NewE.isUsable())
|
||||
continue;
|
||||
IC = SemaRef.ActOnOpenMPAlignClause(NewE.get(), AC->getBeginLoc(),
|
||||
AC->getLParenLoc(), AC->getEndLoc());
|
||||
// If align clause value ends up being invalid, this can end up null.
|
||||
if (!IC)
|
||||
continue;
|
||||
}
|
||||
Clauses.push_back(IC);
|
||||
}
|
||||
|
||||
|
|
|
@ -2269,6 +2269,16 @@ public:
|
|||
EndLoc);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'align' clause.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new OpenMP clause.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
OMPClause *RebuildOMPAlignClause(Expr *A, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc) {
|
||||
return getSema().ActOnOpenMPAlignClause(A, StartLoc, LParenLoc, EndLoc);
|
||||
}
|
||||
|
||||
/// Rebuild the operand to an Objective-C \@synchronized statement.
|
||||
///
|
||||
/// By default, performs semantic analysis to build the new statement.
|
||||
|
@ -9547,6 +9557,15 @@ TreeTransform<Derived>::TransformOMPFilterClause(OMPFilterClause *C) {
|
|||
C->getLParenLoc(), C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPAlignClause(OMPAlignClause *C) {
|
||||
ExprResult E = getDerived().TransformExpr(C->getAlignment());
|
||||
if (E.isInvalid())
|
||||
return nullptr;
|
||||
return getDerived().RebuildOMPAlignClause(E.get(), C->getBeginLoc(),
|
||||
C->getLParenLoc(), C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *TreeTransform<Derived>::TransformOMPUnifiedAddressClause(
|
||||
OMPUnifiedAddressClause *C) {
|
||||
|
|
|
@ -11974,6 +11974,9 @@ OMPClause *OMPClauseReader::readClause() {
|
|||
case llvm::omp::OMPC_bind:
|
||||
C = OMPBindClause::CreateEmpty(Context);
|
||||
break;
|
||||
case llvm::omp::OMPC_align:
|
||||
C = new (Context) OMPAlignClause();
|
||||
break;
|
||||
#define OMP_CLAUSE_NO_CLASS(Enum, Str) \
|
||||
case llvm::omp::Enum: \
|
||||
break;
|
||||
|
@ -12964,6 +12967,11 @@ void OMPClauseReader::VisitOMPBindClause(OMPBindClause *C) {
|
|||
C->setBindKindLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPAlignClause(OMPAlignClause *C) {
|
||||
C->setAlignment(Record.readExpr());
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
OMPTraitInfo *ASTRecordReader::readOMPTraitInfo() {
|
||||
OMPTraitInfo &TI = getContext().getNewOMPTraitInfo();
|
||||
TI.Sets.resize(readUInt32());
|
||||
|
|
|
@ -4757,9 +4757,10 @@ void ASTDeclReader::UpdateDecl(Decl *D,
|
|||
auto AllocatorKind =
|
||||
static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(Record.readInt());
|
||||
Expr *Allocator = Record.readExpr();
|
||||
Expr *Alignment = Record.readExpr();
|
||||
SourceRange SR = readSourceRange();
|
||||
D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
|
||||
Reader.getContext(), AllocatorKind, Allocator, SR,
|
||||
Reader.getContext(), AllocatorKind, Allocator, Alignment, SR,
|
||||
AttributeCommonInfo::AS_Pragma));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -5026,6 +5026,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
|
|||
auto *A = D->getAttr<OMPAllocateDeclAttr>();
|
||||
Record.push_back(A->getAllocatorType());
|
||||
Record.AddStmt(A->getAllocator());
|
||||
Record.AddStmt(A->getAlignment());
|
||||
Record.AddSourceRange(A->getRange());
|
||||
break;
|
||||
}
|
||||
|
@ -6230,6 +6231,11 @@ void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {
|
|||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPAlignClause(OMPAlignClause *C) {
|
||||
Record.AddStmt(C->getAlignment());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
|
||||
Record.push_back(C->varlist_size());
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
// expected-no-diagnostics
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -emit-pch -o %t %s
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
|
||||
//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
|
||||
//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
|
||||
//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
|
||||
//RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
typedef enum omp_allocator_handle_t {
|
||||
omp_null_allocator = 0,
|
||||
omp_default_mem_alloc = 1,
|
||||
omp_large_cap_mem_alloc = 2,
|
||||
omp_const_mem_alloc = 3,
|
||||
omp_high_bw_mem_alloc = 4,
|
||||
omp_low_lat_mem_alloc = 5,
|
||||
omp_cgroup_mem_alloc = 6,
|
||||
omp_pteam_mem_alloc = 7,
|
||||
omp_thread_mem_alloc = 8,
|
||||
KMP_ALLOCATOR_MAX_HANDLE = __UINTPTR_MAX__
|
||||
} omp_allocator_handle_t;
|
||||
|
||||
int foo1() {
|
||||
char a;
|
||||
#pragma omp allocate(a) align(4) allocator(omp_pteam_mem_alloc)
|
||||
return a;
|
||||
}
|
||||
// DUMP: FunctionDecl {{.*}}
|
||||
// DUMP: DeclStmt {{.*}}
|
||||
// DUMP: VarDecl {{.*}}a 'char'
|
||||
// DUMP: OMPAllocateDeclAttr {{.*}}OMPPTeamMemAlloc
|
||||
// DUMP: DeclRefExpr {{.*}}'omp_allocator_handle_t' EnumConstant {{.*}} 'omp_pteam_mem_alloc' 'omp_allocator_handle_t'
|
||||
// DUMP: ConstantExpr {{.*}}'int'
|
||||
// DUMP: value: Int 4
|
||||
// DUMP: IntegerLiteral {{.*}}'int' 4
|
||||
// DUMP: DeclStmt {{.*}}
|
||||
// DUMP: OMPAllocateDecl {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'char' lvalue Var {{.*}} 'a' 'char'
|
||||
// DUMP: OMPAlignClause {{.*}}
|
||||
// DUMP: ConstantExpr {{.*}}'int'
|
||||
// DUMP: value: Int 4
|
||||
// DUMP: IntegerLiteral {{.*}}'int' 4
|
||||
// DUMP: OMPAllocatorClause {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'omp_allocator_handle_t' EnumConstant {{.*}}'omp_pteam_mem_alloc' 'omp_allocator_handle_t'
|
||||
// PRINT: #pragma omp allocate(a) align(4) allocator(omp_pteam_mem_alloc)
|
||||
|
||||
int foo2() {
|
||||
char b;
|
||||
#pragma omp allocate(b) allocator(omp_low_lat_mem_alloc) align(2)
|
||||
return b;
|
||||
}
|
||||
// DUMP: FunctionDecl {{.*}}
|
||||
// DUMP: DeclStmt {{.*}}
|
||||
// DUMP: VarDecl {{.*}}b 'char'
|
||||
// DUMP: OMPAllocateDeclAttr {{.*}}Implicit OMPLowLatMemAlloc
|
||||
// DUMP: DeclRefExpr {{.*}}'omp_allocator_handle_t' EnumConstant {{.*}} 'omp_low_lat_mem_alloc' 'omp_allocator_handle_t'
|
||||
// DUMP: ConstantExpr {{.*}}'int'
|
||||
// DUMP: value: Int 2
|
||||
// DUMP: IntegerLiteral {{.*}}'int' 2
|
||||
// DUMP: DeclStmt {{.*}}
|
||||
// DUMP: OMPAllocateDecl {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'char' lvalue Var {{.*}} 'b' 'char'
|
||||
// DUMP: OMPAllocatorClause {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'omp_allocator_handle_t' EnumConstant {{.*}} 'omp_low_lat_mem_alloc' 'omp_allocator_handle_t'
|
||||
// DUMP: OMPAlignClause {{.*}}
|
||||
// DUMP: ConstantExpr {{.*}}'int'
|
||||
// DUMP: value: Int 2
|
||||
// DUMP: IntegerLiteral {{.*}}'int' 2
|
||||
// PRINT: #pragma omp allocate(b) allocator(omp_low_lat_mem_alloc) align(2)
|
||||
|
||||
template <typename T, unsigned size>
|
||||
T run() {
|
||||
T foo;
|
||||
#pragma omp allocate(foo) align(size)
|
||||
return size;
|
||||
}
|
||||
|
||||
int template_test() {
|
||||
double d;
|
||||
d = run<double, 1>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// DUMP: FunctionTemplateDecl {{.*}}
|
||||
// DUMP: TemplateTypeParmDecl {{.*}}
|
||||
// DUMP: NonTypeTemplateParmDecl {{.*}}'unsigned int' depth 0 index 1 size
|
||||
// DUMP: FunctionDecl {{.*}}'T ()'
|
||||
// DUMP: DeclStmt {{.*}}
|
||||
// DUMP: OMPAllocateDecl {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'T' lvalue Var {{.*}} 'foo' 'T'
|
||||
// DUMP: OMPAlignClause {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'unsigned int' NonTypeTemplateParm {{.*}} 'size' 'unsigned int'
|
||||
// DUMP: FunctionDecl {{.*}}run 'double ()'
|
||||
// DUMP: TemplateArgument type 'double'
|
||||
// DUMP: BuiltinType {{.*}}'double'
|
||||
// DUMP: TemplateArgument integral 1
|
||||
// DUMP: OMPAllocateDeclAttr {{.*}}Implicit OMPNullMemAlloc
|
||||
// DUMP: ConstantExpr {{.*}}'unsigned int'
|
||||
// DUMP: value: Int 1
|
||||
// DUMP: SubstNonTypeTemplateParmExpr {{.*}}'unsigned int'
|
||||
// DUMP: NonTypeTemplateParmDecl {{.*}}'unsigned int' depth 0 index 1 size
|
||||
// DUMP: IntegerLiteral {{.*}}'unsigned int' 1
|
||||
// DUMP: OMPAllocateDecl {{.*}}
|
||||
// DUMP: DeclRefExpr {{.*}}'double':'double' lvalue Var {{.*}} 'foo' 'double':'double'
|
||||
// DUMP: OMPAlignClause {{.*}}
|
||||
// DUMP: ConstantExpr {{.*}}'unsigned int'
|
||||
// DUMP: value: Int 1
|
||||
// DUMP: SubstNonTypeTemplateParmExpr {{.*}}'unsigned int'
|
||||
// DUMP: NonTypeTemplateParmDecl {{.*}}'unsigned int' depth 0 index 1 size
|
||||
// DUMP: IntegerLiteral {{.*}}'unsigned int' 1
|
||||
// PRINT: #pragma omp allocate(foo) align(size)
|
||||
// PRINT: #pragma omp allocate(foo) align(1U)
|
||||
#endif // HEADER
|
|
@ -0,0 +1,60 @@
|
|||
// RUN: %clang_cc1 -fopenmp -fopenmp-version=51 %s -verify
|
||||
|
||||
int foobar() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// expected-note@+1 {{declared here}}
|
||||
int a;
|
||||
// expected-note@+1 {{declared here}}
|
||||
int b;
|
||||
// expected-note@+1 {{declared here}}
|
||||
int c;
|
||||
double f;
|
||||
int foo2[10];
|
||||
|
||||
// expected-error@+1 {{expected '(' after 'align'}}
|
||||
#pragma omp allocate(a) align
|
||||
// expected-error@+3 {{expected expression}}
|
||||
// expected-error@+2 {{expected ')'}}
|
||||
// expected-note@+1 {{to match this '('}}
|
||||
#pragma omp allocate(a) align(
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp allocate(a) align()
|
||||
// expected-error@+4 {{expected ')'}}
|
||||
// expected-note@+3 {{to match this '('}}
|
||||
// expected-error@+2 {{expression is not an integral constant expression}}
|
||||
// expected-note@+1 {{read of non-const variable 'a' is not allowed in a constant expression}}
|
||||
#pragma omp allocate(a) align(a
|
||||
// expected-error@+2 {{expression is not an integral constant expression}}
|
||||
// expected-note@+1 {{read of non-const variable 'b' is not allowed in a constant expression}}
|
||||
#pragma omp allocate(a) align(b)
|
||||
// expected-error@+2 {{expression is not an integral constant expression}}
|
||||
// expected-note@+1 {{read of non-const variable 'c' is not allowed in a constant expression}}
|
||||
#pragma omp allocate(a) align(c + 1)
|
||||
// expected-error@+1 {{expected an OpenMP directive}}
|
||||
#pragma omp align(2) allocate(a)
|
||||
// expected-error@+1 {{directive '#pragma omp allocate' cannot contain more than one 'align' clause}}
|
||||
#pragma omp allocate(a) align(2) align(4)
|
||||
// expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
|
||||
#pragma omp allocate(a) align(9)
|
||||
// expected-error@+1 {{integral constant expression must have integral or unscoped enumeration type, not 'double'}}
|
||||
#pragma omp allocate(a) align(f)
|
||||
}
|
||||
|
||||
// Verify appropriate errors when using templates.
|
||||
template <typename T, unsigned size, unsigned align>
|
||||
T run() {
|
||||
T foo[size];
|
||||
// expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
|
||||
#pragma omp allocate(foo) align(align)
|
||||
return foo[0];
|
||||
}
|
||||
|
||||
int template_test() {
|
||||
double d;
|
||||
// expected-note@+1 {{in instantiation of function template specialization 'run<double, 10U, 3U>' requested here}}
|
||||
d = run<double, 10, 3>();
|
||||
return 0;
|
||||
}
|
|
@ -2315,6 +2315,10 @@ void OMPClauseEnqueue::VisitOMPFilterClause(const OMPFilterClause *C) {
|
|||
Visitor->AddStmt(C->getThreadID());
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPAlignClause(const OMPAlignClause *C) {
|
||||
Visitor->AddStmt(C->getAlignment());
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPUnifiedAddressClause(
|
||||
const OMPUnifiedAddressClause *) {}
|
||||
|
||||
|
|
|
@ -1481,6 +1481,7 @@ CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
|
|||
CHECK_SIMPLE_CLAUSE(AppendArgs, OMPC_append_args)
|
||||
CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order)
|
||||
CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind)
|
||||
CHECK_SIMPLE_CLAUSE(Align, OMPC_align)
|
||||
|
||||
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
|
||||
CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)
|
||||
|
|
|
@ -363,6 +363,9 @@ def OMPC_Filter : Clause<"filter"> {
|
|||
let clangClass = "OMPFilterClause";
|
||||
let flangClass = "ScalarIntExpr";
|
||||
}
|
||||
def OMPC_Align : Clause<"align"> {
|
||||
let clangClass = "OMPAlignClause";
|
||||
}
|
||||
def OMPC_When: Clause<"when"> {}
|
||||
|
||||
def OMPC_Bind : Clause<"bind"> {
|
||||
|
@ -1539,7 +1542,8 @@ def OMP_TargetTeamsDistributeSimd :
|
|||
}
|
||||
def OMP_Allocate : Directive<"allocate"> {
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<OMPC_Allocator>
|
||||
VersionedClause<OMPC_Allocator>,
|
||||
VersionedClause<OMPC_Align, 51>
|
||||
];
|
||||
}
|
||||
def OMP_DeclareVariant : Directive<"declare variant"> {
|
||||
|
|
Loading…
Reference in New Issue