Skip to content

Commit

Permalink
Revert "Support guarded_by attribute and related attributes inside …
Browse files Browse the repository at this point in the history
…C structs and support late parsing them (#94216)"

This reverts commit af0d712.

Reverting due to likely regression:

llvm/llvm-project#94216 (comment)
  • Loading branch information
delcypher committed Jun 12, 2024
1 parent f074500 commit c9d5800
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 213 deletions.
4 changes: 0 additions & 4 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,6 @@ Attribute Changes in Clang
size_t count;
};
- The ``guarded_by``, ``pt_guarded_by``, ``acquired_after``, ``acquired_before``
attributes now support referencing struct members in C. The arguments are also
now late parsed when ``-fexperimental-late-parse-attributes`` is passed like
for ``counted_by``.
Improvements to Clang's diagnostics
-----------------------------------
Expand Down
6 changes: 6 additions & 0 deletions clang/docs/ThreadSafetyAnalysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,12 @@ doesn't know that munl.mu == mutex. The SCOPED_CAPABILITY attribute handles
aliasing for MutexLocker, but does so only for that particular pattern.


ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
-------------------------------------------------------------------------

To be fixed in a future update.


.. _mutexheader:

mutex.h
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3633,7 +3633,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
def GuardedBy : InheritableAttr {
let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3644,7 +3644,7 @@ def GuardedBy : InheritableAttr {
def PtGuardedBy : InheritableAttr {
let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3655,7 +3655,7 @@ def PtGuardedBy : InheritableAttr {
def AcquiredAfter : InheritableAttr {
let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand All @@ -3666,7 +3666,7 @@ def AcquiredAfter : InheritableAttr {
def AcquiredBefore : InheritableAttr {
let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = LateAttrParseExperimentalExt;
let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1;
Expand Down
14 changes: 0 additions & 14 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3128,20 +3128,6 @@ class Parser : public CodeCompletionHandler {
IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
ParsedAttr::Form Form);

void ParseGuardedByAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, SourceLocation *EndLoc,
ParsedAttr::Form Form);

void ParseAcquiredAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
IdentifierInfo *ScopeName,
SourceLocation ScopeLoc, SourceLocation *EndLoc,
ParsedAttr::Form Form);

void ParseTypeofSpecifier(DeclSpec &DS);
SourceLocation ParseDecltypeSpecifier(DeclSpec &DS);
void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
Expand Down
7 changes: 4 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -5142,7 +5142,7 @@ class Sema final : public SemaBase {
enum ExpressionKind {
EK_Decltype,
EK_TemplateArgument,
EK_AttrArgument,
EK_BoundsAttrArgument,
EK_Other
} ExprContext;

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

bool isAttrContext() const {
bool isBoundsAttrContext() const {
return ExprEvalContexts.back().ExprContext ==
ExpressionEvaluationContextRecord::ExpressionKind::EK_AttrArgument;
ExpressionEvaluationContextRecord::ExpressionKind::
EK_BoundsAttrArgument;
}

/// Increment when we find a reference; decrement when we find an ignored
Expand Down
118 changes: 1 addition & 117 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,16 +671,6 @@ void Parser::ParseGNUAttributeArgs(
ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
Form);
return;
} else if (AttrKind == ParsedAttr::AT_GuardedBy ||
AttrKind == ParsedAttr::AT_PtGuardedBy) {
ParseGuardedByAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
EndLoc, Form);
return;
} else if (AttrKind == ParsedAttr::AT_AcquiredAfter ||
AttrKind == ParsedAttr::AT_AcquiredBefore) {
ParseAcquiredAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,
EndLoc, Form);
return;
} else if (AttrKind == ParsedAttr::AT_CXXAssume) {
ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);
return;
Expand Down Expand Up @@ -3340,112 +3330,6 @@ void Parser::DistributeCLateParsedAttrs(Decl *Dcl,
}
}

/// GuardedBy attributes (e.g., guarded_by):
/// AttrName '(' expression ')'
void Parser::ParseGuardedByAttribute(
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
SourceLocation *EndLoc, ParsedAttr::Form Form) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");

BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
Parens.consumeClose();
return;
}

ArgsVector ArgExprs;
// Don't evaluate argument when the attribute is ignored.
using ExpressionKind =
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
ExpressionKind::EK_AttrArgument);

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

if (ArgExpr.isInvalid()) {
Parens.skipToEnd();
return;
}

ArgExprs.push_back(ArgExpr.get());

auto RParens = Tok.getLocation();
auto &AL =
*Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, RParens), ScopeName,
ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form);

