forked from OSchip/llvm-project
[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
This commit is contained in:
parent
00616f1039
commit
43f40103f0
|
@ -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>;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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> {};
|
||||
|
|
|
@ -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}}
|
Loading…
Reference in New Issue