diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 31435485ef798ea434ef06f5961901ff321fc35c..9e23afcca3614e3506b115ff2e142c3970aa663a 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1180,6 +1180,7 @@ def AssertExclusiveLock : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>; } @@ -1189,6 +1190,7 @@ def AssertSharedLock : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; + let DuplicatesAllowedWhileMerging = 1; let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>; } diff --git a/test/SemaCXX/warn-thread-safety-analysis.cpp b/test/SemaCXX/warn-thread-safety-analysis.cpp index 6b0159064be4b31ecc43027a99e149db59e7c99a..7c0a73327b827910ec376e819ada8ad5ed94c5e9 100644 --- a/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -3616,8 +3616,14 @@ class Foo { EXCLUSIVE_TRYLOCK_FUNCTION(true, mu2_); bool readertrylock() SHARED_TRYLOCK_FUNCTION(true, mu1_) SHARED_TRYLOCK_FUNCTION(true, mu2_); + void assertBoth() ASSERT_EXCLUSIVE_LOCK(mu1_) + ASSERT_EXCLUSIVE_LOCK(mu2_); + void assertShared() ASSERT_SHARED_LOCK(mu1_) + ASSERT_SHARED_LOCK(mu2_); void test(); + void testAssert(); + void testAssertShared(); }; @@ -3676,6 +3682,21 @@ void Foo::test() { } } +// Force duplication of attributes +void Foo::assertBoth() { } +void Foo::assertShared() { } + +void Foo::testAssert() { + assertBoth(); + a = 0; + b = 0; +} + +void Foo::testAssertShared() { + assertShared(); + int zz = a + b; +} + } // end namespace MultipleAttributeTest