Skip to content

Commit

Permalink
Merge pull request #1673 from pragmaware/fix-1671
Browse files Browse the repository at this point in the history
CXX: Fix #1671
  • Loading branch information
pragmaware committed Feb 1, 2018
2 parents 17d07a3 + 1fc679b commit 27728ac
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 29 deletions.
5 changes: 5 additions & 0 deletions Units/parser-cxx.r/bug-github-1671.cpp.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
my_function input.cpp /^void my_function()$/;" f typeref:typename:void
tabs input.cpp /^struct tabs { const static long value = x; };$/;" s file:
tabs input.cpp /^struct tabs<x,typename enable_if_c<(x<0)>::type> { const static long value = -x; };$/;" s file:
value input.cpp /^struct tabs { const static long value = x; };$/;" m struct:tabs typeref:typename:const long file:
value input.cpp /^struct tabs<x,typename enable_if_c<(x<0)>::type> { const static long value = -x; };$/;" m struct:tabs typeref:typename:const long file:
12 changes: 12 additions & 0 deletions Units/parser-cxx.r/bug-github-1671.cpp.d/input.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* Bug #1671 reported by davisking on 2018.01.28 */

template <long x, typename enabled=void>
struct tabs { const static long value = x; };

// specialize tabs
template <long x>
struct tabs<x,typename enable_if_c<(x<0)>::type> { const static long value = -x; };

void my_function()
{
}
16 changes: 8 additions & 8 deletions parsers/cxx/cxx_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,21 +974,21 @@ static bool cxxParserParseClassStructOrUnionInternal(
break;

// Probably a template specialisation
if(!cxxParserCurrentLanguageIsCPP())
{
cxxKeywordEnableFinal(false);
CXX_DEBUG_LEAVE_TEXT("Template specialization in C language?");
return false;
}

// template<typename T> struct X<int>
// {
// }

// FIXME: Should we add the specialisation arguments somewhere?
// Maybe as a separate field?

bRet = cxxParserParseAndCondenseCurrentSubchain(
CXXTokenTypeOpeningParenthesis | CXXTokenTypeOpeningBracket |
CXXTokenTypeOpeningSquareParenthesis |
CXXTokenTypeSmallerThanSign,
false,
false
);

bRet = cxxParserParseTemplateAngleBracketsToSeparateChain();

if(!bRet)
{
Expand Down
1 change: 1 addition & 0 deletions parsers/cxx/cxx_parser_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ bool cxxParserParseUpToOneOf(unsigned int uTokenTypes,
bool bCanReduceInnerElements);
bool cxxParserParseIfForWhileSwitch(void);
bool cxxParserParseTemplatePrefix(void);
bool cxxParserParseTemplateAngleBracketsToSeparateChain(void);
bool cxxParserParseUsingClause(void);
bool cxxParserParseAccessSpecifier(void);
void cxxParserAnalyzeOtherStatement(void);
Expand Down
69 changes: 48 additions & 21 deletions parsers/cxx/cxx_parser_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@


//
// Parses the <parameters> part of the template prefix.
// Here we are pointing at the initial < (but the token chain has been
// emptied by cxxParserParseTemplatePrefix())
// Parses the <parameters> part of a template specification.
// Here we are pointing at the initial <.
//
static bool cxxParserParseTemplatePrefixAngleBrackets(void)
static bool cxxParserParseTemplateAngleBrackets(void)
{
CXX_DEBUG_ENTER();

Expand All @@ -53,6 +52,11 @@ static bool cxxParserParseTemplatePrefixAngleBrackets(void)
// database etc) we simply can't do the same. However, we try to recover if we
// figure out we (or the programmer?) screwed up.

CXX_DEBUG_ASSERT(
cxxTokenTypeIs(cxxTokenChainLast(g_cxx.pTokenChain),CXXTokenTypeSmallerThanSign),
"We should be pointing at the opening angle bracket here"
);

int iTemplateLevel = 0;

for(;;)
Expand Down Expand Up @@ -252,6 +256,42 @@ static bool cxxParserParseTemplatePrefixAngleBrackets(void)
return true;
}

//
// Parses the template angle brackets and puts it in g_cxx.pTemplateTokenChain.
//
bool cxxParserParseTemplateAngleBracketsToSeparateChain(void)
{
CXX_DEBUG_ENTER();

CXX_DEBUG_ASSERT(cxxParserCurrentLanguageIsCPP(),"This should be called only in C++");

CXX_DEBUG_ASSERT(
cxxTokenTypeIs(cxxTokenChainLast(g_cxx.pTokenChain),CXXTokenTypeSmallerThanSign),
"We should be pointing at the opening angle bracket here"
);

CXXTokenChain * pSave = g_cxx.pTokenChain;
g_cxx.pTokenChain = cxxTokenChainCreate();
cxxTokenChainAppend(g_cxx.pTokenChain,cxxTokenChainTakeLast(pSave));

if(!cxxParserParseTemplateAngleBrackets())
{
CXX_DEBUG_LEAVE_TEXT("Failed to parse angle brackets");
cxxTokenChainDestroy(pSave);
return false;
}

if(g_cxx.pTemplateTokenChain)
cxxTokenChainDestroy(g_cxx.pTemplateTokenChain);

g_cxx.pTemplateTokenChain = g_cxx.pTokenChain;
g_cxx.pTokenChain = pSave;

CXX_DEBUG_LEAVE();
return true;
}


//
// Parses a template<anything> prefix.
// The parsed template parameter definition is stored in a separate token chain.
Expand All @@ -260,6 +300,8 @@ bool cxxParserParseTemplatePrefix(void)
{
CXX_DEBUG_ENTER();

CXX_DEBUG_ASSERT(cxxParserCurrentLanguageIsCPP(),"This should be called only in C++");

CXX_DEBUG_ASSERT(
cxxTokenTypeIs(cxxTokenChainLast(g_cxx.pTokenChain),CXXTokenTypeKeyword),
"We should be pointing at the template keyword here"
Expand All @@ -283,23 +325,8 @@ bool cxxParserParseTemplatePrefix(void)
return true; // tolerate syntax error
}

CXXTokenChain * pSave = g_cxx.pTokenChain;
g_cxx.pTokenChain = cxxTokenChainCreate();
cxxTokenChainAppend(g_cxx.pTokenChain,cxxTokenChainTakeLast(pSave));

if(!cxxParserParseTemplatePrefixAngleBrackets())
{
CXX_DEBUG_LEAVE_TEXT("Failed to parse angle brackets");
cxxTokenChainDestroy(pSave);
return false;
}

if(g_cxx.pTemplateTokenChain)
cxxTokenChainDestroy(g_cxx.pTemplateTokenChain);

g_cxx.pTemplateTokenChain = g_cxx.pTokenChain;
g_cxx.pTokenChain = pSave;
bool bRet = cxxParserParseTemplateAngleBracketsToSeparateChain();

CXX_DEBUG_LEAVE();
return true;
return bRet;
}

0 comments on commit 27728ac

Please sign in to comment.