From: Jordan Rose Date: Thu, 30 Apr 2015 17:20:30 +0000 (+0000) Subject: Batch up access-related diagnostics on enum constants until the whole enum is parsed. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c00065b76ecab2693bf46fce64a1b5a9a43bd986;p=clang Batch up access-related diagnostics on enum constants until the whole enum is parsed. That way we can take any trailing availability attributes into account. rdar://problem/20713550 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236241 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index e19d1115f0..155b3aa72d 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -250,6 +250,17 @@ public: i->Destroy(); } + DelayedDiagnosticPool(DelayedDiagnosticPool &&Other) + : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) { + Other.Diagnostics.clear(); + } + DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) { + Parent = Other.Parent; + Diagnostics = std::move(Other.Diagnostics); + Other.Diagnostics.clear(); + return *this; + } + const DelayedDiagnosticPool *getParent() const { return Parent; } /// Does this pool, or any of its ancestors, contain any diagnostics? diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c64421793c..16639f04ce 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3974,6 +3974,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Diag(Tok, diag::error_empty_enum); SmallVector EnumConstantDecls; + SmallVector EnumAvailabilityDiags; Decl *LastEnumConstDecl = nullptr; @@ -4004,7 +4005,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation EqualLoc; ExprResult AssignedVal; - ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); + EnumAvailabilityDiags.emplace_back(*this); if (TryConsumeToken(tok::equal, EqualLoc)) { AssignedVal = ParseConstantExpression(); @@ -4018,7 +4019,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { IdentLoc, Ident, attrs.getList(), EqualLoc, AssignedVal.get()); - PD.complete(EnumConstDecl); + EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; @@ -4074,6 +4075,14 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { getCurScope(), attrs.getList()); + // Now handle enum constant availability diagnostics. + assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); + for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) { + ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); + EnumAvailabilityDiags[i].redelay(); + PD.complete(EnumConstantDecls[i]); + } + EnumScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getCloseLocation()); diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h index 71cfec4704..c2f4980419 100644 --- a/lib/Parse/RAIIObjectsForParser.h +++ b/lib/Parse/RAIIObjectsForParser.h @@ -58,6 +58,12 @@ namespace clang { Active = false; } } + SuppressAccessChecks(SuppressAccessChecks &&Other) + : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)), + State(Other.State), Active(Other.Active) { + Other.Active = false; + } + void operator=(SuppressAccessChecks &&Other) = delete; void done() { assert(Active && "trying to end an inactive suppression"); diff --git a/test/Sema/attr-availability.c b/test/Sema/attr-availability.c index 48bdf26598..ce64fab398 100644 --- a/test/Sema/attr-availability.c +++ b/test/Sema/attr-availability.c @@ -79,3 +79,84 @@ void f8() { extern int x2 __attribute__((availability(macosx,introduced=10.2))); // expected-note {{previous attribute is here}} extern int x2 __attribute__((availability(macosx,introduced=10.5))); // expected-warning {{availability does not match previous declaration}} + + +enum Original { + OriginalDeprecated __attribute__((availability(macosx, deprecated=10.2))), // expected-note + {{'OriginalDeprecated' has been explicitly marked deprecated here}} + OriginalUnavailable __attribute__((availability(macosx, unavailable))) // expected-note + {{'OriginalUnavailable' has been explicitly marked unavailable here}} +}; + +enum AllDeprecated { + AllDeprecatedCase, // expected-note + {{'AllDeprecatedCase' has been explicitly marked deprecated here}} + AllDeprecatedUnavailable __attribute__((availability(macosx, unavailable))) // expected-note + {{'AllDeprecatedUnavailable' has been explicitly marked unavailable here}} +} __attribute__((availability(macosx, deprecated=10.2))); + +enum AllUnavailable { + AllUnavailableCase, // expected-note + {{'AllUnavailableCase' has been explicitly marked unavailable here}} +} __attribute__((availability(macosx, unavailable))); + +enum User { + UserOD = OriginalDeprecated, // expected-warning {{deprecated}} + UserODDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalDeprecated, + UserODUnavailable __attribute__((availability(macosx, unavailable))) = OriginalDeprecated, // expected-warning {{deprecated}} + + UserOU = OriginalUnavailable, // expected-error {{unavailable}} + UserOUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalUnavailable, // expected-error {{unavailable}} + UserOUUnavailable __attribute__((availability(macosx, unavailable))) = OriginalUnavailable, + + UserAD = AllDeprecatedCase, // expected-warning {{deprecated}} + UserADDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedCase, + UserADUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedCase, // expected-warning {{deprecated}} + + UserADU = AllDeprecatedUnavailable, // expected-error {{unavailable}} + UserADUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedUnavailable, // expected-error {{unavailable}} + UserADUUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedUnavailable, + + UserAU = AllUnavailableCase, // expected-error {{unavailable}} + UserAUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllUnavailableCase, // expected-error {{unavailable}} + UserAUUnavailable __attribute__((availability(macosx, unavailable))) = AllUnavailableCase, +}; + +enum UserDeprecated { + UserDeprecatedOD = OriginalDeprecated, + UserDeprecatedODDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalDeprecated, + UserDeprecatedODUnavailable __attribute__((availability(macosx, unavailable))) = OriginalDeprecated, + + UserDeprecatedOU = OriginalUnavailable, // expected-error {{unavailable}} + UserDeprecatedOUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalUnavailable, // expected-error {{unavailable}} + UserDeprecatedOUUnavailable __attribute__((availability(macosx, unavailable))) = OriginalUnavailable, + + UserDeprecatedAD = AllDeprecatedCase, + UserDeprecatedADDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedCase, + UserDeprecatedADUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedCase, + + UserDeprecatedADU = AllDeprecatedUnavailable, // expected-error {{unavailable}} + UserDeprecatedADUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedUnavailable, // expected-error {{unavailable}} + UserDeprecatedADUUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedUnavailable, + + UserDeprecatedAU = AllUnavailableCase, // expected-error {{unavailable}} + UserDeprecatedAUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllUnavailableCase, // expected-error {{unavailable}} + UserDeprecatedAUUnavailable __attribute__((availability(macosx, unavailable))) = AllUnavailableCase, +} __attribute__((availability(macosx, deprecated=10.2))); + +enum UserUnavailable { + UserUnavailableOD = OriginalDeprecated, // expected-warning {{deprecated}} + UserUnavailableODDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalDeprecated, + UserUnavailableODUnavailable __attribute__((availability(macosx, unavailable))) = OriginalDeprecated, // expected-warning {{deprecated}} + + UserUnavailableOU = OriginalUnavailable, + UserUnavailableOUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = OriginalUnavailable, + UserUnavailableOUUnavailable __attribute__((availability(macosx, unavailable))) = OriginalUnavailable, + + UserUnavailableAD = AllDeprecatedCase, // expected-warning {{deprecated}} + UserUnavailableADDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedCase, + UserUnavailableADUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedCase, // expected-warning {{deprecated}} + + UserUnavailableADU = AllDeprecatedUnavailable, + UserUnavailableADUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllDeprecatedUnavailable, + UserUnavailableADUUnavailable __attribute__((availability(macosx, unavailable))) = AllDeprecatedUnavailable, + + UserUnavailableAU = AllUnavailableCase, + UserUnavailableAUDeprecated __attribute__((availability(macosx, deprecated=10.2))) = AllUnavailableCase, + UserUnavailableAUUnavailable __attribute__((availability(macosx, unavailable))) = AllUnavailableCase, +} __attribute__((availability(macosx, unavailable)));