r301410 - [OPENMP] Move handling of threadprivate vars from the stack, NFC.

Ahmed Bougacha via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 26 18:59:47 PDT 2017


Hey Alexey,

This is causing asan errors, e.g.:

==4735==ERROR: AddressSanitizer: heap-buffer-overflow on
address 0x61f000000e70 at pc 0x00010a8a7f4a bp 0x7fff5c57a390
sp 0x7fff5c57a388
READ of size 4 at 0x61f000000e70 thread T0
    #0 0x10a8a7f49 in
(anonymous namespace)::DSAStackTy::hasDSA(clang::ValueDecl*,
llvm::function_ref<bool
(clang::OpenMPClauseKind)> const&, llvm::function_ref<bool
(clang::OpenMPDirectiveKind)> const&, bool) SemaOpenMP.cpp:836
    #1 0x10a8a4560
in clang::Sema::IsOpenMPCapturedDecl(clang::ValueDecl*) SemaOpenMP.cpp:1107
    #2 0x10a575739 in
clang::Sema::tryCaptureVariable(clang::VarDecl*, clang::SourceLocation,
clang::Sema::TryCaptureKind, clang::SourceLocation, bool, clang::QualType&,
clang::QualType&, unsigned int const*) SemaExpr.cpp:14005
   ...

0x61f000000e70 is located 16 bytes to the left of 3440-byte
region [0x61f000000e80,0x61f000001bf0) allocated by thread T0 here:
    #0 0x116f036d2 in
wrap__Znwm (libclang_rt.asan_osx_dynamic.dylib:x86_64+0x656d2)
    #1 0x10a8a1642 in
clang::Sema::InitDataSharingAttributesStack() SemaOpenMP.cpp:914
    #2 0x109fc8585 in
clang::Sema::Sema(clang::Preprocessor&, clang::ASTContext&,
clang::ASTConsumer&,
clang::TranslationUnitKind, clang::CodeCompleteConsumer*) Sema.cpp:125
   ...

SUMMARY: AddressSanitizer: heap-buffer-overflow SemaOpenMP.cpp:836
in (anonymous
namespace)::DSAStackTy::hasDSA(clang::ValueDecl*, llvm::function_ref<bool
(clang::OpenMPClauseKind)> const&, llvm::function_ref<bool
(clang::OpenMPDirectiveKind)> const&, bool)


http://green.lab.llvm.org/green/job/clang-stage2-cmake-RgSan_check/3344/testReport/junit/Clang/OpenMP/atomic_codegen_cpp/

Can you have a look?
Thanks!
-Ahmed


