Skip to content

Commit a0b321f

Browse files
authored
Merge pull request #4354 from masatake/c++--scope-op-in-specialization
C++: skip template arguments in template specializations
2 parents f1e09ef + e281716 commit a0b321f

File tree

9 files changed

+124
-3
lines changed

9 files changed

+124
-3
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
--sort=no
2+
--fields=+{signature}
3+
--kinds-C++=+fstz
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
TestUtil input.cpp /^struct TestUtil {$/;" s file:
2+
isNull input.cpp /^ static bool isNull(const T&) { return false; }$/;" f struct:TestUtil typeref:typename:bool file: signature:(const T &)
3+
__anon39cbdfcb010d input.cpp /^ static bool isNull(const T&) { return false; }$/;" z function:TestUtil::isNull typeref:typename:const T & file:
4+
TestUtil input.cpp /^struct TestUtil<T*> {$/;" s file:
5+
isNull input.cpp /^ static bool isNull(T* f) { return 0 == f; }$/;" f struct:TestUtil typeref:typename:bool file: signature:(T * f)
6+
f input.cpp /^ static bool isNull(T* f) { return 0 == f; }$/;" z function:TestUtil::isNull typeref:typename:T * file:
7+
memtype input.cpp /^struct memtype {};$/;" s file:
8+
klass input.cpp /^struct klass {};$/;" s file:
9+
isNull input.cpp /^TestUtil<const memtype klass::*&>::isNull(const memtype klass::* &f)$/;" f class:TestUtil typeref:typename:bool signature:(const memtype klass::* & f)
10+
f input.cpp /^TestUtil<const memtype klass::*&>::isNull(const memtype klass::* &f)$/;" z function:TestUtil::isNull typeref:typename:const memtype klass::* & file:
11+
Handler input.cpp /^struct Handler {$/;" s file:
12+
process input.cpp /^ void process(T value) { }$/;" f struct:Handler typeref:typename:void file: signature:(T value)
13+
value input.cpp /^ void process(T value) { }$/;" z function:Handler::process typeref:typename:T file:
14+
Handler input.cpp /^struct Handler<R (C::*)()> {$/;" s file:
15+
process input.cpp /^ void process(R (C::*method)()) { }$/;" f struct:Handler typeref:typename:void file: signature:(R (C::* method)())
16+
method input.cpp /^ void process(R (C::*method)()) { }$/;" z function:Handler::process typeref:typename:R (C::*)() file:
17+
Handler input.cpp /^struct Handler<R (C::*)(A)> {$/;" s file:
18+
process input.cpp /^ void process(R (C::*method)(A)) { }$/;" f struct:Handler typeref:typename:void file: signature:(R (C::* method)(A))
19+
method input.cpp /^ void process(R (C::*method)(A)) { }$/;" z function:Handler::process typeref:typename:R (C::*)(A) file:
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Derived from #4348 submitted by @gaborbernat.
2+
3+
// C++ template specialization that previously triggered scope management crash
4+
// Test case for issue 4344: assertion failure in cxxScopePushTop
5+
template <class T>
6+
struct TestUtil {
7+
static bool isNull(const T&) { return false; }
8+
};
9+
10+
template <class T>
11+
struct TestUtil<T*> {
12+
static bool isNull(T* f) { return 0 == f; }
13+
};
14+
15+
struct memtype {};
16+
struct klass {};
17+
18+
template <>
19+
inline
20+
bool
21+
TestUtil<const memtype klass::*&>::isNull(const memtype klass::* &f)
22+
{
23+
return 0 == f;
24+
}
25+
26+
// Additional test cases for complex template specializations
27+
template <typename T>
28+
struct Handler {
29+
void process(T value) { }
30+
};
31+
32+
template <typename R, typename C>
33+
struct Handler<R (C::*)()> {
34+
void process(R (C::*method)()) { }
35+
};
36+
37+
template <typename R, typename C, typename A>
38+
struct Handler<R (C::*)(A)> {
39+
void process(R (C::*method)(A)) { }
40+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cxx11
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--sort=no
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Point input.cpp /^struct Point {$/;" s file:
2+
distance input.cpp /^ int distance(void) {$/;" f struct:Point typeref:typename:int file:
3+
NS input.cpp /^namespace NS {$/;" n file:
4+
MyReal input.cpp /^ using MyReal = float;$/;" t namespace:NS typeref:typename:float file:
5+
MyVec input.cpp /^ using MyVec = T[2];$/;" t namespace:NS typeref:typename:T[2] file:
6+
distance input.cpp /^int Point<int>::distance(void) { return 1; }$/;" f class:Point typeref:typename:int
7+
distance input.cpp /^int Point<NS::MyReal>::distance(void) { return 1; }$/;" f class:Point typeref:typename:int
8+
distance input.cpp /^int Point<NS::MyVec<int>>::distance(void) { return 1; }$/;" f class:Point typeref:typename:int
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
template <class T>
2+
struct Point {
3+
int distance(void) {
4+
return 0;
5+
}
6+
};
7+
8+
namespace NS {
9+
using MyReal = float;
10+
template <class T>
11+
using MyVec = T[2];
12+
};
13+
14+
template<>
15+
int Point<int>::distance(void) { return 1; }
16+
17+
template<>
18+
int Point<NS::MyReal>::distance(void) { return 1; }
19+
20+
template<>
21+
int Point<NS::MyVec<int>>::distance(void) { return 1; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cxx11

parsers/cxx/cxx_parser_function.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,10 +1591,37 @@ int cxxParserEmitFunctionTags(
15911591
{
15921592
CXXToken * pScopeId = pInfo->pScopeStart;
15931593

1594-
pInfo->pScopeStart = cxxTokenChainNextTokenOfType(
1594+
while (1)
1595+
{
1596+
pInfo->pScopeStart = cxxTokenChainNextTokenOfType(
15951597
pInfo->pScopeStart,
1596-
CXXTokenTypeMultipleColons
1597-
);
1598+
CXXTokenTypeMultipleColons|CXXTokenTypeSmallerThanSign);
1599+
1600+
CXX_DEBUG_ASSERT(pInfo->pScopeStart,
1601+
"We could find neither '::' nor '<'");
1602+
if (!pInfo->pScopeStart)
1603+
{
1604+
pInfo->pScopeStart = pInfo->pIdentifierStart;
1605+
break;
1606+
}
1607+
1608+
if (cxxTokenTypeIs(pInfo->pScopeStart, CXXTokenTypeMultipleColons))
1609+
break; // Good!
1610+
1611+
if (cxxTokenTypeIs(pInfo->pScopeStart, CXXTokenTypeSmallerThanSign))
1612+
{
1613+
// Skip the template arguments.
1614+
// Should we add the template arguments to the scope? (FIXME)
1615+
pInfo->pScopeStart = cxxTokenChainSkipToEndOfTemplateAngleBracket(pInfo->pScopeStart);
1616+
CXX_DEBUG_ASSERT(pInfo->pScopeStart,
1617+
"We could not find '>', the end of template argument(s)");
1618+
if (!pInfo->pScopeStart)
1619+
{
1620+
pInfo->pScopeStart = pInfo->pIdentifierStart;
1621+
break;
1622+
}
1623+
}
1624+
}
15981625

15991626
CXX_DEBUG_ASSERT(pInfo->pScopeStart,"We should have found a next token here");
16001627

0 commit comments

Comments
 (0)