Skip to content

[Clang] Warn on deprecated specializations used in system headers. #70353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,8 @@ Improvements to Clang's diagnostics
- ``-Wzero-as-null-pointer-constant`` diagnostic is no longer emitted when using ``__null``
(or, more commonly, ``NULL`` when the platform defines it as ``__null``) to be more consistent
with GCC.
- Clang will warn on deprecated specializations used in system headers when their instantiation
is caused by user code.

Improvements to Clang's time-trace
----------------------------------
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8464,6 +8464,8 @@ class Sema final {
ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg);

SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;

/// Specifies the context in which a particular template
/// argument is being checked.
enum CheckTemplateArgumentKind {
Expand Down
23 changes: 23 additions & 0 deletions clang/lib/Sema/SemaAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,29 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
}
}

// We emit deprecation warning for deprecated specializations
// when their instantiation stacks originate outside
// of a system header, even if the diagnostics is suppresed at the
// point of definition.
SourceLocation InstantiationLoc =
S.getTopMostPointOfInstantiation(ReferringDecl);
bool ShouldAllowWarningInSystemHeader =
InstantiationLoc != Loc &&
!S.getSourceManager().isInSystemHeader(InstantiationLoc);
struct AllowWarningInSystemHeaders {
AllowWarningInSystemHeaders(DiagnosticsEngine &E,
bool AllowWarningInSystemHeaders)
: Engine(E), Prev(E.getSuppressSystemWarnings()) {
E.setSuppressSystemWarnings(!AllowWarningInSystemHeaders);
}
~AllowWarningInSystemHeaders() { Engine.setSuppressSystemWarnings(Prev); }

private:
DiagnosticsEngine &Engine;
bool Prev;
} SystemWarningOverrideRAII(S.getDiagnostics(),
ShouldAllowWarningInSystemHeader);

if (!Message.empty()) {
S.Diag(Loc, diag_message) << ReferringDecl << Message << FixIts;
if (ObjCProperty)
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11601,3 +11601,25 @@ void Sema::checkSpecializationReachability(SourceLocation Loc,
Sema::AcceptableKind::Reachable)
.check(Spec);
}

/// Returns the top most location responsible for the definition of \p N.
/// If \p N is a a template specialization, this is the location
/// of the top of the instantiation stack.
/// Otherwise, the location of \p N is returned.
SourceLocation Sema::getTopMostPointOfInstantiation(const NamedDecl *N) const {
if (!getLangOpts().CPlusPlus || CodeSynthesisContexts.empty())
return N->getLocation();
if (const auto *FD = dyn_cast<FunctionDecl>(N)) {
if (!FD->isFunctionTemplateSpecialization())
return FD->getLocation();
} else if (!isa<ClassTemplateSpecializationDecl,
VarTemplateSpecializationDecl>(N)) {
return N->getLocation();
}
for (const CodeSynthesisContext &CSC : CodeSynthesisContexts) {
if (!CSC.isInstantiationRecord() || CSC.PointOfInstantiation.isInvalid())
continue;
return CSC.PointOfInstantiation;
}
return N->getLocation();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s

#ifdef BE_THE_HEADER
#pragma clang system_header

template <typename T>
struct traits;

template <>
struct [[deprecated]] traits<int> {}; // expected-note {{'traits<int>' has been explicitly marked deprecated here}}

template<typename T, typename Trait = traits<T>> // expected-warning {{'traits<int>' is deprecated}}
struct basic_string {};

// should not warn, defined and used in system headers
using __do_what_i_say_not_what_i_do = traits<int> ;

template<typename T, typename Trait = traits<double>>
struct should_not_warn {};

#else
#define BE_THE_HEADER
#include __FILE__

basic_string<int> test1; // expected-note {{in instantiation of default argument for 'basic_string<int>' required here}}
should_not_warn<int> test2;

#endif