[Patch] Clang: allow scoped_lockable to acquire multiple locks

Aaron Ballman aaron at aaronballman.com
Tue Sep 2 05:56:42 PDT 2014


On Sun, Aug 31, 2014 at 12:53 AM, Ed Schouten <ed at 80386.nl> wrote:
> Hi DeLesley,
>
> First of all, thanks for your work on the thread annotations for
> Clang! Impressed by how well they work, I decided to patch up
> FreeBSD's pthread library to use these annotations by default.
>
> http://lists.freebsd.org/pipermail/freebsd-toolchain/2014-August/001183.html
>
> While experimenting with using these annotations in a C++ codebase, I
> discovered that it's currently not possible to use these for
> interlocking, as scoped_lockable does not support acquiring multiple
> mutexes. Example:
>
> class SCOPED_LOCKABLE DoubleGuard {
>   DoubleGuard(Mutex* m1, Mutex* m2) EXCLUSIVE_LOCK_FUNCTION(m1, m2) {
>     if (m1 == m2) {
>       m1_ = m1;
>       m2_ = nullptr;
>       m1_->Lock();
>     } else {
>       if (m1 < m2) {
>         m1_ = m1;
>         m2_ = m2;
>       } else {
>         m1_ = m2;
>         m2_ = m1;
>       }
>       m1_->Lock();
>       m2_->Lock();
>     }
>   }
>
>   ~DoubleGuard() UNLOCK_FUNCTION() {
>     m1_->Unlock();
>     if (m2_ != nullptr)
>       m2_->Unlock();
>   }
>
>  private:
>   Mutex* m1_;
>   Mutex* m2_;
> };
>
> This class cannot be used, as it will cause a warning that the guard
> object itself is locked twice. Attached is a patch to fix this. It
> changes the lock path to always create exactly one FactEntry for
> scoped lockables. Instead of having a single UnderlyingMutex, it now
> uses a CapExprSet.
>
> What are your thoughts on this change? Is it all right for me to commit this?

Thank you for working on this! Comments below.

> Index: lib/Analysis/ThreadSafety.cpp
> ===================================================================
> --- lib/Analysis/ThreadSafety.cpp (revision 216834)
> +++ lib/Analysis/ThreadSafety.cpp (working copy)
> @@ -97,23 +97,23 @@
>  /// shared.
>  class FactEntry : public CapabilityExpr {
>  private:
> -  LockKind          LKind;            ///<  exclusive or shared
> -  SourceLocation    AcquireLoc;       ///<  where it was acquired.
> -  bool              Managed;          ///<  for ScopedLockable objects
> -  bool              Asserted;         ///<  true if the lock was asserted
> -  const til::SExpr* UnderlyingMutex;  ///<  for ScopedLockable objects
> +  LockKind       LKind;              ///<  exclusive or shared
> +  SourceLocation AcquireLoc;         ///<  where it was acquired.
> +  bool           Managed;            ///<  for ScopedLockable objects
> +  bool           Asserted;           ///<  true if the lock was asserted
> +  CapExprSet     UnderlyingMutexes;  ///<  for ScopedLockable objects
>
>  public:
>    FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
>              bool Mng=false, bool Asrt=false)
>      : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Managed(Mng),
> -      Asserted(Asrt), UnderlyingMutex(nullptr)
> +      Asserted(Asrt)
>    {}
>
>    FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
> -            const til::SExpr *Mu)
> +            const CapExprSet& UnderlyingMutexes)
>      : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Managed(false),
> -      Asserted(false), UnderlyingMutex(Mu)
> +      Asserted(false), UnderlyingMutexes(UnderlyingMutexes)
>    {}
>
>    LockKind          kind()       const { return LKind;    }
> @@ -120,7 +120,7 @@
>    SourceLocation    loc()        const { return AcquireLoc; }
>    bool              asserted()   const { return Asserted; }
>    bool              managed()    const { return Managed;  }
> -  const til::SExpr* underlying() const { return UnderlyingMutex; }
> +  const CapExprSet* underlying() const { return &UnderlyingMutexes; }

Might as well return this by const reference, that will make usages
with range-based for loops a bit easier to read.

