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