From: Aaron Ballman Date: Fri, 14 Nov 2014 22:34:56 +0000 (+0000) Subject: [c++1z] Support [[deprecated]] attributes on namespaces. Note that it only applies... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00dccd63cd9db239052a06b113eb28c9b66144fc;p=clang [c++1z] Support [[deprecated]] attributes on namespaces. Note that it only applies to situations where the namespace is mentioned. Thus, use on anonymous namespaces is diagnosed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@222054 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 8eb2757384..deb8685bbe 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3820,6 +3820,9 @@ def warn_property_method_deprecated : InGroup; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup; +def warn_deprecated_anonymous_namespace : Warning< + "'deprecated' attribute on anonymous namespace ignored">, + InGroup; def warn_deprecated_fwdclass_message : Warning< "%0 may be deprecated because the receiver type is unknown">, InGroup; diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 0193e80a75..49e8a155c3 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -652,6 +652,10 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // don't extend the nested-name-specifier. Just return now. if (ErrorRecoveryLookup) return false; + + // The use of a nested name specifier may trigger deprecation warnings. + DiagnoseUseOfDecl(SD, CCLoc); + if (NamespaceDecl *Namespace = dyn_cast(SD)) { SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1b04e52f15..00f9f80328 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4139,6 +4139,19 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D, D->addAttr(RCA); } +static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (auto *NSD = dyn_cast(D)) { + if (NSD->isAnonymousNamespace()) { + S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace); + // Do not want to attach the attribute to the namespace because that will + // cause confusing diagnostic reports for uses of declarations within the + // namespace. + return; + } + } + handleAttrWithMessage(S, D, Attr); +} + /// Handles semantic checking for features that are common to all attributes, /// such as checking whether a parameter was properly specified, or the correct /// number of arguments were passed, etc. @@ -4283,7 +4296,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute(S, D, Attr); break; case AttributeList::AT_Deprecated: - handleAttrWithMessage(S, D, Attr); + handleDeprecatedAttr(S, D, Attr); break; case AttributeList::AT_Destructor: handleDestructorAttr(S, D, Attr); @@ -4994,19 +5007,18 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K, llvm_unreachable("Neither a deprecation or unavailable kind"); } - DeclarationName Name = D->getDeclName(); if (!Message.empty()) { - S.Diag(Loc, diag_message) << Name << Message; + S.Diag(Loc, diag_message) << D << Message; if (ObjCProperty) S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) << ObjCProperty->getDeclName() << property_note_select; } else if (!UnknownObjCClass) { - S.Diag(Loc, diag) << Name; + S.Diag(Loc, diag) << D; if (ObjCProperty) S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) << ObjCProperty->getDeclName() << property_note_select; } else { - S.Diag(Loc, diag_fwdclass_message) << Name; + S.Diag(Loc, diag_fwdclass_message) << D; S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0bd1222454..c960f54b94 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7404,6 +7404,10 @@ Decl *Sema::ActOnUsingDirective(Scope *S, NamedDecl *Named = R.getFoundDecl(); assert((isa(Named) || isa(Named)) && "expected namespace decl"); + + // The use of a nested name specifier may trigger deprecation warnings. + DiagnoseUseOfDecl(Named, IdentLoc); + // C++ [namespace.udir]p1: // A using-directive specifies that the names in the nominated // namespace can be used in the scope in which the @@ -8494,11 +8498,13 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) PrevDecl = nullptr; + NamedDecl *ND = R.getFoundDecl(); + if (PrevDecl) { if (NamespaceAliasDecl *AD = dyn_cast(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace; check that it matches. - if (!AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl()))) { + if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) { Diag(AliasLoc, diag::err_redefinition_different_namespace_alias) << Alias; Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias) @@ -8515,10 +8521,13 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, } } + // The use of a nested name specifier may trigger deprecation warnings. + DiagnoseUseOfDecl(ND, IdentLoc); + NamespaceAliasDecl *AliasDecl = NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getWithLocInContext(Context), - IdentLoc, R.getFoundDecl()); + IdentLoc, ND); if (PrevDecl) AliasDecl->setPreviousDecl(cast(PrevDecl)); diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp index 3bbbf9eed6..a27cea84db 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -21,8 +21,7 @@ e my_enum; // expected-warning {{'e' is deprecated}} template class X {}; template <> class [[deprecated]] X {}; // expected-note {{'X' has been explicitly marked deprecated here}} X x1; -// FIXME: The diagnostic here could be much better by mentioning X. -X x2; // expected-warning {{'X' is deprecated}} +X x2; // expected-warning {{'X' is deprecated}} template class [[deprecated]] X2 {}; template <> class X2 {}; diff --git a/test/SemaCXX/cxx-deprecated.cpp b/test/SemaCXX/cxx-deprecated.cpp new file mode 100644 index 0000000000..47accd4ae1 --- /dev/null +++ b/test/SemaCXX/cxx-deprecated.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s + +namespace [[deprecated]] {} // expected-warning {{'deprecated' attribute on anonymous namespace ignored}} + +namespace [[deprecated]] N { // expected-note 4{{'N' has been explicitly marked deprecated here}} + int X; + int Y = X; // Ok + int f(); +} + +int N::f() { // Ok + return Y; // Ok +} + +void f() { + int Y = N::f(); // expected-warning {{'N' is deprecated}} + using N::X; // expected-warning {{'N' is deprecated}} + int Z = X; //Ok +} + +void g() { + using namespace N; // expected-warning {{'N' is deprecated}} + int Z = Y; // Ok +} + +namespace M = N; // expected-warning {{'N' is deprecated}}