aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--include/clang/Sema/Sema.h5
-rw-r--r--lib/Sema/SemaDeclAttr.cpp11
-rw-r--r--lib/Sema/SemaDeclObjC.cpp16
-rw-r--r--lib/Sema/SemaExpr.cpp18
-rw-r--r--lib/Sema/SemaExprObjC.cpp8
-rw-r--r--test/SemaObjC/special-dep-unavail-warning.m47
7 files changed, 96 insertions, 16 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index a6f4cc8130..b53fb416be 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1878,10 +1878,15 @@ def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DeprecatedDeclarations>;
def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
InGroup<DeprecatedDeclarations>;
+def warn_deprecated_fwdclass_message : Warning<
+ "%0 maybe deprecated because receiver type is unknown">,
+ InGroup<DeprecatedDeclarations>;
def err_unavailable : Error<"%0 is unavailable">;
def err_unavailable_message : Error<"%0 is unavailable: %1">;
+def warn_unavailable_fwdclass_message : Warning<
+ "%0 maybe unavailable because receiver type is unknown">;
def note_unavailable_here : Note<
- "function has been explicitly marked %select{unavailable|deleted}0 here">;
+ "function has been explicitly marked %select{unavailable|deleted|deprecated}0 here">;
def warn_not_enough_argument : Warning<
"not enough variable arguments in %0 declaration to fit a sentinel">;
def warn_missing_sentinel : Warning <
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 77ecde89e1..24f1b217e0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1704,14 +1704,15 @@ public:
ParsingDeclStackState PushParsingDeclaration();
void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
- SourceLocation Loc);
+ SourceLocation Loc, bool UnkownObjCClass=false);
void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
- bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc);
+ bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool UnkownObjCClass=false);
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
ObjCMethodDecl *Getter,
SourceLocation Loc);
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index e77a660ada..06cb42ec0e 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2903,7 +2903,8 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
}
void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
- SourceLocation Loc) {
+ SourceLocation Loc,
+ bool UnkownObjCClass) {
// Delay if we're currently parsing a declaration.
if (ParsingDeclDepth) {
DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D,
@@ -2917,6 +2918,10 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message,
if (!Message.empty())
Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
<< Message;
- else
- Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+ else {
+ if (!UnkownObjCClass)
+ Diag(Loc, diag::warn_deprecated) << D->getDeclName();
+ else
+ Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName();
+ }
}
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 38e91465d2..5d9a924ed8 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -1302,7 +1302,21 @@ void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
// signature.
for (ObjCMethodList *List = &Entry; List; List = List->Next)
if (MatchTwoMethodDeclarations(Method, List->Method)) {
- List->Method->setDefined(impl);
+ ObjCMethodDecl *PrevObjCMethod = List->Method;
+ PrevObjCMethod->setDefined(impl);
+ // If a method is deprecated, push it in the global pool.
+ // This is used for better diagnostics.
+ if (Method->getAttr<DeprecatedAttr>()) {
+ if (!PrevObjCMethod->getAttr<DeprecatedAttr>())
+ List->Method = Method;
+ }
+ // If new method is unavailable, push it into global pool
+ // unless previous one is deprecated.
+ if (Method->getAttr<UnavailableAttr>()) {
+ if (!PrevObjCMethod->getAttr<UnavailableAttr>() &&
+ !PrevObjCMethod->getAttr<DeprecatedAttr>())
+ List->Method = Method;
+ }
return;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 01a505bb08..56ad9b4241 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -49,13 +49,14 @@ using namespace sema;
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
-/// If IgnoreDeprecated is set to true, this should not want about deprecated
+/// If IgnoreDeprecated is set to true, this should not warn about deprecated
/// decls.
///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
-bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
+bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
+ bool UnkownObjCClass) {
if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
@@ -76,13 +77,18 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
// See if the decl is deprecated.
if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>())
- EmitDeprecationWarning(D, DA->getMessage(), Loc);
+ EmitDeprecationWarning(D, DA->getMessage(), Loc, UnkownObjCClass);
// See if the decl is unavailable
if (const UnavailableAttr *UA = D->getAttr<UnavailableAttr>()) {
- if (UA->getMessage().empty())
- Diag(Loc, diag::err_unavailable) << D->getDeclName();
- else
+ if (UA->getMessage().empty()) {
+ if (!UnkownObjCClass)
+ Diag(Loc, diag::err_unavailable) << D->getDeclName();
+ else
+ Diag(Loc, diag::warn_unavailable_fwdclass_message)
+ << D->getDeclName();
+ }
+ else
Diag(Loc, diag::err_unavailable_message)
<< D->getDeclName() << UA->getMessage();
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index baa34f9ce8..bbb047990b 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1023,6 +1023,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
break;
}
}
+ bool forwardClass = false;
if (!Method) {
// If we have implementations in scope, check "private" methods.
Method = LookupPrivateInstanceMethod(Sel, ClassDecl);
@@ -1033,14 +1034,15 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// compatibility. FIXME: should we deviate??
if (OCIType->qual_empty()) {
Method = LookupInstanceMethodInGlobalPool(Sel,
- SourceRange(LBracLoc, RBracLoc));
- if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
+ SourceRange(LBracLoc, RBracLoc));
+ forwardClass = OCIType->getInterfaceDecl()->isForwardDecl();
+ if (Method && !forwardClass)
Diag(Loc, diag::warn_maynot_respond)
<< OCIType->getInterfaceDecl()->getIdentifier() << Sel;
}
}
}
- if (Method && DiagnoseUseOfDecl(Method, Loc))
+ if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
return ExprError();
} else if (!Context.getObjCIdType().isNull() &&
(ReceiverType->isPointerType() ||
diff --git a/test/SemaObjC/special-dep-unavail-warning.m b/test/SemaObjC/special-dep-unavail-warning.m
new file mode 100644
index 0000000000..b7a2d66344
--- /dev/null
+++ b/test/SemaObjC/special-dep-unavail-warning.m
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar://8769853
+
+@interface B
+- (void) depInA;
+- (void) unavailMeth __attribute__((unavailable)); // expected-note {{function has been explicitly marked unavailable here}}
+- (void) depInA1 __attribute__((deprecated));
+- (void) unavailMeth1;
+- (void) depInA2 __attribute__((deprecated));
+- (void) unavailMeth2 __attribute__((unavailable)); // expected-note {{function has been explicitly marked unavailable here}}
+- (void) depunavailInA;
+- (void) depunavailInA1 __attribute__((deprecated)) __attribute__((unavailable)); // expected-note {{function has been explicitly marked unavailable here}}
+- (void)FuzzyMeth __attribute__((deprecated));
+- (void)FuzzyMeth1 __attribute__((unavailable));
+@end
+
+@interface A
+- (void) unavailMeth1 __attribute__((unavailable)); // expected-note {{function has been explicitly marked unavailable here}}
+- (void) depInA __attribute__((deprecated));
+- (void) depInA2 __attribute__((deprecated));
+- (void) depInA1;
+- (void) unavailMeth2 __attribute__((unavailable));
+- (void) depunavailInA __attribute__((deprecated)) __attribute__((unavailable)); // expected-note {{function has been explicitly marked unavailable here}}
+- (void) depunavailInA1;
+- (void)FuzzyMeth __attribute__((unavailable));
+- (void)FuzzyMeth1 __attribute__((deprecated));
+@end
+
+
+@class C;
+
+void test(C *c) {
+ [c depInA]; // expected-warning {{'depInA' maybe deprecated because receiver type is unknown}}
+ [c unavailMeth]; // expected-warning {{'unavailMeth' maybe unavailable because receiver type is unknown}}
+ [c depInA1]; // expected-warning {{'depInA1' maybe deprecated because receiver type is unknown}}
+ [c unavailMeth1]; // expected-warning {{'unavailMeth1' maybe unavailable because receiver type is unknown}}
+ [c depInA2]; // expected-warning {{'depInA2' maybe deprecated because receiver type is unknown}}
+ [c unavailMeth2]; // expected-warning {{'unavailMeth2' maybe unavailable because receiver type is unknown}}
+ [c depunavailInA]; // expected-warning {{'depunavailInA' maybe deprecated because receiver type is unknown}} \
+ // expected-warning {{'depunavailInA' maybe unavailable because receiver type is unknown}}
+ [c depunavailInA1]; // expected-warning {{'depunavailInA1' maybe deprecated because receiver type is unknown}} \
+ // expected-warning {{'depunavailInA1' maybe unavailable because receiver type is unknown}}
+ [c FuzzyMeth]; // expected-warning {{'FuzzyMeth' maybe deprecated because receiver type is unknown}}
+ [c FuzzyMeth1]; // expected-warning {{'FuzzyMeth1' maybe deprecated because receiver type is unknown}}
+
+}
+