There are two main issues here.
Field Expansion
From the user manual:
When you define new glossary entries expansion is performed by
default, except for the name
, description
, descriptionplural
, symbol
,
symbolplural
and sort
keys (these keys all have expansion suppressed
via \glssetnoexpandfield
).
(The reason for these exceptions is for backward compatibility to earlier versions that used to write that information to the glossary file. The expansion suppression helped to protect fragile commands in the write process.)
To see this in action we can use the glossaries
debugging commands (only described in the documented code, not in the user manual). \showgloname
will show the definition of the name
field, \showglofirst
will show the definition of the first
field and \showglotext
will show the definition of the text
field (one argument required in each case, and that's the entry label). (I've trimmed down the MWE.)
\documentclass{article}
\usepackage{textgreek}
\usepackage[nogroupskip,toc,acronym]{glossaries}
\makeglossaries
\newglossaryentry{TNF}{
type={acronym},
sort={tumor necrosis factor},
name={TNF},
first={tumor necrosis factor (TNF)},
description={tumor necrosis factor}
}
\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
type={acronym},
sort={tumor necrosis factor alpha},
name={\TNFalpha},
first={tumor necrosis factor alpha~(\TNFalpha)},
description={tumor necrosis factor alpha}
}
\begin{document}
\showglofirst{TNF}
\showglofirst{TNFalpha}
\showgloname{TNF}
\showgloname{TNFalpha}
\showglotext{TNF}
\showglotext{TNFalpha}
\end{document}
This doesn't create any output, but it shows the definitions in the transcript. (When run in TeX's interactive mode, these commands will interrupt the run as though they were error messages.) Below are the relevant parts of the transcript.
The value of the first
field for the TNF
entry:
> \glo@TNF@first=macro:
->tumor necrosis factor (TNF).
The value of the first
field for the TNFalpha
entry:
> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace {}(TNF--{\textalpha }).
So here the \TNFalpha
command has been expanded and so has the non-breakable space ~
but \textalpha
doesn't get expanded because it's protected.
The value of the name
field for the TNF
entry:
> \glo@TNF@name=macro:
->TNF.
The value of the name
field for the TNFalpha
entry:
> \glo@TNFalpha@name=macro:
->\TNFalpha .
Here \TNFalpha
hasn't been expanded, because the name
key isn't expanded by default.
The text
key wasn't explicitly used so it picked up its value from the name
field, but in this case expansion is performed.
The value of the text
field for the TNF
entry:
> \glo@TNF@text=macro:
->TNF.
The value of the text
field for the TNFalpha
entry:
> \glo@TNFalpha@text=macro:
->TNF--{\textalpha }.
Unlike with the name
field, \TNFalpha
has now been expanded.
Therefore, if you use \ifglsused
within the first
key, by default it will be evaluated when the entry is defined. If the above example is changed so that the definition for TNFalpha
is now:
\newglossaryentry{TNFalpha}{
type={acronym},
sort={tumor necrosis factor alpha},
name={\TNFalpha},
first={\ifglsused{TNF}{\TNFalpha}{tumor necrosis factor alpha~(\TNFalpha)}},
description={tumor necrosis factor alpha}
}
Then \showglofirst{TNFalpha}
still produces the same result:
> \glo@TNFalpha@first=macro:
->tumor necrosis factor alpha\protect \nobreakspace {}(TNF--{\textalpha }).
This is because when TNFalpha
is defined, TNF
hasn't been used so it definition expands to the false part (third argument) of \ifglsused
.
Nested Links
If you add \glsdisp
(or any similar command) to the first
field, you'll end up with nested links. Both \glsdisp
and \gls
internally use the same command \@gls@link
to deal with the hyperlink and to wrap the link text inside \glstextformat
. So nesting these commands can cause problems.
The simplest solution is to switch off the expansion for the first
and firstplural
fields, remove \glsdisp
from the field value and just use \glsunset
to mark the TNF
entry as having been used. Like this:
\documentclass{article}
\usepackage{textgreek}
\usepackage[nogroupskip,toc,acronym]{glossaries}
\makeglossaries
\newglossaryentry{TNF}{
type={acronym},
sort={tumor necrosis factor},
name={TNF},
first={tumor necrosis factor (TNF)},
description={tumor necrosis factor}
}
\glssetnoexpandfield{first}
\glssetnoexpandfield{firstpl}
\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
type={acronym},
sort={tumor necrosis factor alpha},
name={\TNFalpha},
first={\ifglsused{TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis factor alpha~(\TNFalpha)}},
description={tumor necrosis factor alpha}
}
\begin{document}
\gls{TNFalpha}. \gls{TNF}.
\end{document}
This produces:

