Don't suppress access-control or invalid-type diagnostics from a

declarator just because we were able to build an invalid decl
for it.  The invalid-type diagnostics, in particular, are still useful
to know, and may indicate something about why the decl is invalid.

Also, recover from an illegal pointer/reference-to-unqualified-retainable
type using __strong instead of __autoreleasing;  in general, a random
object is much more likely to be __strong, so this avoids unnecessary
cascading errors in the most common case.

llvm-svn: 149074
This commit is contained in:
John McCall 2012-01-26 20:04:03 +00:00
parent fc98d453df
commit 18a962bab5
3 changed files with 19 additions and 4 deletions

View File

@ -4033,7 +4033,7 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
// We only want to actually emit delayed diagnostics when we // We only want to actually emit delayed diagnostics when we
// successfully parsed a decl. // successfully parsed a decl.
if (decl && !decl->isInvalidDecl()) { if (decl) {
// We emit all the active diagnostics, not just those starting // We emit all the active diagnostics, not just those starting
// from the saved state. The idea is this: we get one push for a // from the saved state. The idea is this: we get one push for a
// decl spec and another for each declarator; in a decl group like: // decl spec and another for each declarator; in a decl group like:
@ -4048,7 +4048,9 @@ void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state,
switch (diag.Kind) { switch (diag.Kind) {
case DelayedDiagnostic::Deprecation: case DelayedDiagnostic::Deprecation:
S.HandleDelayedDeprecationCheck(diag, decl); // Don't bother giving deprecation diagnostics if the decl is invalid.
if (!decl->isInvalidDecl())
S.HandleDelayedDeprecationCheck(diag, decl);
break; break;
case DelayedDiagnostic::Access: case DelayedDiagnostic::Access:

View File

@ -1062,7 +1062,9 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
} else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) { } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
return type; return type;
// If that failed, give an error and recover using __autoreleasing. // If that failed, give an error and recover using __strong. __strong
// is the option most likely to prevent spurious second-order diagnostics,
// like when binding a reference to a field.
} else { } else {
// These types can show up in private ivars in system headers, so // These types can show up in private ivars in system headers, so
// we need this to not be an error in those cases. Instead we // we need this to not be an error in those cases. Instead we
@ -1074,7 +1076,7 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
} else { } else {
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference; S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
} }
implicitLifetime = Qualifiers::OCL_Autoreleasing; implicitLifetime = Qualifiers::OCL_Strong;
} }
assert(implicitLifetime && "didn't infer any lifetime!"); assert(implicitLifetime && "didn't infer any lifetime!");

View File

@ -86,3 +86,14 @@ void func()
- (id)not_ret:(id) b __attribute((ns_returns_retained)); // expected-error {{overriding method has mismatched ns_returns_retained attributes}} - (id)not_ret:(id) b __attribute((ns_returns_retained)); // expected-error {{overriding method has mismatched ns_returns_retained attributes}}
- (id)both__returns_not_retained:(id) b __attribute((ns_returns_not_retained)); - (id)both__returns_not_retained:(id) b __attribute((ns_returns_not_retained));
@end @end
// Test that we give a good diagnostic here that mentions the missing
// ownership qualifier. We don't want this to get suppressed because
// of an invalid conversion.
void test7(void) {
id x;
id *px = &x; // expected-error {{pointer to non-const type 'id' with no explicit ownership}}
I *y;
J **py = &y; // expected-error {{pointer to non-const type 'J *' with no explicit ownership}} expected-warning {{incompatible pointer types initializing}}
}