if (EndLoc)
*EndLoc = RParens;

if (!Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_attribute_wrong_number_arguments)
<< AL << 1;
Parens.skipToEnd();
return;
}

Parens.consumeClose();
}

/// Acquired attributes (e.g., acquired_before, acquired_after):
/// AttrName '(' expression-list ')'
void Parser::ParseAcquiredAttribute(
IdentifierInfo &AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
SourceLocation *EndLoc, ParsedAttr::Form Form) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");

BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();

if (Tok.is(tok::r_paren)) {
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
Parens.consumeClose();
return;
}

auto ArgStart = Tok.getLocation();

ArgsVector ArgExprs;

do {

// Don't evaluate argument when the attribute is ignored.
using ExpressionKind =
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
nullptr, ExpressionKind::EK_AttrArgument);

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

if (ArgExpr.isInvalid()) {
Parens.skipToEnd();
return;
}

ArgExprs.push_back(ArgExpr.get());

} while (TryConsumeToken(tok::comma));

auto ArgEnd = Tok.getLocation();

Attrs.addNew(&AttrName, SourceRange(ArgStart, ArgEnd), ScopeName, ScopeLoc,
ArgExprs.data(), ArgExprs.size(), Form);

if (EndLoc)
*EndLoc = ArgEnd;

Parens.consumeClose();
}

/// Bounds attributes (e.g., counted_by):
/// AttrName '(' expression ')'
void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
Expand All @@ -3471,7 +3355,7 @@ void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,
Sema::ExpressionEvaluationContextRecord::ExpressionKind;
EnterExpressionEvaluationContext EC(
Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,
ExpressionKind::EK_AttrArgument);
ExpressionKind::EK_BoundsAttrArgument);

