]> granicus.if.org Git - clang/commitdiff
[c++1z] Support [[deprecated]] attributes on namespaces. Note that it only applies...
authorAaron Ballman <aaron@aaronballman.com>
Fri, 14 Nov 2014 22:34:56 +0000 (22:34 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Fri, 14 Nov 2014 22:34:56 +0000 (22:34 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@222054 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp
test/SemaCXX/cxx-deprecated.cpp [new file with mode: 0644]

index 8eb2757384da087aae75da69e4c44ca540793cd7..deb8685bbef5c236f9c375fe1543fd781b30b34c 100644 (file)
@@ -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>;
index 0193e80a75583ff86118e8413725f78e150659aa..49e8a155c3ab75bba3074d975cd3b0cdedcf15ef 100644 (file)
@@ -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);
index 1b04e52f1508ad3477e76cde52564b8e60350ddf..00f9f803286a98413706fa33b269e4aedfaff2e0 100644 (file)
@@ -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);
   }
 
index 0bd1222454b7b17840dd3f3a1f9e9074e1237e99..c960f54b94a8c7d9716cf3c8634bd224c02090df 100644 (file)
@@ -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.\r
+    DiagnoseUseOfDecl(Named, IdentLoc);\r
+
     // 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.\r
+  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));
 
index 3bbbf9eed6e4f4bc5cef3240f766e9ca854ce7a4..a27cea84db45671034a1768b240008439702b86b 100644 (file)
@@ -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/test/SemaCXX/cxx-deprecated.cpp b/test/SemaCXX/cxx-deprecated.cpp
new file mode 100644 (file)
index 0000000..47accd4
--- /dev/null
@@ -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}}