Skip to content

Commit

Permalink
Batch up access-related diagnostics on enum constants until the whole…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
jrose-apple committed Apr 30, 2015
1 parent 46e2722 commit c00065b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 2 deletions.
11 changes: 11 additions & 0 deletions include/clang/Sema/DelayedDiagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,17 @@ class DelayedDiagnosticPool {
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?
Expand Down
13 changes: 11 additions & 2 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3974,6 +3974,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
Diag(Tok, diag::error_empty_enum);

SmallVector<Decl *, 32> EnumConstantDecls;
SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;

Decl *LastEnumConstDecl = nullptr;

Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
6 changes: 6 additions & 0 deletions lib/Parse/RAIIObjectsForParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
81 changes: 81 additions & 0 deletions test/Sema/attr-availability.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)));

0 comments on commit c00065b

Please sign in to comment.