If you swap them around so that you have
\gls{TNF}. \gls{TNFalpha}.
instead of
\gls{TNFalpha}. \gls{TNF}.
then the result is

Edit: The expansion settings are checked each time a new entry is defined, but you only need to switch expansion on again if you have an entry that needs to have the fields expanded. For example:
\newcommand{\stuff}{foo}
\newglossaryentry{stuff1}{name={\stuff},description={stuff1}}
\renewcommand{\stuff}{bar}
\newglossaryentry{stuff2}{name={\stuff},description={stuff2}}
This type of definition looks a bit weird when done explicitly like this, but it's sometimes done by commands that internally use \newglossaryentry
. In the above example, \stuff
needs to be expanded when the entry is defined as \stuff
is just a temporary command whose definition keeps changing. If you don't have this situation, then you can just put all your \glsetnoexpandfield
commands before you start defining any of your entries.
Case-Changing
The first letter upper casing commands such as \Gls
use \makefirstuc
provided by mfirstuc
. This command does try to deal with the possibility that the argument may contain a formatting command, but because there's no generic way to determine the syntax of a command, specifically which argument is text and which is a label, \makefirstuc
has to apply some restrictions in order to work properly.
- If the argument starts with
\protect
, this is discarded, and \makefirstuc
is applied to the remainder. For example, \makefirstuc{\protect\textbf{foo}}
is the same as \makefirstuc{\textbf{foo}}
.
- The argument of
\makefirstuc
may start with just text. For example \makefirstuc{foo}
just does \MakeUppercase foo
which results in Foo. Whereas \makefirstuc{{fo}o}
does \MakeUppercase{fo}o
which results in FOo.
If the argument of \makefirstuc
starts with a control sequence without an argument, that control sequence is assumed to be a character control sequence such as \ae
or \o
and the case change is applied to that. For example, \makefirstuc{\ae foo}
does \MakeUppercase\ae foo
which results in Æfoo. This means that
\newcommand{\foo}{foo}\makefirstuc{\foo}
does \MakeUppercase\foo
which produces FOO.
If the argument of \makefirstuc
starts with a control sequence followed by a group, the control sequence is assumed to be a formatting command. The grouped material is assumed to be text and the case change is applied to that. For example, \makefirstuc{\textbf{foo}}
is equivalent to \textbf{\MakeUppercase foo}
which results in Foo.
No expansion is performed on the argument of \makefirstuc
as this could cause simple text-block commands with a single argument to be expanded into something too complicated to parse.
Returning to the MWE, \Gls{TNFalpha}
on first use (or \Glsfirst{TNFalpha}
) attempts
\makefirstuc{\ifglsused{TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis
factor alpha~(\TNFalpha)}}
This falls into case 4 (control sequence followed by a group). So this attempts to do
{\ifglsused{\MakeUppercase TNF}{\TNFalpha}{\glsunset{TNF}tumor necrosis
factor alpha~(\TNFalpha)}}
which is the cause of your error message. The only way to resolve the problem is to define a command where the first argument is the text that requires the case change. For example:
% \ifnotused{not used}{used}{label}
\newcommand*{\ifnotused}[3]{%
\ifglsused{#3}{#2}{\glsunset{#3}#1}%
}
\newcommand{\TNFalpha}{TNF--{\textalpha}}
\newglossaryentry{TNFalpha}{
type={acronym},
sort={tumor necrosis factor alpha},
name={\TNFalpha},
first={\ifnotused{tumor necrosis factor alpha~(\TNFalpha)}{\TNFalpha}{TNF}},
description={tumor necrosis factor alpha}
}
Since \TNFalpha
already starts with a capital there's no need to worry about dealing with the case when the conditional in \ifnotused
selects the second argument.