diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 07417020758..a57bbfc1d53 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -887,16 +887,56 @@ bool Sema::IsOpenMPCapturedByRef(ValueDecl *D, // array section, the runtime library may pass the NULL value to the // device instead of the value passed to it by the compiler. - // FIXME: Right now, only implicit maps are implemented. Properly mapping - // values requires having the map, private, and firstprivate clauses SEMA - // and parsing in place, which we don't yet. if (Ty->isReferenceType()) Ty = Ty->castAs<ReferenceType>()->getPointeeType(); - IsByRef = !Ty->isScalarType(); + + // Locate map clauses and see if the variable being captured is referred to + // in any of those clauses. Here we only care about variables, not fields, + // because fields are part of aggregates. + bool IsVariableUsedInMapClause = false; + bool IsVariableAssociatedWithSection = false; + + DSAStack->checkMappableExprComponentListsForDecl( + D, /*CurrentRegionOnly=*/true, + [&](OMPClauseMappableExprCommon::MappableExprComponentListRef + MapExprComponents) { + + auto EI = MapExprComponents.rbegin(); + auto EE = MapExprComponents.rend(); + + assert(EI != EE && "Invalid map expression!"); + + if (isa<DeclRefExpr>(EI->getAssociatedExpression())) + IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D; + + ++EI; + if (EI == EE) + return false; + + if (isa<ArraySubscriptExpr>(EI->getAssociatedExpression()) || + isa<OMPArraySectionExpr>(EI->getAssociatedExpression()) || + isa<MemberExpr>(EI->getAssociatedExpression())) { + IsVariableAssociatedWithSection = true; + // There is nothing more we need to know about this variable. + return true; + } + + // Keep looking for more map info. + return false; + }); + + if (IsVariableUsedInMapClause) { + // If variable is identified in a map clause it is always captured by + // reference except if it is a pointer that is dereferenced somehow. + IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection); + } else { + // By default, all the data that has a scalar type is mapped by copy. + IsByRef = !Ty->isScalarType(); + } } - // When passing data by value, we need to make sure it fits the uintptr size + // When passing data by copy, we need to make sure it fits the uintptr size // and alignment, because the runtime library only deals with uintptr types. // If it does not fit the uintptr size, we need to pass the data by reference // instead. |