>
>    // Return true if LKind >= LK, where exclusive > shared
>    bool isAtLeast(LockKind LK) {
> @@ -960,28 +960,31 @@
>                                        LDat->kind(), ReceivedKind, UnlockLoc);
>    }
>
> -  if (LDat->underlying()) {
> +  const CapExprSet* UnderlyingMutexes = LDat->underlying();
> +  if (!UnderlyingMutexes->empty()) {
>      assert(!Cp.negative() && "Managing object cannot be negative.");
> -    CapabilityExpr UnderCp(LDat->underlying(), false);
> -    FactEntry UnderEntry(!UnderCp, LK_Exclusive, UnlockLoc);
> +    for (const CapabilityExpr& UnderlyingMutex : *UnderlyingMutexes) {
> +      CapabilityExpr UnderCp(UnderlyingMutex.sexpr(), false);
> +      FactEntry UnderEntry(!UnderCp, LK_Exclusive, UnlockLoc);
>
> -    // This is scoped lockable object, which manages the real mutex.
> -    if (FullyRemove) {
> -      // We're destroying the managing object.
> -      // Remove the underlying mutex if it exists; but don't warn.
> -      if (FSet.findLock(FactMan, UnderCp)) {
> +      // This is scoped lockable object, which manages the real mutex.
> +      if (FullyRemove) {
> +        // We're destroying the managing object.
> +        // Remove the underlying mutex if it exists; but don't warn.
> +        if (FSet.findLock(FactMan, UnderCp)) {
> +          FSet.removeLock(FactMan, UnderCp);
> +          FSet.addLock(FactMan, UnderEntry);
> +        }
> +        FSet.removeLock(FactMan, Cp);
> +      } else {
> +        // We're releasing the underlying mutex, but not destroying the
> +        // managing object.  Warn on dual release.
> +        if (!FSet.findLock(FactMan, UnderCp)) {
> +          Handler.handleUnmatchedUnlock(DiagKind, UnderCp.toString(), UnlockLoc);
> +        }
>          FSet.removeLock(FactMan, UnderCp);
>          FSet.addLock(FactMan, UnderEntry);
>        }
> -      FSet.removeLock(FactMan, Cp);
> -    } else {
> -      // We're releasing the underlying mutex, but not destroying the
> -      // managing object.  Warn on dual release.
> -      if (!FSet.findLock(FactMan, UnderCp)) {
> -        Handler.handleUnmatchedUnlock(DiagKind, UnderCp.toString(), UnlockLoc);
> -      }
> -      FSet.removeLock(FactMan, UnderCp);
> -      FSet.addLock(FactMan, UnderEntry);
>      }
>      return;
>    }
> @@ -1530,7 +1533,6 @@
>                        CapDiagKind);
>
>    // Add the managing object as a dummy mutex, mapped to the underlying mutex.
> -  // FIXME: this doesn't work if we acquire multiple locks.
>    if (isScopedVar) {
>      SourceLocation MLoc = VD->getLocation();
>      DeclRefExpr DRE(VD, false, VD->getType(), VK_LValue, VD->getLocation());
> @@ -1537,18 +1539,12 @@
>      // FIXME: does this store a pointer to DRE?
>      CapabilityExpr Scp = Analyzer->SxBuilder.translateAttrExpr(&DRE, nullptr);
>
> -    for (const auto &M : ExclusiveLocksToAdd)
> -      Analyzer->addLock(FSet, FactEntry(Scp, LK_Exclusive, MLoc, M.sexpr()),
> -                        CapDiagKind);
> -    for (const auto &M : SharedLocksToAdd)
> -      Analyzer->addLock(FSet, FactEntry(Scp, LK_Shared, MLoc, M.sexpr()),
> -                        CapDiagKind);
> -
> -    // handle corner case where the underlying mutex is invalid
> -    if (ExclusiveLocksToAdd.size() == 0 && SharedLocksToAdd.size() == 0) {
> -      Analyzer->addLock(FSet, FactEntry(Scp, LK_Exclusive, MLoc),
> -                        CapDiagKind);
> -    }
> +    CapExprSet UnderlyingMutexes(ExclusiveLocksToAdd);
> +    std::copy(SharedLocksToAdd.begin(), SharedLocksToAdd.end(),
> +              std::back_inserter(UnderlyingMutexes));
> +    Analyzer->addLock(FSet,
> +                      FactEntry(Scp, LK_Exclusive, MLoc, UnderlyingMutexes),
> +                      CapDiagKind);

This adds all locks to the analyzer as exclusive locks, but the
previous code would handled shared locks separately. Is that
intentional?

This also removes the corner case handling, is that no longer required?

>    }
>
>    // Remove locks.
> @@ -1729,15 +1725,18 @@
>          *Iter1 = Fact;
>        }
>      } else {
> -      if (LDat2->underlying()) {
> -        if (FSet2.findLock(FactMan, CapabilityExpr(LDat2->underlying(),
> -                                                    false))) {
> -          // If this is a scoped lock that manages another mutex, and if the
> -          // underlying mutex is still held, then warn about the underlying
> -          // mutex.
> -          Handler.handleMutexHeldEndOfScope("mutex",
> -                                            sx::toString(LDat2->underlying()),
> -                                            LDat2->loc(), JoinLoc, LEK1);
> +      const CapExprSet* UnderlyingMutexes = LDat2->underlying();
> +      if (!UnderlyingMutexes->empty()) {
> +        for (const CapabilityExpr &UnderlyingMutex : *UnderlyingMutexes) {
> +          if (FSet2.findLock(FactMan, CapabilityExpr(UnderlyingMutex.sexpr(),
> +                                                     false))) {
> +            // If this is a scoped lock that manages another mutex, and if the
> +            // underlying mutex is still held, then warn about the underlying
> +            // mutex.
> +            Handler.handleMutexHeldEndOfScope(
> +                "mutex", sx::toString(UnderlyingMutex.sexpr()),
> +                LDat2->loc(), JoinLoc, LEK1);
> +          }
>          }
>        }
>        else if (!LDat2->managed() && !LDat2->asserted() &&
> @@ -1754,15 +1753,18 @@
>      const FactEntry *LDat2 = FSet2.findLock(FactMan, *LDat1);
>
>      if (!LDat2) {
> -      if (LDat1->underlying()) {
> -        if (FSet1Orig.findLock(FactMan, CapabilityExpr(LDat1->underlying(),
> -                                                       false))) {
> -          // If this is a scoped lock that manages another mutex, and if the
> -          // underlying mutex is still held, then warn about the underlying
> -          // mutex.
> -          Handler.handleMutexHeldEndOfScope("mutex",
> -                                            sx::toString(LDat1->underlying()),
> -                                            LDat1->loc(), JoinLoc, LEK1);
> +      const CapExprSet* UnderlyingMutexes = LDat1->underlying();
> +      if (!UnderlyingMutexes->empty()) {
> +        for (const CapabilityExpr &UnderlyingMutex : *UnderlyingMutexes) {
> +          if (FSet1Orig.findLock(
> +              FactMan, CapabilityExpr(UnderlyingMutex.sexpr(), false))) {
> +            // If this is a scoped lock that manages another mutex, and if the
> +            // underlying mutex is still held, then warn about the underlying
> +            // mutex.
> +            Handler.handleMutexHeldEndOfScope(
> +                "mutex", sx::toString(UnderlyingMutex.sexpr()),
> +                LDat1->loc(), JoinLoc, LEK1);
> +          }
>          }
>        }
>        else if (!LDat1->managed() && !LDat1->asserted() &&
> Index: test/SemaCXX/warn-thread-safety-analysis.cpp
> ===================================================================
> --- test/SemaCXX/warn-thread-safety-analysis.cpp (revision 216834)
> +++ test/SemaCXX/warn-thread-safety-analysis.cpp (working copy)
> @@ -63,6 +63,12 @@
>    void Release() UNLOCK_FUNCTION();
>  };
>
> +class __attribute__((scoped_lockable)) DoubleMutexLock {
> + public:
> +  DoubleMutexLock(Mutex *mu1, Mutex *mu2)
> +      __attribute__((exclusive_lock_function(mu1, mu2)));
> +  ~DoubleMutexLock() __attribute__((unlock_function));
> +};
>
>  // The universal lock, written "*", allows checking to be selectively turned
>  // off for a particular piece of code.
> @@ -1662,6 +1668,12 @@
>      a = b+1;
>      b = a+1;
>    }
> +
> +  void foo5() {
> +    DoubleMutexLock mulock(&mu1, &mu2);
> +    a = b+1;
> +    b = a+1;
> +  }
>  };
>
>  } // end namespace test_scoped_lockable
>

When I apply this patch and run the tests on Windows 7 (built with
MSVC 2013 as x86), I get the following crash:

54>  Running the Clang regression tests
54>  -- Testing: 7601 tests, 32 threads --
54>  FAIL: Clang :: SemaCXX/warn-thread-safety-analysis.cpp (5831 of 7601)
54>  ******************** TEST 'Clang ::
SemaCXX/warn-thread-safety-analysis.cpp' FAILED ********************
54>  Script:
54>  --
54>  E:/llvm/2013/Debug/bin/clang.EXE -cc1 -internal-isystem
E:\llvm\2013\Debug\bin\..\lib\clang\3.6.0\include -fsyntax-only
-verify -std=c++11 -Wthread-safety -Wthread-safety-beta
-Wno-thread-safety-negative -fcxx-exceptions
E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp
54>  --
54>  Exit Code: -1073741819
54>
54>  Command Output (stdout):
54>  --
54>  Command 0: "E:/llvm/2013/Debug/bin/clang.EXE" "-cc1"
"-internal-isystem"
"E:\llvm\2013\Debug\bin\..\lib\clang\3.6.0\include" "-fsyntax-only"
"-verify" "-std=c++11" "-Wthread-safety" "-Wthread-safety-beta"
"-Wno-thread-safety-negative" "-fcxx-exceptions"
"E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp"
54>  Command 0 Result: -1073741819
54>  Command 0 Output:
54>
54>
54>  Command 0 Stderr:
54>  Stack dump:
54>
54>  0. Program arguments: E:/llvm/2013/Debug/bin/clang.EXE -cc1
-internal-isystem E:\llvm\2013\Debug\bin\..\lib\clang\3.6.0\include
-fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta
-Wno-thread-safety-negative -fcxx-exceptions
E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp
54>
54>  1. E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp:1677:2:
current parser token ';'
54>
54>  2. E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp:1633:1:
parsing namespace 'test_scoped_lockable'
54>
54>  3. E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp:1635:1:
parsing struct/union/class body 'TestScopedLockable'
54>
54>  4. E:\llvm\llvm\tools\clang\test\SemaCXX\warn-thread-safety-analysis.cpp:1672:15:
parsing function body 'foo5'
54>
54>  0x03584EB1 (0xCCCCCCCC 0x05FBB554 0x0358095C 0xDDDDDDDD),
clang::threadSafety::til::SExpr::opcode() + 0x11 bytes(s),
e:\llvm\llvm\tools\clang\include\clang\analysis\analyses\threadsafetytil.h,
line 254 + 0x11 byte(s)
54>
54>  0x0357DF63 (0xDDDDDDDD 0x05FBB564 0x0358135A 0xDDDDDDDD),
clang::threadSafety::til::Wildcard::classof() + 0x13 bytes(s),
e:\llvm\llvm\tools\clang\include\clang\analysis\analyses\threadsafetytil.h,
line 591 + 0x13 byte(s)
54>
54>  0x0358095C (0xDDDDDDDD 0x05FBBC0C 0x05FBB570 0x03581F9E),
llvm::isa_impl<clang::threadSafety::til::Wildcard,clang::threadSafety::til::SExpr,void>::doit()
+ 0xC bytes(s), e:\llvm\llvm\include\llvm\support\casting.h, line 56 +
0x9 byte(s)
54>
54>  0x0358135A (0xDDDDDDDD 0x05FBB580 0x03581FD3 0x05FBB57C),
llvm::isa_impl_cl<clang::threadSafety::til::Wildcard,clang::threadSafety::til::SExpr
const *>::doit() + 0x3A bytes(s),
e:\llvm\llvm\include\llvm\support\casting.h, line 96 + 0x9 byte(s)
54>
54>  0x03581F9E (0x05FBB57C 0xDDDDDDDD 0x05FBB58C 0x0356D9CC),
llvm::isa_impl_wrap<clang::threadSafety::til::Wildcard,clang::threadSafety::til::SExpr
const *,clang::threadSafety::til::SExpr const *>::doit() + 0xE
bytes(s), e:\llvm\llvm\include\llvm\support\casting.h, line 122 + 0xB
byte(s)
54>
54>  0x03581FD3 (0x05FBB5A4 0x05FBB598 0x0358464D 0x05FBB5A4),
llvm::isa_impl_wrap<clang::threadSafety::til::Wildcard,clang::threadSafety::til::SExpr
const * const,clang::threadSafety::til::SExpr const *>::doit() + 0x23
bytes(s), e:\llvm\llvm\include\llvm\support\casting.h, line 114 + 0x18
byte(s)
54>
54>  0x0356D9CC (0x05FBB5A4 0x05FBB5B0 0x035845EA 0x002C2830),
llvm::isa<clang::threadSafety::til::Wildcard,clang::threadSafety::til::SExpr
const *>() + 0xC bytes(s),
e:\llvm\llvm\include\llvm\support\casting.h, line 134 + 0x9 byte(s)
54>
54>  0x0358464D (0x002C2830 0xDDDDDDDD 0xCCCCCCCC 0x00295758),
clang::threadSafety::sx::matches() + 0x2D bytes(s),
e:\llvm\llvm\tools\clang\include\clang\analysis\analyses\threadsafetycommon.h,
line 54 + 0x9 byte(s)
54>
54>  0x035845EA (0x05FBB6EC 0x05FBB5DC 0x05FBB5CC 0x035670F5),
clang::threadSafety::CapabilityExpr::matches() + 0x3A bytes(s),
e:\llvm\llvm\tools\clang\include\clang\analysis\analyses\threadsafetycommon.h,
line 278 + 0x23 byte(s)
54>
54>  0x0355F33B (0x00000001 0x05FBB5E4 0x0356BD94 0x05FBBDDE),
<lambda_d6e0ee6982fd80115d3e880dc6316785>::operator()() + 0x2B
bytes(s), e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line
221
54>
54>  0x035670F5 (0x05FBBDDE 0x05FBBDE0 0x05FBC2BC 0x05FBB6EC),
std::_Find_if<unsigned short const
*,<lambda_d6e0ee6982fd80115d3e880dc6316785> >() + 0x25 bytes(s),
d:\program files (x86)\microsoft visual studio
12.0\vc\include\algorithm, line 44 + 0xF byte(s)
54>
54>  0x0356BD94 (0x05FBBDDC 0x05FBBDE0 0x05FBC2BC 0x05FBB6EC),
std::find_if<unsigned short const
*,<lambda_d6e0ee6982fd80115d3e880dc6316785> >() + 0x54 bytes(s),
d:\program files (x86)\microsoft visual studio
12.0\vc\include\algorithm, line 56 + 0x27 byte(s)
54>
54>  0x035825CB (0x05FBC2BC 0x05FBB6EC 0x05FBBBF8 0x05FBBC0C),
clang::threadSafety::FactSet::findLock() + 0x4B bytes(s),
e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line 219 +
0x2E byte(s)
54>
54>  0x03560821 (0x05FBBDD0 0x05FBBAEC 0x00009D67 0x00000001),
clang::threadSafety::ThreadSafetyAnalyzer::removeLock() + 0x1F1
bytes(s), e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line
974 + 0x15 byte(s)
54>
54>  0x035648B5 (0x05FBBD6C 0x0026CB50 0x00000000 0x05FBC2E4),
clang::threadSafety::BuildLockset::handleCall() + 0xAD5 bytes(s),
e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line 1558 +
0x34 byte(s)
54>
54>  0x0356272B (0x05FBC5D0 0x05FBC588 0xCCCCCCCC 0x002C28F8),
clang::threadSafety::ThreadSafetyAnalyzer::runAnalysis() + 0xD8B
bytes(s), e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line
2034
54>
54>  0x0355F0C4 (0x05FBC5D0 0x05FBC51C 0x05FBC6DC 0x05FBC96C),
clang::threadSafety::runThreadSafetyAnalysis() + 0x44 bytes(s),
e:\llvm\llvm\tools\clang\lib\analysis\threadsafety.cpp, line 2101
54>
54>  0x030DE2A3 (0xCDCDCDC5 0x0024EBA8 0x002AC070 0x00000000),
clang::sema::AnalysisBasedWarnings::IssueWarnings() + 0x7A3 bytes(s),
e:\llvm\llvm\tools\clang\lib\sema\analysisbasedwarnings.cpp, line 1958
+ 0x13 byte(s)
54>
54>  0x02CA8238 (0x05FBC838 0x002AC070 0x00000000 0x05FBC8D8),
clang::Sema::PopFunctionScopeInfo() + 0x98 bytes(s),
e:\llvm\llvm\tools\clang\lib\sema\sema.cpp, line 1099
54>
54>  0x02D3D7E4 (0x002AC070 0x002C07E8 0x00000000 0x0024DBA0),
clang::Sema::ActOnFinishFunctionBody() + 0x9E4 bytes(s),
e:\llvm\llvm\tools\clang\lib\sema\semadecl.cpp, line 10392
54>
54>  0x02D3CDF0 (0x002AC070 0x002C07E8 0x05FBC954 0x05FBC96C),
clang::Sema::ActOnFinishFunctionBody() + 0x20 bytes(s),
e:\llvm\llvm\tools\clang\lib\sema\semadecl.cpp, line 10209
54>
54>  0x02B0EF6F (0x002AC070 0x05FBC920 0x05FBC9B8 0x05FBC96C),
clang::Parser::ParseFunctionStatementBody() + 0x14F bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsestmt.cpp, line 1866 + 0x18
byte(s)
54>
54>  0x02B27D00 (0x0028F850 0x0028F850 0x05FBC9B8 0x02B27864),
clang::Parser::ParseLexedMethodDef() + 0x3F0 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsecxxinlinemethods.cpp, line 457
54>
54>  0x02B2650D (0x05FBCC24 0x05FBE4E8 0x0028F850 0x00000000),
clang::Parser::LexedMethod::ParseLexedMethodDefs() + 0x1D bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsecxxinlinemethods.cpp, line 254
54>
54>  0x02B27864 (0x001F2400 0x05FBD370 0x05FBE4E8 0xCCCCCCCC),
clang::Parser::ParseLexedMethodDefs() + 0x124 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsecxxinlinemethods.cpp, line 391
+ 0x23 byte(s)
54>
54>  0x02B1AFFE (0x00009A79 0x00009A80 0x05FBD294 0x00000011),
clang::Parser::ParseCXXMemberSpecification() + 0xB0E bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedeclcxx.cpp, line 2778
54>
54>  0x02B1A084 (0x00000064 0x00009A79 0x05FBD76C 0x05FBD6F0),
clang::Parser::ParseClassSpecifier() + 0x1564 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedeclcxx.cpp, line 1641
54>
54>  0x02AD1C87 (0x05FBD76C 0x05FBD6F0 0x00000003 0x00000005),
clang::Parser::ParseDeclarationSpecifiers() + 0x16D7 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedecl.cpp, line 3111
54>
54>  0x02AB03C8 (0x05FBDC90 0x05FBDCA8 0x05FBD76C 0x00000003),
clang::Parser::ParseDeclOrFunctionDefInternal() + 0x38 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parser.cpp, line 836
54>
54>  0x02AB0319 (0x05FBDC90 0x05FBDCA8 0x00000000 0x00000003),
clang::Parser::ParseDeclarationOrFunctionDefinition() + 0x89 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parser.cpp, line 904 + 0x1B byte(s)
54>
54>  0x02AAFD11 (0x05FBDC90 0x05FBDCA8 0x00000000 0x05FBE04C),
clang::Parser::ParseExternalDeclaration() + 0x9B1 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parser.cpp, line 762 + 0x16 byte(s)
54>
54>  0x02B16BAD (0x05FBDFFC 0x05FBDFE4 0x05FBDFCC 0x00000000),
clang::Parser::ParseInnerNamespace() + 0x8D bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedeclcxx.cpp, line 210
54>
54>  0x02B168D8 (0x00000000 0x05FBE408 0x00000000 0x05FBE46C),
clang::Parser::ParseNamespace() + 0xA18 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedeclcxx.cpp, line 189
54>
54>  0x02ACE07E (0x05FBE48C 0x05FBE374 0x00000000 0x05FBE408),
clang::Parser::ParseDeclaration() + 0x15E bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parsedecl.cpp, line 1329 + 0x1B
byte(s)
54>
54>  0x02AAF989 (0x05FBE48C 0x05FBE4B4 0x00000000 0x05FBE564),
clang::Parser::ParseExternalDeclaration() + 0x629 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parser.cpp, line 701 + 0x1D byte(s)
54>
54>  0x02AAC79F (0x05FBE51C 0x05FBE60C 0x05FBE574 0x00263C18),
clang::Parser::ParseTopLevelDecl() + 0x1DF bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parser.cpp, line 559 + 0x12 byte(s)
54>
54>  0x02AAAA68 (0x0024DBA0 0x00000000 0x00000000 0x05FBE590),
clang::ParseAST() + 0x1B8 bytes(s),
e:\llvm\llvm\tools\clang\lib\parse\parseast.cpp, line 145 + 0xC
byte(s)
54>
54>  0x01E34CB1 (0x05FBE5B8 0xCCCCCCCC 0xCCCCCCCC 0xCCCCCCCC),
clang::ASTFrontendAction::ExecuteAction() + 0x101 bytes(s),
e:\llvm\llvm\tools\clang\lib\frontend\frontendaction.cpp, line 522 +
0x30 byte(s)
54>
54>  0x01E3489E (0x05FBE6B0 0x00000000 0xCCCCCCCC 0xCCCCCCCC),
clang::FrontendAction::Execute() + 0x7E bytes(s),
e:\llvm\llvm\tools\clang\lib\frontend\frontendaction.cpp, line 423 +
0xF byte(s)
54>
54>  0x01DF7CA1 (0x001FBB88 0x05FBEBBC 0x00000000 0xCCCCCCCC),
clang::CompilerInstance::ExecuteAction() + 0x2A1 bytes(s),
e:\llvm\llvm\tools\clang\lib\frontend\compilerinstance.cpp, line 807
54>
54>  0x01F4AB5E (0x001F7EE8 0x05FBF938 0xCCCCCCCC 0xCCCCCCCC),
clang::ExecuteCompilerInvocation() + 0x30E bytes(s),
e:\llvm\llvm\tools\clang\lib\frontendtool\executecompilerinvocation.cpp,
line 222 + 0x11 byte(s)
54>
54>  0x00A6C87F (0x05FBF520 0x0000000A 0x001F6E60 0x009A1370),
cc1_main() + 0x2FF bytes(s),
e:\llvm\llvm\tools\clang\tools\driver\cc1_main.cpp, line 110 + 0xE
byte(s)
54>
54>  0x00A5A4B8 (0x05FBF518 0x0000000C 0x001F6E85 0x00000000),
ExecuteCC1Tool() + 0x78 bytes(s),
e:\llvm\llvm\tools\clang\tools\driver\driver.cpp, line 369 + 0x2B
byte(s)
54>
54>  0x00A5A81B (0x0000000C 0x001F4410 0x001EED60 0xBB9F99A5), main()
+ 0x2BB bytes(s), e:\llvm\llvm\tools\clang\tools\driver\driver.cpp,
line 412 + 0x33 byte(s)
54>
54>  0x038AD9E9 (0x05FBF99C 0x775E338A 0x7EFDE000 0x05FBF9DC),
__tmainCRTStartup() + 0x199 bytes(s),
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c, line 626 + 0x19 byte(s)
54>
54>  0x038ADB2D (0x7EFDE000 0x05FBF9DC 0x77C79F72 0x7EFDE000),
mainCRTStartup() + 0xD bytes(s),
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c, line 466
54>
54>  0x775E338A (0x7EFDE000 0x4F1AFA0D 0x00000000 0x00000000),
BaseThreadInitThunk() + 0x12 bytes(s)
54>
54>  0x77C79F72 (0x038ADB20 0x7EFDE000 0x00000000 0x00000000),
RtlInitializeExceptionChain() + 0x63 bytes(s)
54>
54>  0x77C79F45 (0x038ADB20 0x7EFDE000 0x00000000 0x00000000),
RtlInitializeExceptionChain() + 0x36 bytes(s)
54>
54>
54>
54>
54>  --
54>
54>  ********************
54>
54>  Testing Time: 130.64s
54>  ********************
54>  Failing Tests (1):
54>      Clang :: SemaCXX/warn-thread-safety-analysis.cpp
54>
54>    Expected Passes    : 7504
54>    Expected Failures  : 18
54>    Unsupported Tests  : 78
54>    Unexpected Failures: 1

Also, you may want to run your patch through clang-format as there
were some formatting issues such as "foo* bar" instead of "foo *bar".

~Aaron



More information about the cfe-commits mailing list