Skip to content

Commit

Permalink
Merge pull request #3416 from delsner/bugfix/#3388-fix-template-funct…
Browse files Browse the repository at this point in the history
…ion-return-type

#3388 Bugfix for cpp template function return types

MERGING without getting a review from @pragmaware.
  • Loading branch information
masatake committed Jun 26, 2022
2 parents 7c12820 + 7dd0cdf commit af8c172
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ template<typename T,int I,int J = I < V> K funcC(T t)
}

// The original comment: This stuff is allowed by C++03
// template<typename T,int I,int J = (I >> 2)> K funcD(T t)
// template<typename T,int I,int J = I >> 2> K funcD(T t)
// However, the above input is rejected with:
// error: default template arguments may not be used in function templates
// without `-std=c++11' or `-std=gnu++11'
Expand Down
3 changes: 3 additions & 0 deletions Units/parser-cxx.r/templates7.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--sort=no
--kinds-C++=*
--fields-c++=+{template}
8 changes: 8 additions & 0 deletions Units/parser-cxx.r/templates7.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
foo input.hpp /^A foo()$/;" f typeref:typename:A template:<typename A,typename B>
A input.hpp /^template<typename A, typename B>$/;" Z function:foo typeref:meta:typename
B input.hpp /^template<typename A, typename B>$/;" Z function:foo typeref:meta:typename
bar input.hpp /^A& bar(A& a, const B& b)$/;" f typeref:typename:A & template:<typename A,typename B>
A input.hpp /^template<typename A, typename B>$/;" Z function:bar typeref:meta:typename
B input.hpp /^template<typename A, typename B>$/;" Z function:bar typeref:meta:typename
a input.hpp /^A& bar(A& a, const B& b)$/;" z function:bar typeref:typename:A & file:
b input.hpp /^A& bar(A& a, const B& b)$/;" z function:bar typeref:typename:const B & file:
11 changes: 11 additions & 0 deletions Units/parser-cxx.r/templates7.d/input.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
template<typename A, typename B>
A foo()
{
return A();
}

template<typename A, typename B>
A& bar(A& a, const B& b)
{
return a;
}
1 change: 1 addition & 0 deletions Units/parser-cxx.r/templates7.d/validator
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cxx11
36 changes: 6 additions & 30 deletions parsers/cxx/cxx_parser_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,10 @@ cxxParserParseTemplateAngleBracketsInternal(bool bCaptureTypeParameters,int iNes
// around but without proper state (include headers, macro expansion, full type
// database etc) we simply can't do the same. However, we try to recover if we
// figure out we (or the programmer?) screwed up.
//
// For 'greater-than' operators, the first non-nested operator is taken as the
// end of the template parameter list rather than a 'greater-than' operator.
// Treating non-nested operators differently is a syntax error at least since C++03
// onwards according to https://en.cppreference.com/w/cpp/language/template_parameters.
//
// Like gcc, if this function knows identifiers in a template prefix more,
// the quality of parsing becomes better.
Expand Down Expand Up @@ -421,35 +424,8 @@ cxxParserParseTemplateAngleBracketsInternal(bool bCaptureTypeParameters,int iNes

CXX_DEBUG_PRINT("Found %d greater-than signs",iGreaterThanCount);

// check greater than operator: very narrow conditions
if(
(iGreaterThanCount == 1) &&
(
// whatever op 2 [C++03 allows this without parens]
// whatever op (...) [C++03 allows this without parens]
cxxTokenTypeIsOneOf(
g_cxx.pToken,
CXXTokenTypeNumber | CXXTokenTypeOpeningParenthesis
) ||
// whatever op nonTypeParameter [C++03 allows this without parens]
(
cxxTokenTypeIs(g_cxx.pToken,CXXTokenTypeIdentifier) &&
cxxTokenIsPresentInTemplateParametersAsNonType(g_cxx.pToken)
)
// WARNING: don't be tempted to add a loose condition that has
// (!cxxTokenIsPresentInTemplateParametersAsType()) on the right.
// It's unsafe.
)
)
{
CXX_DEBUG_PRINT("Treating as greater-than sign");

if(cxxTokenTypeIsOneOf(g_cxx.pToken,CXXTokenTypeOpeningParenthesis))
cxxParserUngetCurrentToken(); // needs to be condensed

continue;
}

// We do not check for the greater than operator, as it is only valid
// inside parentheses in a template parameter list (see i#3388).

// check right shift operator: a bit broader conditions
if(
Expand Down

0 comments on commit af8c172

Please sign in to comment.