% \iffalse meta-comment
%
% Packaged, documented, and maintained by Brian Dunn.
%
% Based on code by David Carlisle.
%
% In the public domain.
%
% \fi
%
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{labelschanged}
%<package>    [2024/01/12 v1.01 Identifies endlessly-changing labels.]
%
%<*driver>
\documentclass{ltxdoc}

\usepackage{labelschanged}


\usepackage{xcolor}
\definecolor{myurlcolor}{rgb}{0,0,.7}
\definecolor{mylinkcolor}{rgb}{.7,0,0}

\usepackage[bookmarks=true,hidelinks,%
colorlinks,linkcolor=mylinkcolor,urlcolor=myurlcolor,%
pageanchor=true,hyperindex=true,
]{hyperref}

\hypersetup{%
pdfinfo={%
Title={The Labelschanged Package},%
Author={Brian Dunn},%
Subject={LaTeX labels.},%
Keywords={LaTeX, labels, warning, changed}%
}}

\DeclareRobustCommand{\pkg}[1]{\textsf{#1}}

\setlength{\parindent}{0em}
\setlength{\parskip}{1.4ex}
\setcounter{secnumdepth}{0}

\setcounter{IndexColumns}{2}

\DisableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{labelschanged.dtx}
\end{document}
%</driver>
% \fi
%
% \iffalse
%<*package>
% \fi
%
%
% \CheckSum{19}
%
% \CharacterTable
% {Upper-case     \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote \"      Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent \'      Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than \>      Question mark \?
%   Commercial at \@     Left bracket \[      Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent \`      Left brace    \{     Vertical bar \|
%   Right brace   \}     Tilde         \~}



% \changes{v1.0}{2017/12/11}{\ 2017/12/11: New pkg.}
% \changes{v1.01}{2024/01/12}{\ 2024/01/12}
% \changes{v1.01}{2024/01/12}{Updated contact info.}



% \GetFileInfo{labelschanged.sty}
%
% \DoNotIndex{\newcommand,\renewcommand,\addtocounter,\begin,\end,\begingroup,\endgroup}
% \DoNotIndex{\global,\ifbool,\ifthenelse,\isequivalentto,\let}
% \DoNotIndex{\booltrue,\boolfalse}
% \expandafter\DoNotIndex\expandafter{\detokenize{\(,\),\,,\\,\#,\$,\%,\^,\_,\~,\ ,\&,\{,\}}}
%
% \begin{center}
% \thispagestyle{empty}
% \vfill
% \vfill
% \Huge The \textbf{labelschanged} package \medskip
%
% \bigskip
%
% \large
% Identifies labels which cause endless ``may have changed'' warnings,
% and also labels which are ``multiply-defined''. \\
%
% \bigskip
%
% \normalsize \fileversion\ --- \filedate
%
% \footnotesize
% Packaged, documented, and maintained by \textsc{Brian Dunn}
%
% In the public domain.
%
% Github: \url{https://github.com/bdtc/labelschanged}
%
% \end{center}
%
%
% \thispagestyle{empty}
%
%
% \section{``Label(s) may have changed.''}
%
% Several conditions can cause \LaTeX\ labels to keep changing,
% no matter how many times a document is recompiled.
% \begin{description}
% \item[Dynamic references:] Some packages, such as \pkg{varioref},
% generate text references which dynamically change depending on the location
% of each float, and these changing messages may then cause the floats themselves to move.
%
% \item[Margin/foot notes:] References in margin or foot notes may have a similar effect.
%
% \item[Active characters:] Due to the way changing labels are detected,
% problems may also be caused by active characters in captions or section names.
% \end{description}
%
% In these circumstances, the warning
% \begin{quote}
% \small
% \texttt{LaTeX Warning: \\
%   Label(s) may have changed. Rerun to get cross-references right.}
% \end{quote}
% reoccurs despite multiple document re-compiles.
% Locating the problem labels may be difficult, as there may not be any message
% identifying which labels have changed.
%
%
% \section{Locating the changing labels}
%
% In the preamble of the document, place:
% \begin{quote}
% \ttfamily
% \cs{usepackage}\{labelschanged\}
% \end{quote}
% The \pkg{labelschanged} package will print the names of the labels which changed,
% and their associated definitions before and after the recompile.
% \begin{quote}
% \ttfamily
% Label `xyz' has changed: \\
% \rmfamily\small
% \textless{}before/after comparisons\textgreater
% \end{quote}
%
%
% \section{Solutions}
%
% \begin{description}
% \item[Dynamic references:]
%   \pkg{varioref} issues a warning if the reference text spans a page break.
%   \cs{fullref} or a plain \cs{ref} may be used instead.
% \item[Margin notes:] See the packages \pkg{marginfit}, \pkg{mparhack}, \pkg{marginfix},
%   and \pkg{marginnote} for possible improvements in margin note placement, which
%   then may resolve the changing labels problem.
% \item[Footnotes:] See the packages \pkg{footnotehyper}, \pkg{footnote},
%   and \pkg{ftnright} for possible improvements in footnote placement,
%   which again may resolve the changing labels problem.
%   For \pkg{footmisc}, try avoiding the |perpage| option.
% \item[Active characters:] The sectioning commands
%   (\cs{chapter}, \cs{section}, etc.)
%   and the \cs{caption} command all have an optional ``short'' argument
%   which, if provided, is used in the table of contents and list of figures/tables
%   instead of the regular argument.
%   \begin{quote}
%   |\section[Simple heading name]{Complicated heading name}| \\
%   |\caption[Simple caption]{Complicated caption}|
%   \end{quote}
%   Providing a simplified caption or section heading may resolve the problem of
%   incorrectly detecting changing labels.
%
% \item[\pkg{memoir} and \pkg{breqn}:] See \href
% {https://tex.stackexchange.com/questions/331209/warning-labels-may-have-changed-with-breqn}
% {https://tex.stackexchange.com/questions/331209/ \\
%   \hspace*{2em}warning-labels-may-have-changed-with-breqn}
% \end{description}
%
%
% \section{Multiply-defined labels}
%
% A bonus side-effect of the \pkg{labelschanged} packages is that
% multiply-defined labels are also listed at the end of the compilation.
% While warnings of multiply-defined labels also appear earlier in the log,
% listing them again at the end makes it easier to quickly identify those
% which are a problem.
%
% Avoid using |\label{}| or |\bibitem{}|.
%
%
% \section{Missing references}
%
% Unfortunately, locating missing references still requires searching the log to
% find which are a problem.
%
%
% \clearpage
%
% \section{References}
%
% This code is taken almost verbatim from David Carlisle's reply to a post on
% \textsc{TeX-LaTeX Stack Exchange}:
% \begin{quote}
% \ttfamily
% \href
%   {https://tex.stackexchange.com/questions/154594/how-to-diagnose-a-permanent-labels-may-have-changed-warning}
%   {https://tex.stackexchange.com/questions/154594/ \\ \hspace*{2em} how-to-diagnose-a-permanent-labels-may-have-changed-warning}
% \end{quote}
%
% David has given permission to have this reply converted to a \LaTeX\ package,
% and has placed his \textsc{Stack Exchange} posts the in public domain, per:
% \begin{quote}
% \url{https://tex.meta.stackexchange.com/a/3332/1090}
% \end{quote}
%
% For other discussion on this topic, see:
% \begin{quote}
% \ttfamily
% \href
% {https://tex.stackexchange.com/questions/109178/why-does-the-compiler-keeps-telling-me-forever-to-rerun-because-labels-have-ch}
% {https://tex.stackexchange.com/questions/109178/ \\
%   \hspace*{2em} why-does-the-compiler-keeps-telling-me-forever- \\
%   \hspace*{2em} to-rerun-because-labels-have-ch}
% \end{quote}
%
%
% \StopEventually{
%   \PrintChanges
% ^^A  \PrintIndex
% }
%
% \clearpage
%
% \section{Code}
%
% At the end of the document, the |.aux| file is read back while \cs{newlabel}
% and \cs{bibcite} are effectively redefined as:
% \begin{quote}
% |\def\newlabel{\@testdef r}| \quad ---\,and\,--- \\
% |\def\bibcite{\@testdef b}|
% \end{quote}
%
% While the |.aux| file is read, each label's new definition as given in the
% |.aux| file is compared to its existing definition as defined by |r@<label>|
% or |b@<label>|.
%
% \begin{macro}{\@testdef} \marg{r -or- b} \marg{label} \marg{new definition}
%    \begin{macrocode}
\def\@testdef #1#2#3{%
%    \end{macrocode}
% Remember the new definition for comparison purposes:
%    \begin{macrocode}
    \def\reserved@a{#3}%
%    \end{macrocode}
% Compare with the old definition.  No action if the same.
%    \begin{macrocode}
    \expandafter \ifx \csname #1@#2\endcsname \reserved@a  \else%
%    \end{macrocode}
% If different, print a warning:
%    \begin{macrocode}
        \typeout{^^JLabel `#2' has changed:^^J%
%    \end{macrocode}
% Display the new meaning:
%    \begin{macrocode}
        \meaning\reserved@a^^J%
%    \end{macrocode}
% Display the old meaning:
%    \begin{macrocode}
        \expandafter\meaning\csname #1@#2\endcsname^^J}%
%    \end{macrocode}
% Remember that labels have changed:
%    \begin{macrocode}
        \@tempswatrue%
    \fi%
}
%    \end{macrocode}
% \end{macro}

%
% \iffalse
%</package>
% \fi
%

%
% ^^A At end:
%
% ^^A \clearpage
% ^^A \pagestyle{plain}
% \phantomsection
% \addcontentsline{toc}{section}{Change History and \indexname}
%
% \pagestyle{plain}
%
% \Finale
\endinput


To create the change log:
makeindex -s gglo.ist -o labelschanged.gls labelschanged.glo
makeindex -s gind.ist labelschanged.idx
