Skip to content

Commit c9d5800

Browse files
committed
Revert "Support guarded_by attribute and related attributes inside C structs and support late parsing them (#94216)"
This reverts commit af0d712. Reverting due to likely regression: #94216 (comment)
1 parent f074500 commit c9d5800

File tree

10 files changed

+26
-213
lines changed

10 files changed

+26
-213
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,10 +471,6 @@ Attribute Changes in Clang
471471
size_t count;
472472
};
473473
474-
- The ``guarded_by``, ``pt_guarded_by``, ``acquired_after``, ``acquired_before``
475-
attributes now support referencing struct members in C. The arguments are also
476-
now late parsed when ``-fexperimental-late-parse-attributes`` is passed like
477-
for ``counted_by``.
478474
479475
Improvements to Clang's diagnostics
480476
-----------------------------------

clang/docs/ThreadSafetyAnalysis.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,12 @@ doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
764764
aliasing for MutexLocker, but does so only for that particular pattern.
765765

766766

767+
ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
768+
-------------------------------------------------------------------------
769+
770+
To be fixed in a future update.
771+
772+
767773
.. _mutexheader:
768774

769775
mutex.h

clang/include/clang/Basic/Attr.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3633,7 +3633,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
36333633
def GuardedBy : InheritableAttr {
36343634
let Spellings = [GNU<"guarded_by">];
36353635
let Args = [ExprArgument<"Arg">];
3636-
let LateParsed = LateAttrParseExperimentalExt;
3636+
let LateParsed = LateAttrParseStandard;
36373637
let TemplateDependent = 1;
36383638
let ParseArgumentsAsUnevaluated = 1;
36393639
let InheritEvenIfAlreadyPresent = 1;
@@ -3644,7 +3644,7 @@ def GuardedBy : InheritableAttr {
36443644
def PtGuardedBy : InheritableAttr {
36453645
let Spellings = [GNU<"pt_guarded_by">];
36463646
let Args = [ExprArgument<"Arg">];
3647-
let LateParsed = LateAttrParseExperimentalExt;
3647+
let LateParsed = LateAttrParseStandard;
36483648
let TemplateDependent = 1;
36493649
let ParseArgumentsAsUnevaluated = 1;
36503650
let InheritEvenIfAlreadyPresent = 1;
@@ -3655,7 +3655,7 @@ def PtGuardedBy : InheritableAttr {
36553655
def AcquiredAfter : InheritableAttr {
36563656
let Spellings = [GNU<"acquired_after">];
36573657
let Args = [VariadicExprArgument<"Args">];
3658-
let LateParsed = LateAttrParseExperimentalExt;
3658+
let LateParsed = LateAttrParseStandard;
36593659
let TemplateDependent = 1;
36603660
let ParseArgumentsAsUnevaluated = 1;
36613661
let InheritEvenIfAlreadyPresent = 1;
@@ -3666,7 +3666,7 @@ def AcquiredAfter : InheritableAttr {
36663666
def AcquiredBefore : InheritableAttr {
36673667
let Spellings = [GNU<"acquired_before">];
36683668
let Args = [VariadicExprArgument<"Args">];
3669-
let LateParsed = LateAttrParseExperimentalExt;
3669+
let LateParsed = LateAttrParseStandard;
36703670
let TemplateDependent = 1;
36713671
let ParseArgumentsAsUnevaluated = 1;
36723672
let InheritEvenIfAlreadyPresent = 1;

clang/include/clang/Parse/Parser.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,20 +3128,6 @@ class Parser : public CodeCompletionHandler {
31283128
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
31293129
ParsedAttr::Form Form);
31303130

3131-
void ParseGuardedByAttribute(IdentifierInfo &AttrName,
3132-
SourceLocation AttrNameLoc,
3133-
ParsedAttributes &Attrs,
3134-
IdentifierInfo *ScopeName,
3135-
SourceLocation ScopeLoc, SourceLocation *EndLoc,
3136-
ParsedAttr::Form Form);
3137-
3138-
void ParseAcquiredAttribute(IdentifierInfo &AttrName,
3139-
SourceLocation AttrNameLoc,
3140-
ParsedAttributes &Attrs,
3141-
IdentifierInfo *ScopeName,
3142-
SourceLocation ScopeLoc, SourceLocation *EndLoc,
3143-
ParsedAttr::Form Form);
3144-
31453131
void ParseTypeofSpecifier(DeclSpec &DS);
31463132
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
31473133
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5142,7 +5142,7 @@ class Sema final : public SemaBase {
51425142
enum ExpressionKind {
51435143
EK_Decltype,
51445144
EK_TemplateArgument,
5145-
EK_AttrArgument,
5145+
EK_BoundsAttrArgument,
51465146
EK_Other
51475147
} ExprContext;
51485148

@@ -5249,9 +5249,10 @@ class Sema final : public SemaBase {
52495249
return const_cast<Sema *>(this)->parentEvaluationContext();
52505250
};
52515251

5252-
bool isAttrContext() const {
5252+
bool isBoundsAttrContext() const {
52535253
return ExprEvalContexts.back().ExprContext ==
5254-
ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument;
5254+
ExpressionEvaluationContextRecord::ExpressionKind::
5255+
EK_BoundsAttrArgument;
52555256
}
52565257

52575258
/// Increment when we find a reference; decrement when we find an ignored

clang/lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -671,16 +671,6 @@ void Parser::ParseGNUAttributeArgs(
671671
ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
672672
Form);
673673
return;
674-
} else if (AttrKind == ParsedAttr::AT_GuardedBy ||
675-
AttrKind == ParsedAttr::AT_PtGuardedBy) {
676-
ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
677-
EndLoc, Form);
678-
return;
679-
} else if (AttrKind == ParsedAttr::AT_AcquiredAfter ||
680-
AttrKind == ParsedAttr::AT_AcquiredBefore) {
681-
ParseAcquiredAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
682-
EndLoc, Form);
683-
return;
684674
} else if (AttrKind == ParsedAttr::AT_CXXAssume) {
685675
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
686676
return;
@@ -3340,112 +3330,6 @@ void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
33403330
}
33413331
}
33423332

3343-
/// GuardedBy attributes (e.g., guarded_by):
3344-
/// AttrName '(' expression ')'
3345-
void Parser::ParseGuardedByAttribute(
3346-
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
3347-
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
3348-
SourceLocation *EndLoc, ParsedAttr::Form Form) {
3349-
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
3350-
3351-
BalancedDelimiterTracker Parens(*this, tok::l_paren);
3352-
Parens.consumeOpen();
3353-
3354-
if (Tok.is(tok::r_paren)) {
3355-
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
3356-
Parens.consumeClose();
3357-
return;
3358-
}
3359-
3360-
ArgsVector ArgExprs;
3361-
// Don't evaluate argument when the attribute is ignored.
3362-
using ExpressionKind =
3363-
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
3364-
EnterExpressionEvaluationContext EC(
3365-
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
3366-
ExpressionKind::EK_AttrArgument);
3367-
3368-
ExprResult ArgExpr(
3369-
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
3370-
3371-
if (ArgExpr.isInvalid()) {
3372-
Parens.skipToEnd();
3373-
return;
3374-
}
3375-
3376-
ArgExprs.push_back(ArgExpr.get());
3377-
3378-
auto RParens = Tok.getLocation();
3379-
auto &AL =
3380-
*Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, RParens), ScopeName,
3381-
ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form);
3382-
3383-
if (EndLoc)
3384-
*EndLoc = RParens;
3385-
3386-
if (!Tok.is(tok::r_paren)) {
3387-
Diag(Tok.getLocation(), diag::err_attribute_wrong_number_arguments)
3388-
<< AL << 1;
3389-
Parens.skipToEnd();
3390-
return;
3391-
}
3392-
3393-
Parens.consumeClose();
3394-
}
3395-
3396-
/// Acquired attributes (e.g., acquired_before, acquired_after):
3397-
/// AttrName '(' expression-list ')'
3398-
void Parser::ParseAcquiredAttribute(
3399-
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
3400-
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
3401-
SourceLocation *EndLoc, ParsedAttr::Form Form) {
3402-
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
3403-
3404-
BalancedDelimiterTracker Parens(*this, tok::l_paren);
3405-
Parens.consumeOpen();
3406-
3407-
if (Tok.is(tok::r_paren)) {
3408-
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
3409-
Parens.consumeClose();
3410-
return;
3411-
}
3412-
3413-
auto ArgStart = Tok.getLocation();
3414-
3415-
ArgsVector ArgExprs;
3416-
3417-
do {
3418-
3419-
// Don't evaluate argument when the attribute is ignored.
3420-
using ExpressionKind =
3421-
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
3422-
EnterExpressionEvaluationContext EC(
3423-
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
3424-
nullptr, ExpressionKind::EK_AttrArgument);
3425-
3426-
ExprResult ArgExpr(
3427-
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
3428-
3429-
if (ArgExpr.isInvalid()) {
3430-
Parens.skipToEnd();
3431-
return;
3432-
}
3433-
3434-
ArgExprs.push_back(ArgExpr.get());
3435-
3436-
} while (TryConsumeToken(tok::comma));
3437-
3438-
auto ArgEnd = Tok.getLocation();
3439-
3440-
Attrs.addNew(&AttrName, SourceRange(ArgStart, ArgEnd), ScopeName, ScopeLoc,
3441-
ArgExprs.data(), ArgExprs.size(), Form);
3442-
3443-
if (EndLoc)
3444-
*EndLoc = ArgEnd;
3445-
3446-
Parens.consumeClose();
3447-
}
3448-
34493333
/// Bounds attributes (e.g., counted_by):
34503334
/// AttrName '(' expression ')'
34513335
void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
@@ -3471,7 +3355,7 @@ void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
34713355
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
34723356
EnterExpressionEvaluationContext EC(
34733357
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
3474-
ExpressionKind::EK_AttrArgument);
3358+
ExpressionKind::EK_BoundsAttrArgument);
34753359

34763360
ExprResult ArgExpr(
34773361
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));

clang/lib/Sema/SemaExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2723,7 +2723,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
27232723
// appertains to a type of C struct field such that the name lookup
27242724
// within a struct finds the member name, which is not the case for other
27252725
// contexts in C.
2726-
if (isAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
2726+
if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
27272727
// See if this is reference to a field of struct.
27282728
LookupResult R(*this, NameInfo, LookupMemberName);
27292729
// LookupName handles a name lookup from within anonymous struct.
@@ -3357,7 +3357,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
33573357
case Decl::Field:
33583358
case Decl::IndirectField:
33593359
case Decl::ObjCIvar:
3360-
assert((getLangOpts().CPlusPlus || isAttrContext()) &&
3360+
assert((getLangOpts().CPlusPlus || isBoundsAttrContext()) &&
33613361
"building reference to field in C?");
33623362

33633363
// These can't have reference type in well-formed programs, but

clang/test/AST/ast-dump-color.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ struct Invalid {
8282
//CHECK: {{^}}[[Blue]]| | `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'const Mutex &'[[RESET]]{{$}}
8383
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] implicit constexpr[[CYAN]] Mutex[[RESET]] [[Green]]'void (Mutex &&)'[[RESET]] inline{{ .*$}}
8484
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'Mutex &&'[[RESET]]{{$}}
85-
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] used[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
85+
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]line:25:3[[RESET]]> [[Yellow]]col:3[[RESET]] referenced[[CYAN]] mu1[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
8686
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:3[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
8787
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:18:1[[RESET]], [[Yellow]]line:25:8[[RESET]]> [[Yellow]]col:8[[RESET]][[CYAN]] mu2[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]
8888
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]CXXConstructExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:8[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]] [[Green]]'void () noexcept'[[RESET]]{{$}}
8989
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]VarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:26:1[[RESET]], [[Yellow]]col:5[[RESET]]> [[Yellow]]col:5[[RESET]][[CYAN]] TestExpr[[RESET]] [[Green]]'int'[[RESET]]
9090
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}}
91-
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]]{{$}}
91+
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[MAGENTA]]DeclRefExpr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:40[[RESET]]> [[Green]]'class Mutex':'Mutex'[[RESET]][[Cyan]] lvalue[[RESET]][[Cyan]][[RESET]] [[GREEN]]Var[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]][[CYAN]] 'mu1'[[RESET]] [[Green]]'class Mutex':'Mutex'[[RESET]] non_odr_use_unevaluated{{$}}
9292
//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:28:1[[RESET]], [[Yellow]]line:30:1[[RESET]]> [[Yellow]]line:28:8[[RESET]] struct[[CYAN]] Invalid[[RESET]] definition
9393
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXRecordDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:1[[RESET]], [[Yellow]]col:8[[RESET]]> [[Yellow]]col:8[[RESET]] implicit referenced struct[[CYAN]] Invalid[[RESET]]
9494
//CHECK: {{^}}[[Blue]]| |-[[RESET]][[GREEN]]CXXConstructorDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:29:3[[RESET]], [[Yellow]]col:42[[RESET]]> [[Yellow]]col:29[[RESET]] invalid[[CYAN]] Invalid[[RESET]] [[Green]]'void (int)'[[RESET]]

