@@ -824,17 +824,28 @@ namespace {
824824 isLong == other.isLong ;
825825 }
826826 };
827+
828+ // A parsed function template declaration that type deduction supports. Invalid
829+ // (typeParameters is empty) when the declaration is not supported.
830+ struct DeductionCandidate {
831+ std::vector<const Token*> typeParameters;
832+ std::vector<ParameterShape> parameterShapes;
833+ std::string signature;
834+ };
827835}
828836
829- static bool parseParameterShape (const Token* start, const std::vector<const Token*>& typeParameters, ParameterShape& shape)
837+ // Parse a function parameter of a template declaration. The returned shape has no
838+ // typeTok when the parameter does not have a supported form.
839+ static ParameterShape parseParameterShape (const Token* start, const std::vector<const Token*>& typeParameters)
830840{
841+ ParameterShape shape;
831842 const Token* tok = start;
832843 if (Token::simpleMatch (tok, " const" )) {
833844 shape.isConst = true ;
834845 tok = tok->next ();
835846 }
836847 if (!Token::Match (tok, " %type%" ) || Token::Match (tok, " const|struct|class|union|enum" ))
837- return false ;
848+ return ParameterShape () ;
838849 shape.typeTok = tok;
839850 tok = tok->next ();
840851 if (Token::simpleMatch (tok, " *" )) {
@@ -847,32 +858,33 @@ static bool parseParameterShape(const Token* start, const std::vector<const Toke
847858 if (Token::Match (tok, " %name% ,|)" ))
848859 tok = tok->next ();
849860 if (!Token::Match (tok, " ,|)" ))
850- return false ;
861+ return ParameterShape () ;
851862 const auto it = std::find_if (typeParameters.cbegin (), typeParameters.cend (), [&](const Token* typeParameter) {
852863 return typeParameter->str () == shape.typeTok ->str ();
853864 });
854865 if (it != typeParameters.cend ())
855866 shape.templateParameterIndex = static_cast <int >(it - typeParameters.cbegin ());
856- return true ;
867+ return shape ;
857868}
858869
859870// Convert the ValueType of an argument expression to the type that the parameter shape
860- // deduces for its template parameter. Returns false when the type is not supported.
861- static bool valueTypeToDeducedType (const ValueType* vt, const ParameterShape& shape, DeducedType& deduced)
871+ // deduces for its template parameter. The returned type has an empty typeStr when the
872+ // type is not supported.
873+ static DeducedType valueTypeToDeducedType (const ValueType* vt, const ParameterShape& shape)
862874{
863875 if (!vt)
864- return false ;
876+ return DeducedType () ;
865877 if (vt->bits > 0 || vt->volatileness != 0 )
866- return false ;
878+ return DeducedType () ;
867879 if (vt->smartPointer || vt->smartPointerType || vt->smartPointerTypeToken || vt->container || vt->containerTypeToken )
868- return false ;
880+ return DeducedType () ;
869881
870882 int pointer = vt->pointer ;
871883 unsigned int constness = vt->constness ;
872884 if (shape.isPointer ) {
873885 // "T *": the argument must be a pointer and T is the pointee type
874886 if (pointer < 1 )
875- return false ;
887+ return DeducedType () ;
876888 constness &= ~(1U << pointer);
877889 --pointer;
878890 } else if (!shape.isReference || shape.isConst ) {
@@ -882,9 +894,10 @@ static bool valueTypeToDeducedType(const ValueType* vt, const ParameterShape& sh
882894 // else "T &": the constness is part of the deduced type
883895
884896 if (pointer > 2 )
885- return false ;
897+ return DeducedType () ;
886898 if (constness >= (1U << (pointer + 1 )))
887- return false ;
899+ return DeducedType ();
900+ DeducedType deduced;
888901 deduced.pointer = pointer;
889902 deduced.constness = constness;
890903
@@ -929,22 +942,22 @@ static bool valueTypeToDeducedType(const ValueType* vt, const ParameterShape& sh
929942 case ValueType::RECORD : {
930943 const Scope* typeScope = vt->typeScope ;
931944 if (!typeScope || typeScope->className .empty () || !typeScope->isClassOrStructOrUnion ())
932- return false ;
945+ return DeducedType () ;
933946 deduced.typeStr = typeScope->className ;
934947 for (const Scope* nested = typeScope->nestedIn ; nested && nested->type != ScopeType::eGlobal; nested = nested->nestedIn ) {
935948 if (nested->type != ScopeType::eNamespace && !nested->isClassOrStructOrUnion ())
936- return false ; // local types etc. cannot be named - bail out
949+ return DeducedType () ; // local types etc. cannot be named - bail out
937950 if (nested->className .empty ())
938- return false ;
951+ return DeducedType () ;
939952 deduced.qualification .insert (deduced.qualification .cbegin (), nested->className );
940953 }
941954 break ;
942955 }
943956 default :
944- return false ;
957+ return DeducedType () ;
945958 }
946959
947- return true ;
960+ return deduced ;
948961}
949962
950963// Is there a non template function with the given name in the scope? Overload
@@ -990,14 +1003,14 @@ static void insertDeducedType(Token* tok, const DeducedType& deduced)
9901003 tok->insertToken (" const" );
9911004}
9921005
993- void TemplateSimplifier::deduceFunctionTemplateArguments (Token* tok,
994- std::string& qualification,
995- const std::string& scopeName,
996- const std::multimap<std::string, const TokenAndName*>& functionNameMap)
1006+ std::string TemplateSimplifier::deduceFunctionTemplateArguments (Token* tok,
1007+ std::string qualification,
1008+ const std::string& scopeName,
1009+ const std::multimap<std::string, const TokenAndName*>& functionNameMap)
9971010{
9981011 const auto range = functionNameMap.equal_range (tok->str ());
9991012 if (range.first == range.second )
1000- return ;
1013+ return qualification ;
10011014
10021015 std::string fullName;
10031016 if (!qualification.empty ())
@@ -1096,85 +1109,82 @@ void TemplateSimplifier::deduceFunctionTemplateArguments(Token* tok,
10961109 break ;
10971110 }
10981111 tok->insertToken (" <" );
1099- return ;
1112+ return qualification ;
11001113 }
11011114 }
11021115 }
11031116
11041117 // the remaining deduction needs the types of the argument expressions
11051118 if (instantiationArgs.empty ())
1106- return ;
1119+ return qualification ;
11071120
11081121 // a call through a variable (function object, function pointer) is not a template instantiation
11091122 if (tok->varId () != 0 )
1110- return ;
1123+ return qualification ;
11111124 // a call that the symbol database resolved to a real (non template) function must not
11121125 // be hijacked - overload resolution against non templates is not implemented here
11131126 if (tok->function () && !tok->function ()->templateDef )
1114- return ;
1127+ return qualification ;
11151128
11161129 // Parse a candidate declaration: all parameters must have a supported form and
11171130 // every template parameter must be deducible from the function parameters. The
11181131 // signature identifies the parameter list, so a forward declaration and the
11191132 // definition of the same template can be recognized.
1120- auto parseDeductionCandidate = [&](const TokenAndName& candidate,
1121- std::vector<const Token*>& typeParameters,
1122- std::vector<ParameterShape>& parameterShapes,
1123- std::string& signature) -> bool {
1133+ auto parseDeductionCandidate = [&](const TokenAndName& candidate) -> DeductionCandidate {
11241134 if (candidate.isVariadic ())
1125- return false ;
1135+ return DeductionCandidate () ;
11261136
1127- getTemplateParametersInDeclaration (candidate.token ()->tokAt (2 ), typeParameters);
1128- if (typeParameters.empty () || !areAllParamsTypes (typeParameters))
1129- return false ;
1137+ DeductionCandidate parsed;
1138+ getTemplateParametersInDeclaration (candidate.token ()->tokAt (2 ), parsed.typeParameters );
1139+ if (parsed.typeParameters .empty () || !areAllParamsTypes (parsed.typeParameters ))
1140+ return DeductionCandidate ();
11301141
11311142 std::vector<const Token*> declarationParams;
11321143 getFunctionArguments (candidate.nameToken (), declarationParams);
11331144 if (declarationParams.size () != instantiationArgs.size ())
1134- return false ;
1145+ return DeductionCandidate () ;
11351146
1136- std::vector<bool > deducible (typeParameters.size (), false );
1137- signature = candidate.fullName ();
1147+ std::vector<bool > deducible (parsed. typeParameters .size (), false );
1148+ parsed. signature = candidate.fullName ();
11381149 for (const Token* param : declarationParams) {
1139- ParameterShape shape;
1140- if (!parseParameterShape (param, typeParameters, shape) )
1141- return false ;
1150+ const ParameterShape shape = parseParameterShape (param, parsed. typeParameters ) ;
1151+ if (!shape. typeTok )
1152+ return DeductionCandidate () ;
11421153 if (shape.templateParameterIndex >= 0 )
11431154 deducible[shape.templateParameterIndex ] = true ;
1144- parameterShapes.push_back (shape);
1145- signature += (shape.isConst ? " const" : " " );
1155+ parsed. parameterShapes .push_back (shape);
1156+ parsed. signature += (shape.isConst ? " const" : " " );
11461157 // template parameters are compared by position - their names may differ
11471158 // between a forward declaration and the definition
11481159 if (shape.templateParameterIndex >= 0 )
1149- signature += " $" + std::to_string (shape.templateParameterIndex );
1160+ parsed. signature += " $" + std::to_string (shape.templateParameterIndex );
11501161 else
1151- signature += " " + shape.typeTok ->str ();
1152- signature += (shape.isPointer ? " *" : shape.isReference ? " &" : " " );
1153- signature += " ," ;
1162+ parsed. signature += " " + shape.typeTok ->str ();
1163+ parsed. signature += (shape.isPointer ? " *" : shape.isReference ? " &" : " " );
1164+ parsed. signature += " ," ;
11541165 }
1155- return std::all_of (deducible.cbegin (), deducible.cend (), [](bool b) {
1166+ if (! std::all_of (deducible.cbegin (), deducible.cend (), [](bool b) {
11561167 return b;
1157- });
1168+ }))
1169+ return DeductionCandidate ();
1170+ return parsed;
11581171 };
11591172
11601173 if (!mUseTypeInformation ) {
11611174 // Can the deduction succeed later, when type information is available? Scope
11621175 // matching is not possible yet - the declaration may be in a base class - so
11631176 // consider all declarations with this name.
11641177 for (auto pos = range.first ; pos != range.second ; ++pos) {
1165- std::vector<const Token*> typeParameters;
1166- std::vector<ParameterShape> parameterShapes;
1167- std::string signature;
1168- if (parseDeductionCandidate (*pos->second , typeParameters, parameterShapes, signature)) {
1178+ if (!parseDeductionCandidate (*pos->second ).typeParameters .empty ()) {
11691179 mPendingTypeDeductions = true ;
1170- return ;
1180+ return qualification ;
11711181 }
11721182 }
1173- return ;
1183+ return qualification ;
11741184 }
11751185
11761186 if (!tok->scope ())
1177- return ;
1187+ return qualification ;
11781188
11791189 // The scopes where the call name is looked up, in lookup order: the innermost scope
11801190 // with matching declarations wins. At class scopes the transitive base classes are
@@ -1241,7 +1251,7 @@ void TemplateSimplifier::deduceFunctionTemplateArguments(Token* tok,
12411251 for (const LookupLevel& level : levels) {
12421252 // a non template function with the same name might be a better overload match
12431253 if (level.scope && scopeHasNonTemplateFunction (level.scope , tok->str ()))
1244- return ;
1254+ return qualification ;
12451255 const std::string lookupName = level.scopeName .empty () ? tok->str () : (level.scopeName + " :: " + tok->str ());
12461256 for (auto pos = range.first ; pos != range.second ; ++pos) {
12471257 if (pos->second ->fullName () == lookupName)
@@ -1256,53 +1266,47 @@ void TemplateSimplifier::deduceFunctionTemplateArguments(Token* tok,
12561266
12571267 // parse the candidate declarations
12581268 const TokenAndName* declaration = nullptr ;
1259- std::vector<const Token*> typeParameters;
1260- std::vector<ParameterShape> parameterShapes;
1261- std::string declarationSignature;
1269+ DeductionCandidate parsedDeclaration;
12621270 for (const TokenAndName* candidate : candidates) {
1263- std::vector<const Token*> candidateTypeParameters;
1264- std::vector<ParameterShape> candidateShapes;
1265- std::string signature;
1266- if (!parseDeductionCandidate (*candidate, candidateTypeParameters, candidateShapes, signature))
1271+ DeductionCandidate parsed = parseDeductionCandidate (*candidate);
1272+ if (parsed.typeParameters .empty ())
12671273 continue ;
12681274
12691275 if (declaration) {
12701276 // multiple overloads could match: overload resolution is not implemented => bail out
1271- if (signature != declarationSignature )
1272- return ;
1277+ if (parsed. signature != parsedDeclaration. signature )
1278+ return qualification ;
12731279 continue ; // forward declaration and definition of the same template
12741280 }
12751281 declaration = candidate;
1276- typeParameters = std::move (candidateTypeParameters);
1277- parameterShapes = std::move (candidateShapes);
1278- declarationSignature = std::move (signature);
1282+ parsedDeclaration = std::move (parsed);
12791283 }
12801284 if (!declaration)
1281- return ;
1285+ return qualification ;
12821286
12831287 // deduce the template parameters from the ValueTypes of the argument expressions
12841288 const std::vector<const Token*> argRoots = getArguments (tok);
12851289 if (argRoots.size () != instantiationArgs.size ())
1286- return ;
1287- std::vector<DeducedType> deducedTypes (typeParameters.size ());
1288- std::vector<bool > deducedSet (typeParameters.size (), false );
1289- for (std::size_t i = 0 ; i < parameterShapes.size (); ++i) {
1290- const ParameterShape& shape = parameterShapes[i];
1290+ return qualification ;
1291+ std::vector<DeducedType> deducedTypes (parsedDeclaration. typeParameters .size ());
1292+ std::vector<bool > deducedSet (parsedDeclaration. typeParameters .size (), false );
1293+ for (std::size_t i = 0 ; i < parsedDeclaration. parameterShapes .size (); ++i) {
1294+ const ParameterShape& shape = parsedDeclaration. parameterShapes [i];
12911295 if (shape.templateParameterIndex < 0 )
12921296 continue ;
12931297 const ValueType* vt = argRoots[i]->valueType ();
12941298 if (!vt) {
12951299 // type information is not available (yet) for this argument
12961300 mPendingTypeDeductions = true ;
1297- return ;
1301+ return qualification ;
12981302 }
1299- DeducedType deduced;
1300- if (! valueTypeToDeducedType (vt, shape, deduced))
1301- return ;
1303+ DeducedType deduced = valueTypeToDeducedType (vt, shape) ;
1304+ if (deduced. typeStr . empty ( ))
1305+ return qualification ;
13021306 if (deducedSet[shape.templateParameterIndex ]) {
13031307 // inconsistent deduction => don't deduce
13041308 if (!(deducedTypes[shape.templateParameterIndex ] == deduced))
1305- return ;
1309+ return qualification ;
13061310 } else {
13071311 deducedTypes[shape.templateParameterIndex ] = std::move (deduced);
13081312 deducedSet[shape.templateParameterIndex ] = true ;
@@ -1338,6 +1342,7 @@ void TemplateSimplifier::deduceFunctionTemplateArguments(Token* tok,
13381342 rememberDirtyCallSite (tok);
13391343 mTypeDeductionsMade = true ;
13401344 mChanged = true ;
1345+ return qualification;
13411346}
13421347
13431348void TemplateSimplifier::getTemplateInstantiations ()
@@ -1417,7 +1422,7 @@ void TemplateSimplifier::getTemplateInstantiations()
14171422
14181423 // look for function instantiation with type deduction
14191424 if (tok->strAt (1 ) == " (" )
1420- deduceFunctionTemplateArguments (tok, qualification, scopeName, functionNameMap);
1425+ qualification = deduceFunctionTemplateArguments (tok, qualification, scopeName, functionNameMap);
14211426
14221427 if (!Token::Match (tok, " %name% <" ) ||
14231428 Token::Match (tok, " const_cast|dynamic_cast|reinterpret_cast|static_cast" ))
0 commit comments