Author: Dan Liew Date: 2024-06-12T15:43:12-07:00 New Revision: c9d580033f29196223cd56a0fa238c3ba51d23e4
URL: https://github.com/llvm/llvm-project/commit/c9d580033f29196223cd56a0fa238c3ba51d23e4 DIFF: https://github.com/llvm/llvm-project/commit/c9d580033f29196223cd56a0fa238c3ba51d23e4.diff LOG: Revert "Support `guarded_by` attribute and related attributes inside C structs and support late parsing them (#94216)" This reverts commit af0d7128c8fd053d3de8af208d7d1682bc7a525a. Reverting due to likely regression: https://github.com/llvm/llvm-project/pull/94216#issuecomment-2164013300 Added: Modified: clang/docs/ReleaseNotes.rst clang/docs/ThreadSafetyAnalysis.rst clang/include/clang/Basic/Attr.td clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/Parse/ParseDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/test/AST/ast-dump-color.cpp clang/test/Sema/warn-thread-safety-analysis.c clang/test/SemaCXX/warn-thread-safety-parsing.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f17603a161668..cf1ba02cbc4b2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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 ----------------------------------- diff --git a/clang/docs/ThreadSafetyAnalysis.rst b/clang/docs/ThreadSafetyAnalysis.rst index 6eefa306e3c89..dcde0c706c704 100644 --- a/clang/docs/ThreadSafetyAnalysis.rst +++ b/clang/docs/ThreadSafetyAnalysis.rst @@ -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 diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 6032b934279dd..b70b0c8b836a5 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -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; @@ -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; @@ -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; @@ -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; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 9e11078382756..d054b8cf0d240 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 53b5e18905ca7..4d4579fcfd456 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5142,7 +5142,7 @@ class Sema final : public SemaBase { enum ExpressionKind { EK_Decltype, EK_TemplateArgument, - EK_AttrArgument, + EK_BoundsAttrArgument, EK_Other } ExprContext; @@ -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 diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c7663d4474781..c528917437332 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -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; @@ -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, @@ -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())); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 332e1179f05a2..76145f291887c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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. @@ -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 diff --git a/clang/test/AST/ast-dump-color.cpp b/clang/test/AST/ast-dump-color.cpp index 944b3ecb9a4f7..87797f6bffc5b 100644 --- a/clang/test/AST/ast-dump-color.cpp +++ b/clang/test/AST/ast-dump-color.cpp @@ -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]] diff --git a/clang/test/Sema/warn-thread-safety-analysis.c b/clang/test/Sema/warn-thread-safety-analysis.c index 53fbbe42f137c..642ea88ec3c96 100644 --- a/clang/test/Sema/warn-thread-safety-analysis.c +++ b/clang/test/Sema/warn-thread-safety-analysis.c @@ -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__))) @@ -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. @@ -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'}} \ @@ -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; diff --git a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp index 1626e8375892a..0c5b0cc85897b 100644 --- a/clang/test/SemaCXX/warn-thread-safety-parsing.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-parsing.cpp @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits