diff --git a/Parse/AttributeList.cpp b/Parse/AttributeList.cpp index 4ceece8f27..4fac91fa57 100644 --- a/Parse/AttributeList.cpp +++ b/Parse/AttributeList.cpp @@ -61,7 +61,10 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { if (!memcmp(Str, "annotate", 8)) return AT_annotate; if (!memcmp(Str, "noreturn", 8)) return AT_noreturn; break; - case 11: + case 10: + if (!memcmp(Str, "deprecated", 10)) return AT_deprecated; + break; + case 11: if (!memcmp(Str, "vector_size", 11)) return AT_vector_size; break; case 13: diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index df6dd5c2e1..26528485db 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -255,6 +255,8 @@ FunctionDecl *Sema::MergeFunctionDecl(FunctionDecl *New, ScopedDecl *OldD) { Diag(OldD->getLocation(), diag::err_previous_definition); return New; } + + // FIXME: propagate old Attrs to the New decl QualType OldQType = Old->getCanonicalType(); QualType NewQType = New->getCanonicalType(); @@ -1778,6 +1780,9 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { vDecl->setType(newType); } break; + case AttributeList::AT_deprecated: + New->addAttr(new DeprecatedAttr()); + break; case AttributeList::AT_aligned: HandleAlignedAttribute(New, Attr); break; @@ -1791,7 +1796,11 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { HandleNoReturnAttribute(New, Attr); break; default: - // FIXME: add other attributes... +#if 0 + // TODO: when we have the full set of attributes, warn about unknown ones. + Diag(Attr->getLoc(), diag::warn_attribute_ignored, + Attr->getName()->getName()); +#endif break; } } diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 3d60866c01..5b5b2d235c 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -100,6 +100,10 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, } } if (ValueDecl *VD = dyn_cast(D)) { + // check if referencing an identifier with __attribute__((deprecated)). + if (VD->getAttr()) + Diag(Loc, diag::warn_deprecated, VD->getName()); + // Only create DeclRefExpr's for valid Decl's. if (VD->isInvalidDecl()) return true; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 2517288460..0e5ae58efa 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -26,7 +26,8 @@ public: Aligned, Packed, Annotate, - NoReturn + NoReturn, + Deprecated }; private: @@ -107,6 +108,16 @@ public: static bool classof(const NoReturnAttr *A) { return true; } }; +class DeprecatedAttr : public Attr { +public: + DeprecatedAttr() : Attr(Deprecated) {} + + // Implement isa/cast/dyncast/etc. + + static bool classof(const Attr *A) { return A->getKind() == Deprecated; } + static bool classof(const DeprecatedAttr *A) { return true; } +}; + } // end namespace clang #endif diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 21f348216d..3d0a3f8815 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -617,6 +617,8 @@ DIAG(err_unexpected_typedef, ERROR, "unexpected type name '%0': expected expression") DIAG(err_undeclared_var_use, ERROR, "use of undeclared identifier '%0'") +DIAG(warn_deprecated, WARNING, + "'%0' is deprecated") DIAG(err_redefinition, ERROR, "redefinition of '%0'") DIAG(err_static_non_static, ERROR, diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index a6a699ef8b..6300b984b5 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -49,7 +49,8 @@ public: AT_aligned, AT_packed, AT_annotate, - AT_noreturn + AT_noreturn, + AT_deprecated }; IdentifierInfo *getName() const { return AttrName; }