diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-11-14 22:34:56 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-11-14 22:34:56 +0000 |
commit | 43f40103f045161e7de51d9fb20c3a7f623c7ff1 (patch) | |
tree | 0c8282003c05d470a363c9da4c94420a40e30b70 | |
parent | 00616f1039835c91a50d53df9ce4abc3ed17b3aa (diff) | |
download | bcm5719-llvm-43f40103f045161e7de51d9fb20c3a7f623c7ff1.tar.gz bcm5719-llvm-43f40103f045161e7de51d9fb20c3a7f623c7ff1.zip |
[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.
llvm-svn: 222054
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 13 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp | 3 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx-deprecated.cpp | 26 |
6 files changed, 62 insertions, 9 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8eb2757384d..deb8685bbef 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3820,6 +3820,9 @@ def warn_property_method_deprecated : InGroup<DeprecatedDeclarations>; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup<DeprecatedDeclarations>; +def warn_deprecated_anonymous_namespace : Warning< + "'deprecated' attribute on anonymous namespace ignored">, + InGroup<IgnoredAttributes>; def warn_deprecated_fwdclass_message : Warning< "%0 may be deprecated because the receiver type is unknown">, InGroup<DeprecatedDeclarations>; diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 0193e80a755..49e8a155c3a 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/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<NamespaceDecl>(SD)) { SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1b04e52f150..00f9f803286 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/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<NamespaceDecl>(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<DeprecatedAttr>(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<CXX11NoReturnAttr>(S, D, Attr); break; case AttributeList::AT_Deprecated: - handleAttrWithMessage<DeprecatedAttr>(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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0bd1222454b..c960f54b94a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7404,6 +7404,10 @@ Decl *Sema::ActOnUsingDirective(Scope *S, NamedDecl *Named = R.getFoundDecl(); assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(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<NamespaceAliasDecl>(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<NamespaceAliasDecl>(PrevDecl)); diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp index 3bbbf9eed6e..a27cea84db4 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -21,8 +21,7 @@ e my_enum; // expected-warning {{'e' is deprecated}} template <typename T> class X {}; template <> class [[deprecated]] X<int> {}; // expected-note {{'X<int>' has been explicitly marked deprecated here}} X<char> x1; -// FIXME: The diagnostic here could be much better by mentioning X<int>. -X<int> x2; // expected-warning {{'X' is deprecated}} +X<int> x2; // expected-warning {{'X<int>' is deprecated}} template <typename T> class [[deprecated]] X2 {}; template <> class X2<int> {}; diff --git a/clang/test/SemaCXX/cxx-deprecated.cpp b/clang/test/SemaCXX/cxx-deprecated.cpp new file mode 100644 index 00000000000..47accd4ae1d --- /dev/null +++ b/clang/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}} |