ExprResult ArgExpr(
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2723,7 +2723,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
// appertains to a type of C struct field such that the name lookup
// within a struct finds the member name, which is not the case for other
// contexts in C.
if (isAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) {
// See if this is reference to a field of struct.
LookupResult R(*this, NameInfo, LookupMemberName);
// LookupName handles a name lookup from within anonymous struct.
Expand Down Expand Up @@ -3357,7 +3357,7 @@ ExprResult Sema::BuildDeclarationNameExpr(
case Decl::Field:
case Decl::IndirectField:
case Decl::ObjCIvar:
assert((getLangOpts().CPlusPlus || isAttrContext()) &&
assert((getLangOpts().CPlusPlus || isBoundsAttrContext()) &&
"building reference to field in C?");

// These can't have reference type in well-formed programs, but
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ struct Invalid {
//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]]{{$}}
//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{{ .*$}}
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[GREEN]]ParmVarDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:33[[RESET]]> [[Yellow]]col:33[[RESET]] [[Green]]'Mutex &&'[[RESET]]{{$}}
//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]]
//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]]
//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]]{{$}}
//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]]
//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]]{{$}}
//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]]
//CHECK: {{^}}[[Blue]]| `-[[RESET]][[BLUE]]GuardedByAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:29[[RESET]], [[Yellow]]col:43[[RESET]]>{{$}}
//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]]{{$}}
//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{{$}}
//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
//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]]
//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]]
Expand Down
68 changes: 2 additions & 66 deletions clang/test/Sema/warn-thread-safety-analysis.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -fexperimental-late-parse-attributes -DLATE_PARSING %s

#define LOCKABLE __attribute__ ((lockable))
#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
#define GUARDED_BY(...) __attribute__ ((guarded_by(__VA_ARGS__)))
#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))
#define GUARDED_VAR __attribute__ ((guarded_var))
#define PT_GUARDED_BY(...) __attribute__ ((pt_guarded_by(__VA_ARGS__)))
#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))
#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))
#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))
#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))
Expand All @@ -30,14 +29,6 @@ struct LOCKABLE Mutex {};

struct Foo {
struct Mutex *mu_;
int a_value GUARDED_BY(mu_);

struct Bar {
struct Mutex *other_mu ACQUIRED_AFTER(mu_);
struct Mutex *third_mu ACQUIRED_BEFORE(other_mu);
} bar;

int* a_ptr PT_GUARDED_BY(bar.other_mu);
};

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

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

// Verify late parsing:
#ifdef LATE_PARSING
struct LateParsing {
int a_value_defined_before GUARDED_BY(a_mutex_defined_late);
int *a_ptr_defined_before PT_GUARDED_BY(a_mutex_defined_late);
struct Mutex *a_mutex_defined_early
ACQUIRED_BEFORE(a_mutex_defined_late);
struct Mutex *a_mutex_defined_late
ACQUIRED_AFTER(a_mutex_defined_very_late);
struct Mutex *a_mutex_defined_very_late;
} late_parsing;
#endif

int main(void) {

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

foo_.a_value = 0; // expected-warning {{writing variable 'a_value' requires holding mutex 'mu_' exclusively}}
*foo_.a_ptr = 1; // expected-warning {{writing the value pointed to by 'a_ptr' requires holding mutex 'bar.other_mu' exclusively}}


mutex_exclusive_lock(foo_.bar.other_mu);
mutex_exclusive_lock(foo_.bar.third_mu); // expected-warning{{mutex 'third_mu' must be acquired before 'other_mu'}}
mutex_exclusive_lock(foo_.mu_); // expected-warning{{mutex 'mu_' must be acquired before 'other_mu'}}
mutex_exclusive_unlock(foo_.mu_);
mutex_exclusive_unlock(foo_.bar.other_mu);
mutex_exclusive_unlock(foo_.bar.third_mu);

#ifdef LATE_PARSING
late_parsing.a_value_defined_before = 1; // expected-warning{{writing variable 'a_value_defined_before' requires holding mutex 'a_mutex_defined_late' exclusively}}
late_parsing.a_ptr_defined_before = 0;
mutex_exclusive_lock(late_parsing.a_mutex_defined_late);
mutex_exclusive_lock(late_parsing.a_mutex_defined_early); // expected-warning{{mutex 'a_mutex_defined_early' must be acquired before 'a_mutex_defined_late'}}
mutex_exclusive_unlock(late_parsing.a_mutex_defined_early);
mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);
mutex_exclusive_lock(late_parsing.a_mutex_defined_late);
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'}}
mutex_exclusive_unlock(late_parsing.a_mutex_defined_very_late);
mutex_exclusive_unlock(late_parsing.a_mutex_defined_late);
#endif

return 0;
}

// We had a problem where we'd skip all attributes that follow a late-parsed
// attribute in a single __attribute__.
void run(void) __attribute__((guarded_by(mu1), guarded_by(mu1))); // expected-warning 2{{only applies to non-static data members and global variables}}

int value_with_wrong_number_of_args GUARDED_BY(mu1, mu2); // expected-error{{'guarded_by' attribute takes one argument}}

int *ptr_with_wrong_number_of_args PT_GUARDED_BY(mu1, mu2); // expected-error{{'pt_guarded_by' attribute takes one argument}}

int value_with_no_open_brace __attribute__((guarded_by)); // expected-error{{'guarded_by' attribute takes one argument}}
int *ptr_with_no_open_brace __attribute__((pt_guarded_by)); // expected-error{{'pt_guarded_by' attribute takes one argument}}

int value_with_no_open_brace_on_acquire_after __attribute__((acquired_after)); // expected-error{{'acquired_after' attribute takes at least 1 argument}}
int value_with_no_open_brace_on_acquire_before __attribute__((acquired_before)); // expected-error{{'acquired_before' attribute takes at least 1 argument}}

int value_with_bad_expr GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}
int *ptr_with_bad_expr PT_GUARDED_BY(bad_expr); // expected-error{{use of undeclared identifier 'bad_expr'}}

int value_with_bad_expr_on_acquire_after __attribute__((acquired_after(other_bad_expr))); // expected-error{{use of undeclared identifier 'other_bad_expr'}}
int value_with_bad_expr_on_acquire_before __attribute__((acquired_before(other_bad_expr))); // expected-error{{use of undeclared identifier 'other_bad_expr'}}

int a_final_expression = 0;
6 changes: 5 additions & 1 deletion clang/test/SemaCXX/warn-thread-safety-parsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,11 @@ class Foo {
mutable Mutex mu;
int a GUARDED_BY(mu);

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

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

0 comments on commit c9d5800

Please sign in to comment.