On Wed, Apr 26, 2017 at 7:24 AM, Alexey Bataev via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: abataev
> Date: Wed Apr 26 09:24:21 2017
> New Revision: 301410
>
> URL: http://llvm.org/viewvc/llvm-project?rev=301410&view=rev
> Log:
> [OPENMP] Move handling of threadprivate vars from the stack, NFC.
>
> Threadprivate variables do no need to be handled in the Stack of all
> directives, moving it out for better performance and memory.
>
> Modified:
>     cfe/trunk/lib/Sema/SemaOpenMP.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
> URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=301410&r1=301409&r2=301410&view=diff
>
==============================================================================
> --- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Apr 26 09:24:21 2017
> @@ -118,6 +118,7 @@ private:
>    typedef SmallVector<SharingMapTy, 4> StackTy;
>
>    /// \brief Stack of used declaration and their data-sharing attributes.
> +  DeclSAMapTy Threadprivates;
>    StackTy Stack;
>    /// \brief true, if check for DSA must be from parent directive,
false, if
>    /// from current directive.
> @@ -134,7 +135,7 @@ private:
>    bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
>
>  public:
> -  explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
> +  explicit DSAStackTy(Sema &S) : SemaRef(S) {}
>
>    bool isClauseParsingMode() const { return ClauseKindMode !=
OMPC_unknown; }
>    void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
> @@ -149,7 +150,7 @@ public:
>    }
>
>    void pop() {
> -    assert(Stack.size() > 1 && "Data-sharing attributes stack is
empty!");
> +    assert(!Stack.empty() && "Data-sharing attributes stack is empty!");
>      Stack.pop_back();
>    }
>
> @@ -229,11 +230,11 @@ public:
>
>    /// \brief Returns currently analyzed directive.
>    OpenMPDirectiveKind getCurrentDirective() const {
> -    return Stack.back().Directive;
> +    return Stack.empty() ? OMPD_unknown : Stack.back().Directive;
>    }
>    /// \brief Returns parent directive.
>    OpenMPDirectiveKind getParentDirective() const {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        return Stack[Stack.size() - 2].Directive;
>      return OMPD_unknown;
>    }
> @@ -250,10 +251,10 @@ public:
>    }
>
>    DefaultDataSharingAttributes getDefaultDSA() const {
> -    return Stack.back().DefaultAttr;
> +    return Stack.empty() ? DSA_unspecified : Stack.back().DefaultAttr;
>    }
>    SourceLocation getDefaultDSALocation() const {
> -    return Stack.back().DefaultAttrLoc;
> +    return Stack.empty() ? SourceLocation() :
Stack.back().DefaultAttrLoc;
>    }
>
>    /// \brief Checks if the specified variable is a threadprivate.
> @@ -270,13 +271,13 @@ public:
>    /// \brief Returns true, if parent region is ordered (has associated
>    /// 'ordered' clause), false - otherwise.
>    bool isParentOrderedRegion() const {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        return Stack[Stack.size() - 2].OrderedRegion.getInt();
>      return false;
>    }
>    /// \brief Returns optional parameter for the ordered region.
>    Expr *getParentOrderedRegionParam() const {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        return Stack[Stack.size() - 2].OrderedRegion.getPointer();
>      return nullptr;
>    }
> @@ -287,28 +288,32 @@ public:
>    /// \brief Returns true, if parent region is nowait (has associated
>    /// 'nowait' clause), false - otherwise.
>    bool isParentNowaitRegion() const {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        return Stack[Stack.size() - 2].NowaitRegion;
>      return false;
>    }
>    /// \brief Marks parent region as cancel region.
>    void setParentCancelRegion(bool Cancel = true) {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        Stack[Stack.size() - 2].CancelRegion =
>            Stack[Stack.size() - 2].CancelRegion || Cancel;
>    }
>    /// \brief Return true if current region has inner cancel construct.
> -  bool isCancelRegion() const { return Stack.back().CancelRegion; }
> +  bool isCancelRegion() const {
> +    return Stack.empty() ? false : Stack.back().CancelRegion;
> +  }
>
>    /// \brief Set collapse value for the region.
>    void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops =
Val; }
>    /// \brief Return collapse value for region.
> -  unsigned getAssociatedLoops() const { return
Stack.back().AssociatedLoops; }
> +  unsigned getAssociatedLoops() const {
> +    return Stack.empty() ? 0 : Stack.back().AssociatedLoops;
> +  }
>
>    /// \brief Marks current target region as one with closely nested teams
>    /// region.
>    void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
> -    if (Stack.size() > 2)
> +    if (Stack.size() > 1)
>        Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc;
>    }
>    /// \brief Returns true, if current region has closely nested teams
region.
> @@ -317,14 +322,18 @@ public:
>    }
>    /// \brief Returns location of the nested teams region (if any).
>    SourceLocation getInnerTeamsRegionLoc() const {
> -    if (Stack.size() > 1)
> -      return Stack.back().InnerTeamsRegionLoc;
> -    return SourceLocation();
> +    return Stack.empty() ? SourceLocation() :
Stack.back().InnerTeamsRegionLoc;
>    }
>
> -  Scope *getCurScope() const { return Stack.back().CurScope; }
> -  Scope *getCurScope() { return Stack.back().CurScope; }
> -  SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
> +  Scope *getCurScope() const {
> +    return Stack.empty() ? nullptr : Stack.back().CurScope;
> +  }
> +  Scope *getCurScope() {
> +    return Stack.empty() ? nullptr : Stack.back().CurScope;
> +  }
> +  SourceLocation getConstructLoc() {
> +    return Stack.empty() ? SourceLocation() : Stack.back().ConstructLoc;
> +  }
>
>    /// Do the check specified in \a Check to all component lists and
return true
>    /// if any issue is found.
> @@ -361,7 +370,7 @@ public:
>        ValueDecl *VD,
>        OMPClauseMappableExprCommon::MappableExprComponentListRef
Components,
>        OpenMPClauseKind WhereFoundClauseKind) {
> -    assert(Stack.size() > 1 &&
> +    assert(!Stack.empty() &&
>             "Not expecting to retrieve components from a empty stack!");
>      auto &MEC = Stack.back().MappedExprComponents[VD];
>      // Create new entry and append the new components there.
> @@ -371,23 +380,23 @@ public:
>    }
>
>    unsigned getNestingLevel() const {
> -    assert(Stack.size() > 1);
> -    return Stack.size() - 2;
> +    assert(!Stack.empty());
> +    return Stack.size() - 1;
>    }
>    void addDoacrossDependClause(OMPDependClause *C, OperatorOffsetTy
&OpsOffs) {
> -    assert(Stack.size() > 2);
> +    assert(Stack.size() > 1);
>      assert(isOpenMPWorksharingDirective(Stack[Stack.size() -
2].Directive));
>      Stack[Stack.size() - 2].DoacrossDepends.insert({C, OpsOffs});
>    }
>    llvm::iterator_range<DoacrossDependMapTy::const_iterator>
>    getDoacrossDependClauses() const {
> -    assert(Stack.size() > 1);
> -    if (isOpenMPWorksharingDirective(Stack[Stack.size() - 1].Directive))
{
> -      auto &Ref = Stack[Stack.size() - 1].DoacrossDepends;
> +    assert(!Stack.empty());
> +    if (isOpenMPWorksharingDirective(Stack.back().Directive)) {
> +      auto &Ref = Stack.back().DoacrossDepends;
>        return llvm::make_range(Ref.begin(), Ref.end());
>      }
> -    return llvm::make_range(Stack[0].DoacrossDepends.end(),
> -                            Stack[0].DoacrossDepends.end());
> +    return llvm::make_range(Stack.back().DoacrossDepends.end(),
> +                            Stack.back().DoacrossDepends.end());
>    }
>  };
>  bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
> @@ -416,7 +425,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>    auto *VD = dyn_cast<VarDecl>(D);
>    auto *FD = dyn_cast<FieldDecl>(D);
>    DSAVarData DVar;
> -  if (Iter == std::prev(Stack.rend())) {
> +  if (Iter == Stack.rend()) {
>      // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
Referenced
>      // in a region but not in construct]
>      //  File-scope or namespace-scope variables referenced in called
routines
> @@ -490,8 +499,9 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>      //  bound to the current team is shared.
>      if (isOpenMPTaskingDirective(DVar.DKind)) {
>        DSAVarData DVarTemp;
> -      for (StackTy::reverse_iterator I = std::next(Iter), EE =
Stack.rend();
> -           I != EE; ++I) {
> +      auto I = Iter, E = Stack.rend();
> +      do {
> +        ++I;
>          // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
>          // Referenced in a Construct, implicitly determined, p.6]
>          //  In a task construct, if no default clause is present, a
variable
> @@ -503,9 +513,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>            DVar.CKind = OMPC_firstprivate;
>            return DVar;
>          }
> -        if (isParallelOrTaskRegion(I->Directive))
> -          break;
> -      }
> +      } while (I != E && !isParallelOrTaskRegion(I->Directive));
>        DVar.CKind =
>            (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate :
OMPC_shared;
>        return DVar;
> @@ -520,7 +528,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDS
>  }
>
>  Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
> -  assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
> +  assert(!Stack.empty() && "Data sharing attributes stack is empty");
>    D = getCanonicalDecl(D);
>    auto It = Stack.back().AlignedMap.find(D);
>    if (It == Stack.back().AlignedMap.end()) {
> @@ -535,21 +543,21 @@ Expr *DSAStackTy::addUniqueAligned(Value
>  }
>
>  void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) {
> -  assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
> +  assert(!Stack.empty() && "Data-sharing attributes stack is empty");
>    D = getCanonicalDecl(D);
>    Stack.back().LCVMap.insert(
> -      std::make_pair(D, LCDeclInfo(Stack.back().LCVMap.size() + 1,
Capture)));
> +      {D, LCDeclInfo(Stack.back().LCVMap.size() + 1, Capture)});
>  }
>
>  DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) {
> -  assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
> +  assert(!Stack.empty() && "Data-sharing attributes stack is empty");
>    D = getCanonicalDecl(D);
>    return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D]
>                                            : LCDeclInfo(0, nullptr);
>  }
>
>  DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl
*D) {
> -  assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
> +  assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
>    D = getCanonicalDecl(D);
>    return Stack[Stack.size() - 2].LCVMap.count(D) > 0
>               ? Stack[Stack.size() - 2].LCVMap[D]
> @@ -557,7 +565,7 @@ DSAStackTy::LCDeclInfo DSAStackTy::isPar
>  }
>
>  ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
> -  assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
> +  assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
>    if (Stack[Stack.size() - 2].LCVMap.size() < I)
>      return nullptr;
>    for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
> @@ -571,12 +579,12 @@ void DSAStackTy::addDSA(ValueDecl *D, Ex
>                          DeclRefExpr *PrivateCopy) {
>    D = getCanonicalDecl(D);
>    if (A == OMPC_threadprivate) {
> -    auto &Data = Stack[0].SharingMap[D];
> +    auto &Data = Threadprivates[D];
>      Data.Attributes = A;
>      Data.RefExpr.setPointer(E);
>      Data.PrivateCopy = nullptr;
>    } else {
> -    assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
> +    assert(!Stack.empty() && "Data-sharing attributes stack is empty");
>      auto &Data = Stack.back().SharingMap[D];
>      assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
>             (A == OMPC_firstprivate && Data.Attributes ==
OMPC_lastprivate) ||
> @@ -602,19 +610,17 @@ void DSAStackTy::addDSA(ValueDecl *D, Ex
>
>  bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator
Iter) {
>    D = D->getCanonicalDecl();
> -  if (Stack.size() > 2) {
> -    reverse_iterator I = Iter, E = std::prev(Stack.rend());
> +  if (Stack.size() > 1) {
> +    reverse_iterator I = Iter, E = Stack.rend();
>      Scope *TopScope = nullptr;
> -    while (I != E && !isParallelOrTaskRegion(I->Directive)) {
> +    while (I != E && !isParallelOrTaskRegion(I->Directive))
>        ++I;
> -    }
>      if (I == E)
>        return false;
>      TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
>      Scope *CurScope = getCurScope();
> -    while (CurScope != TopScope && !CurScope->isDeclScope(D)) {
> +    while (CurScope != TopScope && !CurScope->isDeclScope(D))
>        CurScope = CurScope->getParent();
> -    }
>      return CurScope != TopScope;
>    }
>    return false;
> @@ -665,16 +671,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
>                                 D->getLocation()),
>             OMPC_threadprivate);
>    }
> -  if (Stack[0].SharingMap.count(D)) {
> -    DVar.RefExpr = Stack[0].SharingMap[D].RefExpr.getPointer();
> +  auto TI = Threadprivates.find(D);
> +  if (TI != Threadprivates.end()) {
> +    DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
>      DVar.CKind = OMPC_threadprivate;
>      return DVar;
>    }
>
> -  if (Stack.size() == 1) {
> +  if (Stack.empty())
>      // Not in OpenMP execution region and top scope was already checked.
>      return DVar;
> -  }
>
>    // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
Referenced
>    // in a Construct, C/C++, predetermined, p.4]
> @@ -723,10 +729,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTo
>    // Explicitly specified attributes and local variables with
predetermined
>    // attributes.
>    auto StartI = std::next(Stack.rbegin());
> -  auto EndI = std::prev(Stack.rend());
> -  if (FromParent && StartI != EndI) {
> +  auto EndI = Stack.rend();
> +  if (FromParent && StartI != EndI)
>      StartI = std::next(StartI);
> -  }
>    auto I = std::prev(StartI);
>    if (I->SharingMap.count(D)) {
>      DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer();
> @@ -742,10 +747,9 @@ DSAStackTy::DSAVarData DSAStackTy::getIm
>                                                    bool FromParent) {
>    D = getCanonicalDecl(D);
>    auto StartI = Stack.rbegin();
> -  auto EndI = std::prev(Stack.rend());
> -  if (FromParent && StartI != EndI) {
> +  auto EndI = Stack.rend();
> +  if (FromParent && StartI != EndI)
>      StartI = std::next(StartI);
> -  }
>    return getDSA(StartI, D);
>  }
>
> @@ -757,17 +761,20 @@ DSAStackTy::hasDSA(ValueDecl *D,
>    D = getCanonicalDecl(D);
>    auto StartI = std::next(Stack.rbegin());
>    auto EndI = Stack.rend();
> -  if (FromParent && StartI != EndI) {
> +  if (FromParent && StartI != EndI)
>      StartI = std::next(StartI);
> -  }
> -  for (auto I = StartI, EE = EndI; I != EE; ++I) {
> +  if (StartI == EndI)
> +    return {};
> +  auto I = std::prev(StartI);
> +  do {
> +    ++I;
>      if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
>        continue;
>      DSAVarData DVar = getDSA(I, D);
>      if (CPred(DVar.CKind))
>        return DVar;
> -  }
> -  return DSAVarData();
> +  } while (I != EndI);
> +  return {};
>  }
>
>  DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
> @@ -791,7 +798,7 @@ bool DSAStackTy::hasExplicitDSA(
>    if (CPred(ClauseKindMode))
>      return true;
>    D = getCanonicalDecl(D);
> -  auto StartI = std::next(Stack.begin());
> +  auto StartI = Stack.begin();
>    auto EndI = Stack.end();
>    if (std::distance(StartI, EndI) <= (int)Level)
>      return false;
> @@ -805,7 +812,7 @@ bool DSAStackTy::hasExplicitDSA(
>  bool DSAStackTy::hasExplicitDirective(
>      const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
>      unsigned Level) {
> -  auto StartI = std::next(Stack.begin());
> +  auto StartI = Stack.begin();
>    auto EndI = Stack.end();
>    if (std::distance(StartI, EndI) <= (int)Level)
>      return false;
> @@ -819,13 +826,12 @@ bool DSAStackTy::hasDirective(
>          &DPred,
>      bool FromParent) {
>    // We look only in the enclosing region.
> -  if (Stack.size() < 2)
> +  if (Stack.size() < 1)
>      return false;
>    auto StartI = std::next(Stack.rbegin());
> -  auto EndI = std::prev(Stack.rend());
> -  if (FromParent && StartI != EndI) {
> +  auto EndI = Stack.rend();
> +  if (FromParent && StartI != EndI)
>      StartI = std::next(StartI);
> -  }
>    for (auto I = StartI, EE = EndI; I != EE; ++I) {
>      if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
>        return true;
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170426/91c3bcf2/attachment-0001.html>


More information about the cfe-commits mailing list