clang/test/Sema/warn-thread-safety-analysis.c

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta %s
2-
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -fexperimental-late-parse-attributes -DLATE_PARSING %s
32

43
#define LOCKABLE __attribute__ ((lockable))
54
#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
6-
#define GUARDED_BY(...) __attribute__ ((guarded_by(__VA_ARGS__)))
5+
#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
76
#define GUARDED_VAR __attribute__ ((guarded_var))
8-
#define PT_GUARDED_BY(...) __attribute__ ((pt_guarded_by(__VA_ARGS__)))
7+
#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
98
#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
109
#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
1110
#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
@@ -30,14 +29,6 @@ struct LOCKABLE Mutex {};
3029

3130
struct Foo {
3231
struct Mutex *mu_;
33-
int a_value GUARDED_BY(mu_);
34-
35-
struct Bar {
36-
struct Mutex *other_mu ACQUIRED_AFTER(mu_);
37-
struct Mutex *third_mu ACQUIRED_BEFORE(other_mu);
38-
} bar;
39-
40-
int* a_ptr PT_GUARDED_BY(bar.other_mu);
4132
};
4233

4334
// Declare mutex lock/unlock functions.
@@ -83,19 +74,6 @@ int get_value(int *p) SHARED_LOCKS_REQUIRED(foo_.mu_){
8374

8475
void unlock_scope(struct Mutex *const *mu) __attribute__((release_capability(**mu)));
8576

86-
// Verify late parsing:
87-
#ifdef LATE_PARSING
88-
struct LateParsing {
89-
int a_value_defined_before GUARDED_BY(a_mutex_defined_late);
90-
int *a_ptr_defined_before PT_GUARDED_BY(a_mutex_defined_late);
91-
struct Mutex *a_mutex_defined_early
92-
ACQUIRED_BEFORE(a_mutex_defined_late);
93-
struct Mutex *a_mutex_defined_late
94-
ACQUIRED_AFTER(a_mutex_defined_very_late);
95-
struct Mutex *a_mutex_defined_very_late;
96-
} late_parsing;
97-
#endif
98-
9977
int main(void) {
10078

10179
Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -158,51 +136,9 @@ int main(void) {
158136
// Cleanup happens automatically -> no warning.
159137
}
160138

161-
foo_.a_value = 0; // expected-warning {{writing variable 'a_value' requires holding mutex 'mu_' exclusively}}
162-
*foo_.a_ptr = 1; // expected-warning {{writing the value pointed to by 'a_ptr' requires holding mutex 'bar.other_mu' exclusively}}
163-
164-
165-
mutex_exclusive_lock(foo_.bar.other_mu);
166-
mutex_exclusive_lock(foo_.bar.third_mu); // expected-warning{{mutex 'third_mu' must be acquired before 'other_mu'}}
167-
mutex_exclusive_lock(foo_.mu_); // expected-warning{{mutex 'mu_' must be acquired before 'other_mu'}}
168-
mutex_exclusive_unlock(foo_.mu_);
169-
mutex_exclusive_unlock(foo_.bar.other_mu);
170-
mutex_exclusive_unlock(foo_.bar.third_mu);
171-
172-
#ifdef LATE_PARSING
173-
late_parsing.a_value_defined_before = 1; // expected-warning{{writing variable 'a_value_defined_before' requires holding mutex 'a_mutex_defined_late' exclusively}}
174-
late_parsing.a_ptr_defined_before = 0;
175-
mutex_exclusive_lock(late_parsing.a_mutex_defined_late);
176-
mutex_exclusive_lock(late_parsing.a_mutex_defined_early); // expected-warning{{mutex 'a_mutex_defined_early' must be acquired before 'a_mutex_defined_late'}}
177-
mutex_exclusive_unlock(late_parsing.a_mutex_defined_early);
178-
mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);
179-
mutex_exclusive_lock(late_parsing.a_mutex_defined_late);
180-
mutex_exclusive_lock(late_parsing.a_mutex_defined_very_late); // expected-warning{{mutex 'a_mutex_defined_very_late' must be acquired before 'a_mutex_defined_late'}}
181-
mutex_exclusive_unlock(late_parsing.a_mutex_defined_very_late);
182-
mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);
183-
#endif
184-
185139
return 0;
186140
}
187141

