forked from OSchip/llvm-project
Add message to attribute(deprecated).
attribute(unavailable) to do next. // rdar:// 6734520. llvm-svn: 115842
This commit is contained in:
parent
b270f28c1a
commit
55106310ae
|
@ -172,6 +172,7 @@ def Constructor : Attr {
|
|||
|
||||
def Deprecated : Attr {
|
||||
let Spellings = ["deprecated"];
|
||||
let Args = [StringArgument<"Message">];
|
||||
}
|
||||
|
||||
def Destructor : Attr {
|
||||
|
|
|
@ -1745,6 +1745,8 @@ def note_dependent_var_use : Note<"must qualify identifier to find this "
|
|||
def err_undeclared_use : Error<"use of undeclared %0">;
|
||||
def warn_deprecated : Warning<"%0 is deprecated">,
|
||||
InGroup<DeprecatedDeclarations>;
|
||||
def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
|
||||
InGroup<DeprecatedDeclarations>;
|
||||
def err_unavailable : Error<"%0 is unavailable">;
|
||||
def note_unavailable_here : Note<
|
||||
"function has been explicitly marked %select{unavailable|deleted}0 here">;
|
||||
|
|
|
@ -121,7 +121,7 @@ public:
|
|||
|
||||
union {
|
||||
/// Deprecation.
|
||||
struct { NamedDecl *Decl; } DeprecationData;
|
||||
struct { NamedDecl *Decl; const char* Message; } DeprecationData;
|
||||
|
||||
/// Access control.
|
||||
char AccessData[sizeof(AccessedEntity)];
|
||||
|
@ -135,12 +135,14 @@ public:
|
|||
}
|
||||
|
||||
static DelayedDiagnostic makeDeprecation(SourceLocation Loc,
|
||||
NamedDecl *D) {
|
||||
NamedDecl *D,
|
||||
const char *Msg) {
|
||||
DelayedDiagnostic DD;
|
||||
DD.Kind = Deprecation;
|
||||
DD.Triggered = false;
|
||||
DD.Loc = Loc;
|
||||
DD.DeprecationData.Decl = D;
|
||||
DD.DeprecationData.Message = Msg;
|
||||
return DD;
|
||||
}
|
||||
|
||||
|
|
|
@ -1649,7 +1649,8 @@ public:
|
|||
|
||||
ParsingDeclStackState PushParsingDeclaration();
|
||||
void PopParsingDeclaration(ParsingDeclStackState S, Decl *D);
|
||||
void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc);
|
||||
void EmitDeprecationWarning(NamedDecl *D, const char *Message,
|
||||
SourceLocation Loc);
|
||||
|
||||
void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
|
||||
|
||||
|
|
|
@ -903,12 +903,28 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
|
||||
static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
// check the attribute arguments.
|
||||
if (Attr.getNumArgs() != 0) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
|
||||
int noArgs = Attr.getNumArgs();
|
||||
if (noArgs > 1) {
|
||||
S.Diag(Attr.getLoc(),
|
||||
diag::err_attribute_wrong_number_arguments) << "0 or 1";
|
||||
return;
|
||||
}
|
||||
// Handle the case where deprecated attribute has a text message.
|
||||
StringLiteral *SE;
|
||||
if (noArgs == 1) {
|
||||
Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
|
||||
SE = dyn_cast<StringLiteral>(ArgExpr);
|
||||
if (!SE) {
|
||||
S.Diag(ArgExpr->getLocStart(),
|
||||
diag::err_attribute_not_string) << "deprecated";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
SE = StringLiteral::CreateEmpty(S.Context, 1);
|
||||
|
||||
d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context));
|
||||
d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context,
|
||||
SE->getString()));
|
||||
}
|
||||
|
||||
static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
||||
|
@ -2536,20 +2552,30 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD,
|
|||
return;
|
||||
|
||||
DD.Triggered = true;
|
||||
Diag(DD.Loc, diag::warn_deprecated)
|
||||
<< DD.DeprecationData.Decl->getDeclName();
|
||||
if (strlen(DD.DeprecationData.Message))
|
||||
Diag(DD.Loc, diag::warn_deprecated_message)
|
||||
<< DD.DeprecationData.Decl->getDeclName()
|
||||
<< DD.DeprecationData.Message;
|
||||
else
|
||||
Diag(DD.Loc, diag::warn_deprecated)
|
||||
<< DD.DeprecationData.Decl->getDeclName();
|
||||
}
|
||||
|
||||
void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
|
||||
void Sema::EmitDeprecationWarning(NamedDecl *D, const char * Message,
|
||||
SourceLocation Loc) {
|
||||
// Delay if we're currently parsing a declaration.
|
||||
if (ParsingDeclDepth) {
|
||||
DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D));
|
||||
DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D,
|
||||
Message));
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, don't warn if our current context is deprecated.
|
||||
if (isDeclDeprecated(cast<Decl>(CurContext)))
|
||||
return;
|
||||
|
||||
Diag(Loc, diag::warn_deprecated) << D->getDeclName();
|
||||
if (strlen(Message))
|
||||
Diag(Loc, diag::warn_deprecated_message) << D->getDeclName()
|
||||
<< Message;
|
||||
else
|
||||
Diag(Loc, diag::warn_deprecated) << D->getDeclName();
|
||||
}
|
||||
|
|
|
@ -1622,9 +1622,13 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
// If the interface declared this method, and it was deprecated there,
|
||||
// mark it deprecated here.
|
||||
if (InterfaceMD)
|
||||
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>())
|
||||
ObjCMethod->addAttr(::new (Context) DeprecatedAttr(DA->getLocation(),
|
||||
Context));
|
||||
if (Attr *DA = InterfaceMD->getAttr<DeprecatedAttr>()) {
|
||||
StringLiteral *SE = StringLiteral::CreateEmpty(Context, 1);
|
||||
ObjCMethod->addAttr(::new (Context)
|
||||
DeprecatedAttr(DA->getLocation(),
|
||||
Context,
|
||||
SE->getString()));
|
||||
}
|
||||
|
||||
return ObjCMethod;
|
||||
}
|
||||
|
|
|
@ -57,8 +57,10 @@ using namespace sema;
|
|||
///
|
||||
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) {
|
||||
// See if the decl is deprecated.
|
||||
if (D->getAttr<DeprecatedAttr>()) {
|
||||
EmitDeprecationWarning(D, Loc);
|
||||
if (const DeprecatedAttr *DA = D->getAttr<DeprecatedAttr>()) {
|
||||
const char *Message =
|
||||
DA->getMessage().empty() ? "" : DA->getMessage().data();
|
||||
EmitDeprecationWarning(D, Message, Loc);
|
||||
}
|
||||
|
||||
// See if the decl is unavailable
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// RUN: %clang_cc1 %s -verify -fsyntax-only
|
||||
// rdar: // 6734520
|
||||
|
||||
typedef int INT1 __attribute__((deprecated("Please avoid INT1")));
|
||||
|
||||
typedef INT1 INT2 __attribute__ ((__deprecated__("Please avoid INT2")));
|
||||
|
||||
typedef INT1 INT1a; // expected-warning {{'INT1' is deprecated: Please avoid INT1}}
|
||||
|
||||
typedef INT1 INT1b __attribute__ ((deprecated("Please avoid INT1b")));
|
||||
|
||||
INT1 should_be_unavailable; // expected-warning {{'INT1' is deprecated: Please avoid INT1}}
|
||||
INT1a should_not_be_deprecated;
|
||||
|
||||
INT1 f1(void) __attribute__ ((deprecated("Please avoid f1")));
|
||||
INT1 f2(void); // expected-warning {{'INT1' is deprecated: Please avoid INT1}}
|
||||
|
||||
typedef enum {red, green, blue} Color __attribute__((deprecated("Please avoid Color")));
|
||||
|
||||
|
||||
Color c1; // expected-warning {{'Color' is deprecated: Please avoid Color}}
|
||||
|
||||
int g1;
|
||||
int g2 __attribute__ ((deprecated("Please avoid g2")));
|
||||
|
||||
int func1()
|
||||
{
|
||||
int (*pf)() = f1; // expected-warning {{'f1' is deprecated: Please avoid f1}}
|
||||
int i = f2();
|
||||
return g1 + g2; // expected-warning {{'g2' is deprecated: Please avoid g2}}
|
||||
}
|
Loading…
Reference in New Issue