summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGOpenMPRuntime.cpp89
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp16
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp198
4 files changed, 228 insertions, 78 deletions
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 42b7d16dfdb..fb2ce6c16d0 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -862,18 +862,7 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
}
LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
- if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
- return CGF.EmitOMPArraySectionExpr(OASE);
- if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
- return CGF.EmitLValue(ASE);
- auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
- DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD),
- CGF.CapturedStmtInfo &&
- CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
- E->getType(), VK_LValue, E->getExprLoc());
- // Store the address of the original variable associated with the LHS
- // implicit variable.
- return CGF.EmitLValue(&DRE);
+ return CGF.EmitOMPSharedLValue(E);
}
LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
@@ -5978,6 +5967,8 @@ public:
OMP_MAP_PRIVATE_PTR = 0x80,
/// \brief Pass the element to the device by value.
OMP_MAP_PRIVATE_VAL = 0x100,
+ /// Implicit map
+ OMP_MAP_IMPLICIT = 0x200,
};
/// Class that associates information with a base pointer to be passed to the
@@ -6148,7 +6139,7 @@ private:
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
- bool IsFirstComponentList) const {
+ bool IsFirstComponentList, bool IsImplicit) const {
// The following summarizes what has to be generated for each map and the
// types bellow. The generated information is expressed in this order:
@@ -6283,8 +6274,7 @@ private:
} else {
// The base is the reference to the variable.
// BP = &Var.
- BP = CGF.EmitLValue(cast<DeclRefExpr>(I->getAssociatedExpression()))
- .getPointer();
+ BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
// If the variable is a pointer and is being dereferenced (i.e. is not
// the last component), the base has to be the pointer itself, not its
@@ -6303,6 +6293,7 @@ private:
}
}
+ unsigned DefaultFlags = IsImplicit ? OMP_MAP_IMPLICIT : 0;
for (; I != CE; ++I) {
auto Next = std::next(I);
@@ -6337,7 +6328,8 @@ private:
isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
"Unexpected expression");
- auto *LB = CGF.EmitLValue(I->getAssociatedExpression()).getPointer();
+ llvm::Value *LB =
+ CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getPointer();
auto *Size = getExprTypeSize(I->getAssociatedExpression());
// If we have a member expression and the current component is a
@@ -6352,9 +6344,11 @@ private:
BasePointers.push_back(BP);
Pointers.push_back(RefAddr);
Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
- Types.push_back(getMapTypeBits(
- /*MapType*/ OMPC_MAP_alloc, /*MapTypeModifier=*/OMPC_MAP_unknown,
- !IsExpressionFirstInfo, IsCaptureFirstInfo));
+ Types.push_back(DefaultFlags |
+ getMapTypeBits(
+ /*MapType*/ OMPC_MAP_alloc,
+ /*MapTypeModifier=*/OMPC_MAP_unknown,
+ !IsExpressionFirstInfo, IsCaptureFirstInfo));
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
// The reference will be the next base address.
@@ -6369,9 +6363,9 @@ private:
// same expression except for the first one. We also need to signal
// this map is the first one that relates with the current capture
// (there is a set of entries for each capture).
- Types.push_back(getMapTypeBits(MapType, MapTypeModifier,
- !IsExpressionFirstInfo,
- IsCaptureFirstInfo));
+ Types.push_back(DefaultFlags | getMapTypeBits(MapType, MapTypeModifier,
+ !IsExpressionFirstInfo,
+ IsCaptureFirstInfo));
// If we have a final array section, we are done with this expression.
if (IsFinalArraySection)
@@ -6383,7 +6377,6 @@ private:
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
- continue;
}
}
}
@@ -6445,20 +6438,19 @@ public:
RPK_MemberReference,
};
OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
- OpenMPMapClauseKind MapType;
- OpenMPMapClauseKind MapTypeModifier;
- ReturnPointerKind ReturnDevicePointer;
+ OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
+ OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown;
+ ReturnPointerKind ReturnDevicePointer = RPK_None;
+ bool IsImplicit = false;
- MapInfo()
- : MapType(OMPC_MAP_unknown), MapTypeModifier(OMPC_MAP_unknown),
- ReturnDevicePointer(RPK_None) {}
+ MapInfo() = default;
MapInfo(
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapTypeModifier,
- ReturnPointerKind ReturnDevicePointer)
+ ReturnPointerKind ReturnDevicePointer, bool IsImplicit)
: Components(Components), MapType(MapType),
MapTypeModifier(MapTypeModifier),
- ReturnDevicePointer(ReturnDevicePointer) {}
+ ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
};
// We have to process the component lists that relate with the same
@@ -6472,25 +6464,29 @@ public:
const ValueDecl *D,
OMPClauseMappableExprCommon::MappableExprComponentListRef L,
OpenMPMapClauseKind MapType, OpenMPMapClauseKind MapModifier,
- MapInfo::ReturnPointerKind ReturnDevicePointer) {
+ MapInfo::ReturnPointerKind ReturnDevicePointer, bool IsImplicit) {
const ValueDecl *VD =
D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
- Info[VD].push_back({L, MapType, MapModifier, ReturnDevicePointer});
+ Info[VD].emplace_back(L, MapType, MapModifier, ReturnDevicePointer,
+ IsImplicit);
};
// FIXME: MSVC 2013 seems to require this-> to find member CurDir.
for (auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifier(),
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
for (auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_to, OMPC_MAP_unknown,
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
for (auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
- for (auto L : C->component_lists())
+ for (auto L : C->component_lists()) {
InfoGen(L.first, L.second, OMPC_MAP_from, OMPC_MAP_unknown,
- MapInfo::RPK_None);
+ MapInfo::RPK_None, C->isImplicit());
+ }
// Look at the use_device_ptr clause information and mark the existing map
// entries as such. If there is no map information for an entry in the
@@ -6551,9 +6547,9 @@ public:
// Remember the current base pointer index.
unsigned CurrentBasePointersIdx = BasePointers.size();
// FIXME: MSVC 2013 seems to require this-> to find the member method.
- this->generateInfoForComponentList(L.MapType, L.MapTypeModifier,
- L.Components, BasePointers, Pointers,
- Sizes, Types, IsFirstComponentList);
+ this->generateInfoForComponentList(
+ L.MapType, L.MapTypeModifier, L.Components, BasePointers, Pointers,
+ Sizes, Types, IsFirstComponentList, L.IsImplicit);
// If this entry relates with a device pointer, set the relevant
// declaration and add the 'return pointer' flag.
@@ -6617,7 +6613,8 @@ public:
for (auto L : It->second) {
generateInfoForComponentList(
/*MapType=*/OMPC_MAP_to, /*MapTypeModifier=*/OMPC_MAP_unknown, L,
- BasePointers, Pointers, Sizes, Types, IsFirstComponentList);
+ BasePointers, Pointers, Sizes, Types, IsFirstComponentList,
+ /*IsImplicit=*/false);
IsFirstComponentList = false;
}
return;
@@ -6637,9 +6634,9 @@ public:
"We got information for the wrong declaration??");
assert(!L.second.empty() &&
"Not expecting declaration with no component lists.");
- generateInfoForComponentList(C->getMapType(), C->getMapTypeModifier(),
- L.second, BasePointers, Pointers, Sizes,
- Types, IsFirstComponentList);
+ generateInfoForComponentList(
+ C->getMapType(), C->getMapTypeModifier(), L.second, BasePointers,
+ Pointers, Sizes, Types, IsFirstComponentList, C->isImplicit());
IsFirstComponentList = false;
}
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 4dcdaa29379..20f15352098 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -138,6 +138,22 @@ public:
} // namespace
+LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
+ if (auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
+ if (auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
+ OrigVD = OrigVD->getCanonicalDecl();
+ bool IsCaptured =
+ LambdaCaptureFields.lookup(OrigVD) ||
+ (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
+ (CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
+ DeclRefExpr DRE(const_cast<VarDecl *>(OrigVD), IsCaptured,
+ OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
+ return EmitLValue(&DRE);
+ }
+ }
+ return EmitLValue(E);
+}
+
llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
auto &C = getContext();
llvm::Value *Size = nullptr;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index d77cea48b02..635df4bc6b5 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2886,6 +2886,9 @@ public:
const CodeGenLoopBoundsTy &CodeGenLoopBounds,
const CodeGenDispatchBoundsTy &CGDispatchBounds);
+ /// Emits the lvalue for the expression with possibly captured variable.
+ LValue EmitOMPSharedLValue(const Expr *E);
+
private:
/// Helpers for blocks
llvm::Value *EmitBlockLiteral(const CGBlockInfo &Info);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index e4a57db8da5..735e827eeae 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -35,6 +35,11 @@ using namespace clang;
// Stack of data-sharing attributes for variables
//===----------------------------------------------------------------------===//
+static Expr *CheckMapClauseExpressionBase(
+ Sema &SemaRef, Expr *E,
+ OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents,
+ OpenMPClauseKind CKind);
+
namespace {
/// \brief Default data sharing attributes, which can be applied to directive.
enum DefaultDataSharingAttributes {
@@ -1787,6 +1792,7 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> {
bool ErrorFound;
CapturedStmt *CS;
llvm::SmallVector<Expr *, 8> ImplicitFirstprivate;
+ llvm::SmallVector<Expr *, 8> ImplicitMap;
llvm::DenseMap<ValueDecl *, Expr *> VarsWithInheritedDSA;
llvm::DenseSet<ValueDecl *> ImplicitDeclarations;
@@ -1819,6 +1825,50 @@ public:
return;
}
+ if (isOpenMPTargetExecutionDirective(DKind) &&
+ !Stack->isLoopControlVariable(VD).first) {
+ if (!Stack->checkMappableExprComponentListsForDecl(
+ VD, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ // Variable is used if it has been marked as an array, array
+ // section or the variable iself.
+ return StackComponents.size() == 1 ||
+ std::all_of(
+ std::next(StackComponents.rbegin()),
+ StackComponents.rend(),
+ [](const OMPClauseMappableExprCommon::
+ MappableComponent &MC) {
+ return MC.getAssociatedDeclaration() ==
+ nullptr &&
+ (isa<OMPArraySectionExpr>(
+ MC.getAssociatedExpression()) ||
+ isa<ArraySubscriptExpr>(
+ MC.getAssociatedExpression()));
+ });
+ })) {
+ bool CapturedByCopy = false;
+ // By default lambdas are captured as firstprivates.
+ if (const auto *RD =
+ VD->getType().getNonReferenceType()->getAsCXXRecordDecl())
+ if (RD->isLambda())
+ CapturedByCopy = true;
+ CapturedByCopy =
+ CapturedByCopy ||
+ llvm::any_of(
+ CS->captures(), [VD](const CapturedStmt::Capture &I) {
+ return I.capturesVariableByCopy() &&
+ I.getCapturedVar()->getCanonicalDecl() == VD;
+ });
+ if (CapturedByCopy)
+ ImplicitFirstprivate.emplace_back(E);
+ else
+ ImplicitMap.emplace_back(E);
+ return;
+ }
+ }
+
// OpenMP [2.9.3.6, Restrictions, p.2]
// A list item that appears in a reduction clause of the innermost
// enclosing worksharing or parallel construct may not be accessed in an
@@ -1848,40 +1898,104 @@ public:
if (E->isTypeDependent() || E->isValueDependent() ||
E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
return;
+ auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
+ if (!FD)
+ return;
+ OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
- if (auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) {
- auto DVar = Stack->getTopDSA(FD, false);
- // Check if the variable has explicit DSA set and stop analysis if it
- // so.
- if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
- return;
+ auto DVar = Stack->getTopDSA(FD, false);
+ // Check if the variable has explicit DSA set and stop analysis if it
+ // so.
+ if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
+ return;
- auto ELoc = E->getExprLoc();
- auto DKind = Stack->getCurrentDirective();
- // OpenMP [2.9.3.6, Restrictions, p.2]
- // A list item that appears in a reduction clause of the innermost
- // enclosing worksharing or parallel construct may not be accessed in
- // an explicit task.
- DVar = Stack->hasInnermostDSA(
- FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
- [](OpenMPDirectiveKind K) -> bool {
- return isOpenMPParallelDirective(K) ||
- isOpenMPWorksharingDirective(K) ||
- isOpenMPTeamsDirective(K);
- },
- /*FromParent=*/true);
- if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
- ErrorFound = true;
- SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
- ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ if (isOpenMPTargetExecutionDirective(DKind) &&
+ !Stack->isLoopControlVariable(FD).first &&
+ !Stack->checkMappableExprComponentListsForDecl(
+ FD, /*CurrentRegionOnly=*/true,
+ [](OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ return isa<CXXThisExpr>(
+ cast<MemberExpr>(
+ StackComponents.back().getAssociatedExpression())
+ ->getBase()
+ ->IgnoreParens());
+ })) {
+ // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
+ // A bit-field cannot appear in a map clause.
+ //
+ if (FD->isBitField()) {
+ SemaRef.Diag(E->getMemberLoc(),
+ diag::err_omp_bit_fields_forbidden_in_clause)
+ << E->getSourceRange() << getOpenMPClauseName(OMPC_map);
return;
}
+ ImplicitMap.emplace_back(E);
+ return;
+ }
- // Define implicit data-sharing attributes for task.
- DVar = Stack->getImplicitDSA(FD, false);
- if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
- !Stack->isLoopControlVariable(FD).first)
- ImplicitFirstprivate.push_back(E);
+ auto ELoc = E->getExprLoc();
+ // OpenMP [2.9.3.6, Restrictions, p.2]
+ // A list item that appears in a reduction clause of the innermost
+ // enclosing worksharing or parallel construct may not be accessed in
+ // an explicit task.
+ DVar = Stack->hasInnermostDSA(
+ FD, [](OpenMPClauseKind C) -> bool { return C == OMPC_reduction; },
+ [](OpenMPDirectiveKind K) -> bool {
+ return isOpenMPParallelDirective(K) ||
+ isOpenMPWorksharingDirective(K) || isOpenMPTeamsDirective(K);
+ },
+ /*FromParent=*/true);
+ if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
+ ErrorFound = true;
+ SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
+ ReportOriginalDSA(SemaRef, Stack, FD, DVar);
+ return;
+ }
+
+ // Define implicit data-sharing attributes for task.
+ DVar = Stack->getImplicitDSA(FD, false);
+ if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
+ !Stack->isLoopControlVariable(FD).first)
+ ImplicitFirstprivate.push_back(E);
+ return;
+ }
+ if (isOpenMPTargetExecutionDirective(DKind) && !FD->isBitField()) {
+ OMPClauseMappableExprCommon::MappableExprComponentList CurComponents;
+ CheckMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map);
+ auto *VD = cast<ValueDecl>(
+ CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
+ if (!Stack->checkMappableExprComponentListsForDecl(
+ VD, /*CurrentRegionOnly=*/true,
+ [&CurComponents](
+ OMPClauseMappableExprCommon::MappableExprComponentListRef
+ StackComponents,
+ OpenMPClauseKind) {
+ if (CurComponents.size() < StackComponents.size())
+ return false;
+ auto CCI = CurComponents.rbegin();
+ for (const auto &SC : llvm::reverse(StackComponents)) {
+ // Do both expressions have the same kind?
+ if (CCI->getAssociatedExpression()->getStmtClass() !=
+ SC.getAssociatedExpression()->getStmtClass())
+ if (!(isa<OMPArraySectionExpr>(
+ SC.getAssociatedExpression()) &&
+ isa<ArraySubscriptExpr>(
+ CCI->getAssociatedExpression())))
+ return false;
+
+ Decl *CCD = CCI->getAssociatedDeclaration();
+ Decl *SCD = SC.getAssociatedDeclaration();
+ CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
+ SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
+ if (SCD != CCD)
+ return false;
+ std::advance(CCI, 1);
+ }
+ return true;
+ })) {
+ Visit(E->getBase());
}
} else
Visit(E->getBase());
@@ -1889,12 +2003,16 @@ public:
void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
for (auto *C : S->clauses()) {
// Skip analysis of arguments of implicitly defined firstprivate clause
- // for task directives.
- if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid()))
+ // for task|target directives.
+ // Skip analysis of arguments of implicitly defined map clause for target
+ // directives.
+ if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
+ C->isImplicit())) {
for (auto *CC : C->children()) {
if (CC)
Visit(CC);
}
+ }
}
}
void VisitStmt(Stmt *S) {
@@ -1905,7 +2023,10 @@ public:
}
bool isErrorFound() { return ErrorFound; }
- ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; }
+ ArrayRef<Expr *> getImplicitFirstprivate() const {
+ return ImplicitFirstprivate;
+ }
+ ArrayRef<Expr *> getImplicitMap() const { return ImplicitMap; }
llvm::DenseMap<ValueDecl *, Expr *> &getVarsWithInheritedDSA() {
return VarsWithInheritedDSA;
}
@@ -2638,6 +2759,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
SmallVector<Expr *, 4> ImplicitFirstprivates(
DSAChecker.getImplicitFirstprivate().begin(),
DSAChecker.getImplicitFirstprivate().end());
+ SmallVector<Expr *, 4> ImplicitMaps(DSAChecker.getImplicitMap().begin(),
+ DSAChecker.getImplicitMap().end());
// Mark taskgroup task_reduction descriptors as implicitly firstprivate.
for (auto *C : Clauses) {
if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
@@ -2656,6 +2779,17 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
} else
ErrorFound = true;
}
+ if (!ImplicitMaps.empty()) {
+ if (OMPClause *Implicit = ActOnOpenMPMapClause(
+ OMPC_MAP_unknown, OMPC_MAP_tofrom, /*IsMapTypeImplicit=*/true,
+ SourceLocation(), SourceLocation(), ImplicitMaps,
+ SourceLocation(), SourceLocation(), SourceLocation())) {
+ ClausesWithImplicit.emplace_back(Implicit);
+ ErrorFound |=
+ cast<OMPMapClause>(Implicit)->varlist_size() != ImplicitMaps.size();
+ } else
+ ErrorFound = true;
+ }
}
llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
OpenPOWER on IntegriCloud