188142
// We had a problem where we'd skip all attributes that follow a late-parsed
189143
// attribute in a single __attribute__.
190144
void run(void) __attribute__((guarded_by(mu1), guarded_by(mu1))); // expected-warning 2{{only applies to non-static data members and global variables}}
191-
192-
int value_with_wrong_number_of_args GUARDED_BY(mu1, mu2); // expected-error{{'guarded_by' attribute takes one argument}}
193-
194-
int *ptr_with_wrong_number_of_args PT_GUARDED_BY(mu1, mu2); // expected-error{{'pt_guarded_by' attribute takes one argument}}
195-
196-
int value_with_no_open_brace __attribute__((guarded_by)); // expected-error{{'guarded_by' attribute takes one argument}}
197-
int *ptr_with_no_open_brace __attribute__((pt_guarded_by)); // expected-error{{'pt_guarded_by' attribute takes one argument}}
198-
199-
int value_with_no_open_brace_on_acquire_after __attribute__((acquired_after)); // expected-error{{'acquired_after' attribute takes at least 1 argument}}
200-
int value_with_no_open_brace_on_acquire_before __attribute__((acquired_before)); // expected-error{{'acquired_before' attribute takes at least 1 argument}}
201-
202-
int value_with_bad_expr GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}
203-
int *ptr_with_bad_expr PT_GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}
204-
205-
int value_with_bad_expr_on_acquire_after __attribute__((acquired_after(other_bad_expr))); // expected-error{{use of undeclared identifier 'other_bad_expr'}}
206-
int value_with_bad_expr_on_acquire_before __attribute__((acquired_before(other_bad_expr))); // expected-error{{use of undeclared identifier 'other_bad_expr'}}
207-
208-
int a_final_expression = 0;

clang/test/SemaCXX/warn-thread-safety-parsing.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1516,7 +1516,11 @@ class Foo {
15161516
mutable Mutex mu;
15171517
int a GUARDED_BY(mu);
15181518

1519-
static int si GUARDED_BY(mu); // expected-error {{invalid use of non-static data member 'mu'}}
1519+
static int si GUARDED_BY(mu);
1520+
//FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect
1521+
#if __cplusplus <= 199711L
1522+
// expected-error@-3 {{invalid use of non-static data member 'mu'}}
1523+
#endif
15201524

15211525
static void foo() EXCLUSIVE_LOCKS_REQUIRED(mu);
15221526
//FIXME: Bug 32066 - Error should be emitted irrespective of C++ dialect

0 commit comments

Comments
 (0)