Skip to content

Commit 43f4010

Browse files
committed
[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
1 parent 00616f1 commit 43f4010

File tree

6 files changed

+62
-9
lines changed

6 files changed

+62
-9
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3820,6 +3820,9 @@ def warn_property_method_deprecated :
38203820
InGroup<DeprecatedDeclarations>;
38213821
def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
38223822
InGroup<DeprecatedDeclarations>;
3823+
def warn_deprecated_anonymous_namespace : Warning<
3824+
"'deprecated' attribute on anonymous namespace ignored">,
3825+
InGroup<IgnoredAttributes>;
38233826
def warn_deprecated_fwdclass_message : Warning<
38243827
"%0 may be deprecated because the receiver type is unknown">,
38253828
InGroup<DeprecatedDeclarations>;

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,10 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
652652
// don't extend the nested-name-specifier. Just return now.
653653
if (ErrorRecoveryLookup)
654654
return false;
655+
656+
// The use of a nested name specifier may trigger deprecation warnings.
657+
DiagnoseUseOfDecl(SD, CCLoc);
658+
655659

656660
if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) {
657661
SS.Extend(Context, Namespace, IdentifierLoc, CCLoc);

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4139,6 +4139,19 @@ static void handleRequiresCapabilityAttr(Sema &S, Decl *D,
41394139
D->addAttr(RCA);
41404140
}
41414141

4142+
static void handleDeprecatedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
4143+
if (auto *NSD = dyn_cast<NamespaceDecl>(D)) {
4144+
if (NSD->isAnonymousNamespace()) {
4145+
S.Diag(Attr.getLoc(), diag::warn_deprecated_anonymous_namespace);
4146+
// Do not want to attach the attribute to the namespace because that will
4147+
// cause confusing diagnostic reports for uses of declarations within the
4148+
// namespace.
4149+
return;
4150+
}
4151+
}
4152+
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
4153+
}
4154+
41424155
/// Handles semantic checking for features that are common to all attributes,
41434156
/// such as checking whether a parameter was properly specified, or the correct
41444157
/// number of arguments were passed, etc.
@@ -4283,7 +4296,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
42834296
handleSimpleAttribute<CXX11NoReturnAttr>(S, D, Attr);
42844297
break;
42854298
case AttributeList::AT_Deprecated:
4286-
handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);
4299+
handleDeprecatedAttr(S, D, Attr);
42874300
break;
42884301
case AttributeList::AT_Destructor:
42894302
handleDestructorAttr(S, D, Attr);
@@ -4994,19 +5007,18 @@ static void DoEmitAvailabilityWarning(Sema &S, DelayedDiagnostic::DDKind K,
49945007
llvm_unreachable("Neither a deprecation or unavailable kind");
49955008
}
49965009

4997-
DeclarationName Name = D->getDeclName();
49985010
if (!Message.empty()) {
4999-
S.Diag(Loc, diag_message) << Name << Message;
5011+
S.Diag(Loc, diag_message) << D << Message;
50005012
if (ObjCProperty)
50015013
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
50025014
<< ObjCProperty->getDeclName() << property_note_select;
50035015
} else if (!UnknownObjCClass) {
5004-
S.Diag(Loc, diag) << Name;
5016+
S.Diag(Loc, diag) << D;
50055017
if (ObjCProperty)
50065018
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
50075019
<< ObjCProperty->getDeclName() << property_note_select;
50085020
} else {
5009-
S.Diag(Loc, diag_fwdclass_message) << Name;
5021+
S.Diag(Loc, diag_fwdclass_message) << D;
50105022
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
50115023
}
50125024

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7404,6 +7404,10 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
74047404
NamedDecl *Named = R.getFoundDecl();
74057405
assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named))
74067406
&& "expected namespace decl");
7407+
7408+
// The use of a nested name specifier may trigger deprecation warnings.
7409+
DiagnoseUseOfDecl(Named, IdentLoc);
7410+
74077411
// C++ [namespace.udir]p1:
74087412
// A using-directive specifies that the names in the nominated
74097413
// namespace can be used in the scope in which the
@@ -8494,11 +8498,13 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
84948498
if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S))
84958499
PrevDecl = nullptr;
84968500

8501+
NamedDecl *ND = R.getFoundDecl();
8502+
84978503
if (PrevDecl) {
84988504
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
84998505
// We already have an alias with the same name that points to the same
85008506
// namespace; check that it matches.
8501-
if (!AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl()))) {
8507+
if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
85028508
Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
85038509
<< Alias;
85048510
Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias)
@@ -8515,10 +8521,13 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
85158521
}
85168522
}
85178523

8524+
// The use of a nested name specifier may trigger deprecation warnings.
8525+
DiagnoseUseOfDecl(ND, IdentLoc);
8526+
85188527
NamespaceAliasDecl *AliasDecl =
85198528
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
85208529
Alias, SS.getWithLocInContext(Context),
8521-
IdentLoc, R.getFoundDecl());
8530+
IdentLoc, ND);
85228531
if (PrevDecl)
85238532
AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl));
85248533

clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ e my_enum; // expected-warning {{'e' is deprecated}}
2121
template <typename T> class X {};
2222
template <> class [[deprecated]] X<int> {}; // expected-note {{'X<int>' has been explicitly marked deprecated here}}
2323
X<char> x1;
24-
// FIXME: The diagnostic here could be much better by mentioning X<int>.
25-
X<int> x2; // expected-warning {{'X' is deprecated}}
24+
X<int> x2; // expected-warning {{'X<int>' is deprecated}}
2625

2726
template <typename T> class [[deprecated]] X2 {};
2827
template <> class X2<int> {};

clang/test/SemaCXX/cxx-deprecated.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
2+
3+
namespace [[deprecated]] {} // expected-warning {{'deprecated' attribute on anonymous namespace ignored}}
4+
5+
namespace [[deprecated]] N { // expected-note 4{{'N' has been explicitly marked deprecated here}}
6+
int X;
7+
int Y = X; // Ok
8+
int f();
9+
}
10+
11+
int N::f() { // Ok
12+
return Y; // Ok
13+
}
14+
15+
void f() {
16+
int Y = N::f(); // expected-warning {{'N' is deprecated}}
17+
using N::X; // expected-warning {{'N' is deprecated}}
18+
int Z = X; //Ok
19+
}
20+
21+
void g() {
22+
using namespace N; // expected-warning {{'N' is deprecated}}
23+
int Z = Y; // Ok
24+
}
25+
26+
namespace M = N; // expected-warning {{'N' is deprecated}}

0 commit comments

Comments
 (0)