@@ -1308,7 +1308,13 @@ namespace {
13081308 }
13091309
13101310 void addFunction (const std::string &name, const ParsedType &returnType) {
1311- mScopes .back ().members .functions [name].push_back (returnType);
1311+ std::vector<ParsedType> &declarations = mScopes .back ().members .functions [name];
1312+ // the walk can record a declaration twice (class members are
1313+ // recorded up front and again when the body is walked)
1314+ if (std::none_of (declarations.cbegin (), declarations.cend (), [&](const ParsedType &declaration) {
1315+ return sameDeducedType (declaration.type , returnType.type );
1316+ }))
1317+ declarations.push_back (returnType);
13121318 }
13131319
13141320 bool lookupVariable (const std::string &name, ParsedType &result) const {
@@ -1959,6 +1965,46 @@ static void deduceTemplateArgumentsAtFunctionCall(const DeductionContext &ctx, T
19591965 insertPos->insertToken (" >" );
19601966}
19611967
1968+ // Record |tok| in the symbol table when it is the name of a variable or
1969+ // function declaration.
1970+ static void recordDeclaration (const DeductionContext &ctx, DeductionSymbolTable &symbols, const Token *tok)
1971+ {
1972+ ParsedType parsed;
1973+ if (parseVariableDeclaration (ctx, tok, parsed)) {
1974+ symbols.addVariable (tok->str (), parsed);
1975+ } else if (Token::simpleMatch (tok->next (), " (" ) && tok->next ()->link () &&
1976+ !Token::Match (tok->previous (), " .|::|->|new" )) {
1977+ // function declaration: record the return type
1978+ const Token *rpar = tok->next ()->link ();
1979+ if (Token::Match (rpar->next (), " ;|{|const|noexcept" )) {
1980+ const Token *start = findDeclarationTypeStart (ctx, tok);
1981+ if (start && parseType (ctx, start, tok, parsed) == tok && parsed.type .valid )
1982+ symbols.addFunction (tok->str (), parsed);
1983+ }
1984+ }
1985+ }
1986+
1987+ // Record the member declarations of the class body starting at |bodyStart|
1988+ // before it is walked: in a complete-class context (member function bodies,
1989+ // default arguments, constructor initializer lists) the members that are
1990+ // declared later in the class are visible too. The scan is shallow - nested
1991+ // bodies contain locals and nested class members, not members of this class.
1992+ static void recordClassMembers (const DeductionContext &ctx, DeductionSymbolTable &symbols, const Token *bodyStart)
1993+ {
1994+ const Token *const bodyEnd = bodyStart->link ();
1995+ for (const Token *tok = bodyStart->next (); tok && tok != bodyEnd; tok = tok->next ()) {
1996+ if (tok->link () && Token::Match (tok, " (|{|[" ))
1997+ tok = tok->link ();
1998+ else if (Token::simpleMatch (tok, " template <" )) {
1999+ const Token *closing = tok->next ()->findClosingBracket ();
2000+ if (!closing)
2001+ return ;
2002+ tok = closing;
2003+ } else if (tok->isName ())
2004+ recordDeclaration (ctx, symbols, tok);
2005+ }
2006+ }
2007+
19622008void TemplateSimplifier::deduceFunctionTemplateArguments ()
19632009{
19642010 // map from name to the function template declarations a call could instantiate
@@ -1999,6 +2045,9 @@ void TemplateSimplifier::deduceFunctionTemplateArguments()
19992045 symbols.leaveScopesEndingAt (tok);
20002046 else if (tok == classBodyStart) {
20012047 symbols.enterClassScope (tok->link (), std::move (className));
2048+ // members declared later in the class are visible in the
2049+ // member function bodies: record them all up front
2050+ recordClassMembers (ctx, symbols, tok);
20022051 classBodyStart = nullptr ;
20032052 } else if (Token::Match (tok, " (|{" ))
20042053 symbols.enterScope (tok->link ());
@@ -2149,19 +2198,7 @@ void TemplateSimplifier::deduceFunctionTemplateArguments()
21492198 }
21502199
21512200 // record variable and function declarations
2152- ParsedType parsed;
2153- if (parseVariableDeclaration (ctx, tok, parsed)) {
2154- symbols.addVariable (tok->str (), parsed);
2155- } else if (Token::simpleMatch (tok->next (), " (" ) && tok->next ()->link () &&
2156- !Token::Match (tok->previous (), " .|::|->|new" )) {
2157- // function declaration: record the return type
2158- const Token *rpar = tok->next ()->link ();
2159- if (Token::Match (rpar->next (), " ;|{|const|noexcept" )) {
2160- const Token *start = findDeclarationTypeStart (ctx, tok);
2161- if (start && parseType (ctx, start, tok, parsed) == tok && parsed.type .valid )
2162- symbols.addFunction (tok->str (), parsed);
2163- }
2164- }
2201+ recordDeclaration (ctx, symbols, tok);
21652202 }
21662203}
21672204
0 commit comments