Skip to content

Commit 9a7ce23

Browse files
committed
C++: handle lesser and greater operators in template parameters
Close universal-ctags#769. `<' and `>' operators can be used in parameters list of template like: template<char i, bool B = (i>0)> void f0(void) { } template<char i, bool B = i < 10> void f1(void) { } ctags could not handle them well. This commit tries to improve the way to handle them. The original checks only the balance of angle brackets. In addition the original way, this commit considers following things when checking the balance of angle brackets: 1. lesser and greater operators between rounded brackets are ignored. 2. When `=' is found, lesser and greater operators are ignore till the input satisfies one of following conditions: 2.1 `,' is found outside rounded brackets, or 2.2 `>' is found outside rounded brackets, Signed-off-by: Masatake YAMATO <[email protected]>
1 parent 16aa144 commit 9a7ce23

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--sort=no
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
f0 input.cpp /^template<char i, bool B = (i>0)> void f0(void) { }$/;" f
2+
f1 input.cpp /^template<char i, bool B = i < 10> void f1(void) { }$/;" f
3+
f2 input.cpp /^template<char i, long j = (i << 10)> void f2(void) { }$/;" f
4+
f3 input.cpp /^template<char i, long j = i << 10> void f3(void) { }$/;" f
5+
f4 input.cpp /^template<char i, long j = (i >> 10)> void f4(void) { }$/;" f
6+
f5 input.cpp /^template<char i, long j = (i > 10)> void f5(void) { }$/;" f
7+
f6 input.cpp /^template<char i, bool B = (i <= 10)> void f6(void) { }$/;" f
8+
f7 input.cpp /^template<char i, bool B = (i >= 10)> void f7(void) { }$/;" f
9+
f8 input.cpp /^template<char i, char j, bool B = i < 10 && (30 > j)> void f8(void) { }$/;" f
10+
f9 input.cpp /^template<char i, char j, bool B = i < (10 && 30 > j)> void f9(void) { }$/;" f
11+
f10 input.cpp /^template<char i, char j, bool B = (i < 10 && 30 > j)> void f10(void) { }$/;" f
12+
f11 input.cpp /^template<bool b = 0 < 2 && 2 < 4> void f11(void) { }$/;" f
13+
main input.cpp /^int main(void) { return 0; }$/;" f
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* "gcc input.cpp -c -std=c++11" accepts this source code. */
2+
3+
template<char i, bool B = (i>0)> void f0(void) { }
4+
template<char i, bool B = i < 10> void f1(void) { }
5+
template<char i, long j = (i << 10)> void f2(void) { }
6+
template<char i, long j = i << 10> void f3(void) { }
7+
template<char i, long j = (i >> 10)> void f4(void) { }
8+
template<char i, long j = (i > 10)> void f5(void) { }
9+
template<char i, bool B = (i <= 10)> void f6(void) { }
10+
template<char i, bool B = (i >= 10)> void f7(void) { }
11+
template<char i, char j, bool B = i < 10 && (30 > j)> void f8(void) { }
12+
template<char i, char j, bool B = i < (10 && 30 > j)> void f9(void) { }
13+
template<char i, char j, bool B = (i < 10 && 30 > j)> void f10(void) { }
14+
template<bool b = 0 < 2 && 2 < 4> void f11(void) { }
15+
template<typename T1, typename T2> class A;
16+
int main(void) { return 0; }

parsers/c.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1761,6 +1761,54 @@ static void skipToMatch (const char *const pair)
17611761
}
17621762
}
17631763

1764+
static void skipCppTemplateParameterList (void)
1765+
{
1766+
const unsigned long inputLineNumber = getInputLineNumber ();
1767+
int angleBracketsLevel = 1;
1768+
int c = '\0';
1769+
1770+
int roundBracketsLevel = 0;
1771+
boolean defaultValueExpected = FALSE;
1772+
1773+
while (angleBracketsLevel > 0 && (c = skipToNonWhite ()) != EOF)
1774+
{
1775+
if (CollectingSignature)
1776+
vStringPut (Signature, c);
1777+
1778+
if (c == '<')
1779+
{
1780+
if (roundBracketsLevel == 0)
1781+
{
1782+
if (defaultValueExpected == FALSE)
1783+
++angleBracketsLevel;
1784+
}
1785+
}
1786+
else if (c == '>')
1787+
{
1788+
if (roundBracketsLevel == 0)
1789+
{
1790+
--angleBracketsLevel;
1791+
defaultValueExpected = FALSE;
1792+
}
1793+
}
1794+
else if (c == '(')
1795+
roundBracketsLevel ++;
1796+
else if (c == ')')
1797+
roundBracketsLevel --;
1798+
else if (c == '=' && (roundBracketsLevel == 0))
1799+
defaultValueExpected = TRUE;
1800+
else if (c == ',' && (roundBracketsLevel == 0))
1801+
defaultValueExpected = FALSE;
1802+
}
1803+
1804+
if (c == EOF)
1805+
{
1806+
verbose ("%s: failed to find match for '%c' at line %lu\n",
1807+
getInputFileName (), '<', inputLineNumber);
1808+
longjmp (Exception, (int) ExceptionFormattingError);
1809+
}
1810+
}
1811+
17641812
static void skipParens (void)
17651813
{
17661814
const int c = skipToNonWhite ();
@@ -2523,7 +2571,10 @@ static void processAngleBracket (void)
25232571
} else if (languageSupportsGenerics () && c != '<' && c != '=') {
25242572
/* this is a template */
25252573
cppUngetc (c);
2526-
skipToMatch ("<>");
2574+
if (isInputLanguage (Lang_cpp))
2575+
skipCppTemplateParameterList ();
2576+
else
2577+
skipToMatch ("<>");
25272578
} else if (c == '<') {
25282579
/* skip "<<" or "<<=". */
25292580
c = cppGetc ();

0 commit comments

Comments
 (0)