r182170 - Thread safety analysis: add two new attributes to the thread safety analysis:
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Mon May 20 01:23:10 PDT 2013
Hi,
there is a use-after-free in ThreadSafetyAnalyzer::intersectAndWarn.
FSet1.addLock() eventually calls FactManager::Facts.push_back(), which
invalidates all references to Facts elements.
ThreadSafetyAnalyzer::intersectAndWarn keeps one of those references
(LDat2) across the call to FSet1.addLock().
ERROR: AddressSanitizer: heap-use-after-free on address 0x61300000bf60
at pc 0x512e049 bp 0x7fffd977f790 sp 0x7fffd977f788
READ of size 1 at 0x61300000bf60 thread T0
#0 0x512e048 in (anonymous
namespace)::ThreadSafetyAnalyzer::intersectAndWarn((anonymous
namespace)::FactSet&, (anonymous namespace)::FactSet const&,
clang::SourceLocation, clang::thread_safety::LockErrorKind,
clang::thread_safety::LockErrorKind, bool)
tools/clang/lib/Analysis/ThreadSafety.cpp:2207
#1 0x5120b99 in intersectAndWarn
tools/clang/lib/Analysis/ThreadSafety.cpp:1471
#2 0x5120b99 in (anonymous
namespace)::ThreadSafetyAnalyzer::runAnalysis(clang::AnalysisDeclContext&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2443
#3 0x5115ad6 in
clang::thread_safety::runThreadSafetyAnalysis(clang::AnalysisDeclContext&,
clang::thread_safety::ThreadSafetyHandler&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2587
#4 0x479b646 in
clang::sema::AnalysisBasedWarnings::IssueWarnings(clang::sema::AnalysisBasedWarnings::Policy,
clang::sema::FunctionScopeInfo*, clang::Decl const*, clang::BlockExpr
const*) tools/clang/lib/Sema/AnalysisBasedWarnings.cpp:1605
#5 0x3d6414f in
clang::Sema::PopFunctionScopeInfo(clang::sema::AnalysisBasedWarnings::Policy
const*, clang::Decl const*, clang::BlockExpr const*)
tools/clang/lib/Sema/Sema.cpp:1028
#6 0x3f6d6f0 in clang::Sema::ActOnFinishFunctionBody(clang::Decl*,
clang::Stmt*, bool) tools/clang/lib/Sema/SemaDecl.cpp:9021
#7 0x369c6c8 in
clang::Parser::ParseFunctionStatementBody(clang::Decl*,
clang::Parser::ParseScope&) tools/clang/lib/Parse/ParseStmt.cpp:2403
#8 0x3512200 in
clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&,
clang::Parser::ParsedTemplateInfo const&,
clang::Parser::LateParsedAttrList*)
tools/clang/lib/Parse/Parser.cpp:1113
#9 0x354ea70 in
clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, unsigned int,
bool, clang::SourceLocation*, clang::Parser::ForRangeInit*)
tools/clang/lib/Parse/ParseDecl.cpp:1621
#10 0x351027d in
clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec&, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:891
#11 0x350f283 in
clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:907
#12 0x350c3f4 in
clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*) tools/clang/lib/Parse/Parser.cpp:772
#13 0x3509f8f in
clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&)
tools/clang/lib/Parse/Parser.cpp:577
#14 0x34fca0b in clang::ParseAST(clang::Sema&, bool, bool)
tools/clang/lib/Parse/ParseAST.cpp:144
#15 0x32933d9 in clang::FrontendAction::Execute()
tools/clang/lib/Frontend/FrontendAction.cpp:378
#16 0x322ec4e in
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
tools/clang/lib/Frontend/CompilerInstance.cpp:685
#17 0x2c8fc56 in
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:236
#18 0x6f8f9e in cc1_main(char const**, char const**, char const*,
void*) tools/clang/tools/driver/cc1_main.cpp:99
#19 0x6ee153 in main tools/clang/tools/driver/driver.cpp:357
0x61300000bf60 is located 96 bytes inside of 384-byte region
[0x61300000bf00,0x61300000c080)
#0 0x6dc1d5 in operator delete(void*)
projects/compiler-rt/lib/asan/asan_new_delete.cc:83
#1 0x512c29d in deallocate
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/ext/new_allocator.h:98
#2 0x512c29d in size
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_vector.h:156
#3 0x512c29d in FactEntry
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_vector.h:834
#4 0x512c29d in newLock tools/clang/lib/Analysis/ThreadSafety.cpp:810
#5 0x512c29d in (anonymous namespace)::FactSet::addLock((anonymous
namespace)::FactManager&, (anonymous namespace)::SExpr const&,
(anonymous namespace)::LockData const&)
tools/clang/lib/Analysis/ThreadSafety.cpp:845
#6 0x512d4ec in (anonymous
namespace)::ThreadSafetyAnalyzer::intersectAndWarn((anonymous
namespace)::FactSet&, (anonymous namespace)::FactSet const&,
clang::SourceLocation, clang::thread_safety::LockErrorKind,
clang::thread_safety::LockErrorKind, bool)
tools/clang/lib/Analysis/ThreadSafety.cpp:2204
#7 0x5120b99 in intersectAndWarn
tools/clang/lib/Analysis/ThreadSafety.cpp:1471
#8 0x5120b99 in (anonymous
namespace)::ThreadSafetyAnalyzer::runAnalysis(clang::AnalysisDeclContext&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2443
#9 0x5115ad6 in
clang::thread_safety::runThreadSafetyAnalysis(clang::AnalysisDeclContext&,
clang::thread_safety::ThreadSafetyHandler&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2587
#10 0x479b646 in
clang::sema::AnalysisBasedWarnings::IssueWarnings(clang::sema::AnalysisBasedWarnings::Policy,
clang::sema::FunctionScopeInfo*, clang::Decl const*, clang::BlockExpr
const*) tools/clang/lib/Sema/AnalysisBasedWarnings.cpp:1605
#11 0x3d6414f in
clang::Sema::PopFunctionScopeInfo(clang::sema::AnalysisBasedWarnings::Policy
const*, clang::Decl const*, clang::BlockExpr const*)
tools/clang/lib/Sema/Sema.cpp:1028
#12 0x3f6d6f0 in
clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)
tools/clang/lib/Sema/SemaDecl.cpp:9021
#13 0x369c6c8 in
clang::Parser::ParseFunctionStatementBody(clang::Decl*,
clang::Parser::ParseScope&) tools/clang/lib/Parse/ParseStmt.cpp:2403
#14 0x3512200 in
clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&,
clang::Parser::ParsedTemplateInfo const&,
clang::Parser::LateParsedAttrList*)
tools/clang/lib/Parse/Parser.cpp:1113
#15 0x354ea70 in
clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, unsigned int,
bool, clang::SourceLocation*, clang::Parser::ForRangeInit*)
tools/clang/lib/Parse/ParseDecl.cpp:1621
#16 0x351027d in
clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec&, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:891
#17 0x350f283 in
clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:907
#18 0x350c3f4 in
clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*) tools/clang/lib/Parse/Parser.cpp:772
#19 0x3509f8f in
clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&)
tools/clang/lib/Parse/Parser.cpp:577
#20 0x34fca0b in clang::ParseAST(clang::Sema&, bool, bool)
tools/clang/lib/Parse/ParseAST.cpp:144
#21 0x32933d9 in clang::FrontendAction::Execute()
tools/clang/lib/Frontend/FrontendAction.cpp:378
#22 0x322ec4e in
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
tools/clang/lib/Frontend/CompilerInstance.cpp:685
#23 0x2c8fc56 in
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:236
#24 0x6f8f9e in cc1_main(char const**, char const**, char const*,
void*) tools/clang/tools/driver/cc1_main.cpp:99
#25 0x6ee153 in main tools/clang/tools/driver/driver.cpp:357
previously allocated by thread T0 here:
#0 0x6dbf15 in operator new(unsigned long)
projects/compiler-rt/lib/asan/asan_new_delete.cc:52
#1 0x512baf0 in allocate
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/ext/new_allocator.h:92
#2 0x512baf0 in size
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_vector.h:150
#3 0x512baf0 in FactEntry
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_vector.h:834
#4 0x512baf0 in newLock tools/clang/lib/Analysis/ThreadSafety.cpp:810
#5 0x512baf0 in (anonymous namespace)::FactSet::addLock((anonymous
namespace)::FactManager&, (anonymous namespace)::SExpr const&,
(anonymous namespace)::LockData const&)
tools/clang/lib/Analysis/ThreadSafety.cpp:845
#6 0x51254ab in (anonymous
namespace)::ThreadSafetyAnalyzer::addLock((anonymous
namespace)::FactSet&, (anonymous namespace)::SExpr const&, (anonymous
namespace)::LockData const&)
tools/clang/lib/Analysis/ThreadSafety.cpp:1492
#7 0x5129424 in (anonymous
namespace)::BuildLockset::handleCall(clang::Expr*, clang::NamedDecl
const*, clang::VarDecl*)
tools/clang/lib/Analysis/ThreadSafety.cpp:2020
#8 0x512137c in Visit
llvm_build_asan/tools/clang/include/clang/AST/StmtNodes.inc:293
#9 0x512137c in (anonymous
namespace)::ThreadSafetyAnalyzer::runAnalysis(clang::AnalysisDeclContext&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2494
#10 0x5115ad6 in
clang::thread_safety::runThreadSafetyAnalysis(clang::AnalysisDeclContext&,
clang::thread_safety::ThreadSafetyHandler&)
tools/clang/lib/Analysis/ThreadSafety.cpp:2587
#11 0x479b646 in
clang::sema::AnalysisBasedWarnings::IssueWarnings(clang::sema::AnalysisBasedWarnings::Policy,
clang::sema::FunctionScopeInfo*, clang::Decl const*, clang::BlockExpr
const*) tools/clang/lib/Sema/AnalysisBasedWarnings.cpp:1605
#12 0x3d6414f in
clang::Sema::PopFunctionScopeInfo(clang::sema::AnalysisBasedWarnings::Policy
const*, clang::Decl const*, clang::BlockExpr const*)
tools/clang/lib/Sema/Sema.cpp:1028
#13 0x3f6d6f0 in
clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool)
tools/clang/lib/Sema/SemaDecl.cpp:9021
#14 0x369c6c8 in
clang::Parser::ParseFunctionStatementBody(clang::Decl*,
clang::Parser::ParseScope&) tools/clang/lib/Parse/ParseStmt.cpp:2403
#15 0x3512200 in
clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&,
clang::Parser::ParsedTemplateInfo const&,
clang::Parser::LateParsedAttrList*)
tools/clang/lib/Parse/Parser.cpp:1113
#16 0x354ea70 in
clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, unsigned int,
bool, clang::SourceLocation*, clang::Parser::ForRangeInit*)
tools/clang/lib/Parse/ParseDecl.cpp:1621
#17 0x351027d in
clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec&, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:891
#18 0x350f283 in
clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*, clang::AccessSpecifier)
tools/clang/lib/Parse/Parser.cpp:907
#19 0x350c3f4 in
clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&,
clang::ParsingDeclSpec*) tools/clang/lib/Parse/Parser.cpp:772
#20 0x3509f8f in
clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&)
tools/clang/lib/Parse/Parser.cpp:577
#21 0x34fca0b in clang::ParseAST(clang::Sema&, bool, bool)
tools/clang/lib/Parse/ParseAST.cpp:144
#22 0x32933d9 in clang::FrontendAction::Execute()
tools/clang/lib/Frontend/FrontendAction.cpp:378
#23 0x322ec4e in
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
tools/clang/lib/Frontend/CompilerInstance.cpp:685
#24 0x2c8fc56 in
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:236
#25 0x6f8f9e in cc1_main(char const**, char const**, char const*,
void*) tools/clang/tools/driver/cc1_main.cpp:99
#26 0x6ee153 in main tools/clang/tools/driver/driver.cpp:357
On Sat, May 18, 2013 at 1:02 AM, DeLesley Hutchins <delesley at google.com> wrote:
> Author: delesley
> Date: Fri May 17 18:02:59 2013
> New Revision: 182170
>
> URL: http://llvm.org/viewvc/llvm-project?rev=182170&view=rev
> Log:
> Thread safety analysis: add two new attributes to the thread safety analysis:
> assert_exclusive_lock and assert_shared_lock. These attributes are used to
> mark functions that dynamically check (i.e. assert) that a lock is held.
>
> Modified:
> cfe/trunk/include/clang/Basic/Attr.td
> cfe/trunk/lib/Analysis/ThreadSafety.cpp
> cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
> cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=182170&r1=182169&r2=182170&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Fri May 17 18:02:59 2013
> @@ -852,6 +852,20 @@ def SharedLockFunction : InheritableAttr
> let TemplateDependent = 1;
> }
>
> +def AssertExclusiveLock : InheritableAttr {
> + let Spellings = [GNU<"assert_exclusive_lock">];
> + let Args = [VariadicExprArgument<"Args">];
> + let LateParsed = 1;
> + let TemplateDependent = 1;
> +}
> +
> +def AssertSharedLock : InheritableAttr {
> + let Spellings = [GNU<"assert_shared_lock">];
> + let Args = [VariadicExprArgument<"Args">];
> + let LateParsed = 1;
> + let TemplateDependent = 1;
> +}
> +
> // The first argument is an integer or boolean value specifying the return value
> // of a successful lock acquisition.
> def ExclusiveTrylockFunction : InheritableAttr {
>
> Modified: cfe/trunk/lib/Analysis/ThreadSafety.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ThreadSafety.cpp?rev=182170&r1=182169&r2=182170&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/ThreadSafety.cpp (original)
> +++ cfe/trunk/lib/Analysis/ThreadSafety.cpp Fri May 17 18:02:59 2013
> @@ -750,16 +750,18 @@ struct LockData {
> ///
> /// FIXME: add support for re-entrant locking and lock up/downgrading
> LockKind LKind;
> + bool Asserted; // for asserted locks
> bool Managed; // for ScopedLockable objects
> SExpr UnderlyingMutex; // for ScopedLockable objects
>
> - LockData(SourceLocation AcquireLoc, LockKind LKind, bool M = false)
> - : AcquireLoc(AcquireLoc), LKind(LKind), Managed(M),
> + LockData(SourceLocation AcquireLoc, LockKind LKind, bool M=false,
> + bool Asrt=false)
> + : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(Asrt), Managed(M),
> UnderlyingMutex(Decl::EmptyShell())
> {}
>
> LockData(SourceLocation AcquireLoc, LockKind LKind, const SExpr &Mu)
> - : AcquireLoc(AcquireLoc), LKind(LKind), Managed(false),
> + : AcquireLoc(AcquireLoc), LKind(LKind), Asserted(false), Managed(false),
> UnderlyingMutex(Mu)
> {}
>
> @@ -1484,7 +1486,8 @@ void ThreadSafetyAnalyzer::addLock(FactS
> return;
>
> if (FSet.findLock(FactMan, Mutex)) {
> - Handler.handleDoubleLock(Mutex.toString(), LDat.AcquireLoc);
> + if (!LDat.Asserted)
> + Handler.handleDoubleLock(Mutex.toString(), LDat.AcquireLoc);
> } else {
> FSet.addLock(FactMan, Mutex, LDat);
> }
> @@ -1909,6 +1912,7 @@ void BuildLockset::checkPtAccess(const E
> /// the same signature as const method calls can be also treated as reads.
> ///
> void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
> + SourceLocation Loc = Exp->getExprLoc();
> const AttrVec &ArgAttrs = D->getAttrs();
> MutexIDList ExclusiveLocksToAdd;
> MutexIDList SharedLocksToAdd;
> @@ -1933,6 +1937,32 @@ void BuildLockset::handleCall(Expr *Exp,
> break;
> }
>
> + // An assert will add a lock to the lockset, but will not generate
> + // a warning if it is already there, and will not generate a warning
> + // if it is not removed.
> + case attr::AssertExclusiveLock: {
> + AssertExclusiveLockAttr *A = cast<AssertExclusiveLockAttr>(At);
> +
> + MutexIDList AssertLocks;
> + Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
> + for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
> + Analyzer->addLock(FSet, AssertLocks[i],
> + LockData(Loc, LK_Exclusive, false, true));
> + }
> + break;
> + }
> + case attr::AssertSharedLock: {
> + AssertSharedLockAttr *A = cast<AssertSharedLockAttr>(At);
> +
> + MutexIDList AssertLocks;
> + Analyzer->getMutexIDs(AssertLocks, A, Exp, D, VD);
> + for (unsigned i=0,n=AssertLocks.size(); i<n; ++i) {
> + Analyzer->addLock(FSet, AssertLocks[i],
> + LockData(Loc, LK_Shared, false, true));
> + }
> + break;
> + }
> +
> // When we encounter an unlock function, we need to remove unlocked
> // mutexes from the lockset, and flag a warning if they are not there.
> case attr::UnlockFunction: {
> @@ -1986,7 +2016,6 @@ void BuildLockset::handleCall(Expr *Exp,
> }
>
> // Add locks.
> - SourceLocation Loc = Exp->getExprLoc();
> for (unsigned i=0,n=ExclusiveLocksToAdd.size(); i<n; ++i) {
> Analyzer->addLock(FSet, ExclusiveLocksToAdd[i],
> LockData(Loc, LK_Exclusive, isScopedVar));
> @@ -2165,7 +2194,7 @@ void ThreadSafetyAnalyzer::intersectAndW
> const SExpr &FSet2Mutex = FactMan[*I].MutID;
> const LockData &LDat2 = FactMan[*I].LDat;
>
> - if (const LockData *LDat1 = FSet1.findLock(FactMan, FSet2Mutex)) {
> + if (LockData *LDat1 = FSet1.findLock(FactMan, FSet2Mutex)) {
> if (LDat1->LKind != LDat2.LKind) {
> Handler.handleExclusiveAndShared(FSet2Mutex.toString(),
> LDat2.AcquireLoc,
> @@ -2175,6 +2204,10 @@ void ThreadSafetyAnalyzer::intersectAndW
> FSet1.addLock(FactMan, FSet2Mutex, LDat2);
> }
> }
> + if (LDat1->Asserted && !LDat2.Asserted) {
> + // The non-asserted lock is the one we want to track.
> + *LDat1 = LDat2;
> + }
> } else {
> if (LDat2.UnderlyingMutex.isValid()) {
> if (FSet2.findLock(FactMan, LDat2.UnderlyingMutex)) {
> @@ -2186,7 +2219,7 @@ void ThreadSafetyAnalyzer::intersectAndW
> JoinLoc, LEK1);
> }
> }
> - else if (!LDat2.Managed && !FSet2Mutex.isUniversal())
> + else if (!LDat2.Managed && !FSet2Mutex.isUniversal() && !LDat2.Asserted)
> Handler.handleMutexHeldEndOfScope(FSet2Mutex.toString(),
> LDat2.AcquireLoc,
> JoinLoc, LEK1);
> @@ -2209,7 +2242,7 @@ void ThreadSafetyAnalyzer::intersectAndW
> JoinLoc, LEK1);
> }
> }
> - else if (!LDat1.Managed && !FSet1Mutex.isUniversal())
> + else if (!LDat1.Managed && !FSet1Mutex.isUniversal() && !LDat1.Asserted)
> Handler.handleMutexHeldEndOfScope(FSet1Mutex.toString(),
> LDat1.AcquireLoc,
> JoinLoc, LEK2);
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=182170&r1=182169&r2=182170&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri May 17 18:02:59 2013
> @@ -788,6 +788,34 @@ static void handleExclusiveLockFunctionA
> Attr.getAttributeSpellingListIndex()));
> }
>
> +static void handleAssertSharedLockAttr(Sema &S, Decl *D,
> + const AttributeList &Attr) {
> + SmallVector<Expr*, 1> Args;
> + if (!checkLockFunAttrCommon(S, D, Attr, Args))
> + return;
> +
> + unsigned Size = Args.size();
> + Expr **StartArg = Size == 0 ? 0 : &Args[0];
> + D->addAttr(::new (S.Context)
> + AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size,
> + Attr.getAttributeSpellingListIndex()));
> +}
> +
> +static void handleAssertExclusiveLockAttr(Sema &S, Decl *D,
> + const AttributeList &Attr) {
> + SmallVector<Expr*, 1> Args;
> + if (!checkLockFunAttrCommon(S, D, Attr, Args))
> + return;
> +
> + unsigned Size = Args.size();
> + Expr **StartArg = Size == 0 ? 0 : &Args[0];
> + D->addAttr(::new (S.Context)
> + AssertExclusiveLockAttr(Attr.getRange(), S.Context,
> + StartArg, Size,
> + Attr.getAttributeSpellingListIndex()));
> +}
> +
> +
> static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
> const AttributeList &Attr,
> SmallVector<Expr*, 2> &Args) {
> @@ -4918,6 +4946,12 @@ static void ProcessInheritableDeclAttr(S
> break;
>
> // Thread safety attributes:
> + case AttributeList::AT_AssertExclusiveLock:
> + handleAssertExclusiveLockAttr(S, D, Attr);
> + break;
> + case AttributeList::AT_AssertSharedLock:
> + handleAssertSharedLockAttr(S, D, Attr);
> + break;
> case AttributeList::AT_GuardedVar:
> handleGuardedVarAttr(S, D, Attr);
> break;
>
> Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=182170&r1=182169&r2=182170&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
> +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Fri May 17 18:02:59 2013
> @@ -11,8 +11,10 @@
> #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
> #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
> #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
> -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
> -#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
> +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
> +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
> +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
> +#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__)))
> #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
> #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
> #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
> @@ -33,6 +35,9 @@ class __attribute__((lockable)) Mutex {
> bool TryLock() __attribute__((exclusive_trylock_function(true)));
> bool ReaderTryLock() __attribute__((shared_trylock_function(true)));
> void LockWhen(const int &cond) __attribute__((exclusive_lock_function));
> +
> + void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
> + void AssertReaderHeld() ASSERT_SHARED_LOCK();
> };
>
> class __attribute__((scoped_lockable)) MutexLock {
> @@ -3985,3 +3990,105 @@ private:
>
> } // end namespace LockUnlockFunctionTest
>
> +
> +namespace AssertHeldTest {
> +
> +class Foo {
> +public:
> + int c;
> + int a GUARDED_BY(mu_);
> + Mutex mu_;
> +
> + void test1() {
> + mu_.AssertHeld();
> + int b = a;
> + a = 0;
> + }
> +
> + void test2() {
> + mu_.AssertReaderHeld();
> + int b = a;
> + a = 0; // expected-warning {{writing variable 'a' requires locking 'mu_' exclusively}}
> + }
> +
> + void test3() {
> + if (c) {
> + mu_.AssertHeld();
> + }
> + else {
> + mu_.AssertHeld();
> + }
> + int b = a;
> + a = 0;
> + }
> +
> + void test4() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
> + mu_.AssertHeld();
> + int b = a;
> + a = 0;
> + }
> +
> + void test5() UNLOCK_FUNCTION(mu_) {
> + mu_.AssertHeld();
> + mu_.Unlock();
> + }
> +
> + void test6() {
> + mu_.AssertHeld();
> + mu_.Unlock();
> + } // should this be a warning?
> +
> + void test7() {
> + if (c) {
> + mu_.AssertHeld();
> + }
> + else {
> + mu_.Lock();
> + }
> + int b = a;
> + a = 0;
> + mu_.Unlock();
> + }
> +
> + void test8() {
> + if (c) {
> + mu_.Lock();
> + }
> + else {
> + mu_.AssertHeld();
> + }
> + int b = a;
> + a = 0;
> + mu_.Unlock();
> + }
> +
> + void test9() {
> + if (c) {
> + mu_.AssertHeld();
> + }
> + else {
> + mu_.Lock(); // expected-note {{mutex acquired here}}
> + }
> + } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
> +
> + void test10() {
> + if (c) {
> + mu_.Lock(); // expected-note {{mutex acquired here}}
> + }
> + else {
> + mu_.AssertHeld();
> + }
> + } // expected-warning {{mutex 'mu_' is still locked at the end of function}}
> +
> + void assertMu() ASSERT_EXCLUSIVE_LOCK(mu_);
> +
> + void test11() {
> + assertMu();
> + int b = a;
> + a = 0;
> + }
> +};
> +
> +} // end namespace AssertHeldTest
> +
> +
>
> Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp?rev=182170&r1=182169&r2=182170&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp (original)
> +++ cfe/trunk/test/SemaCXX/warn-thread-safety-parsing.cpp Fri May 17 18:02:59 2013
> @@ -8,8 +8,10 @@
> #define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
> #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
> #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
> -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
> -#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
> +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))
> +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))
> +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))
> +#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__)))
> #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))
> #define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))
> #define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))
> @@ -24,7 +26,15 @@
>
> class LOCKABLE Mutex {
> public:
> - void Lock();
> + void Lock() EXCLUSIVE_LOCK_FUNCTION();
> + void ReaderLock() SHARED_LOCK_FUNCTION();
> + void Unlock() UNLOCK_FUNCTION();
> +
> + bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
> + bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
> +
> + void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
> + void AssertReaderHeld() ASSERT_SHARED_LOCK();
> };
>
> class UnlockableMu{
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list