This commit is contained in:
parent
ab08801dc4
commit
adbbadec7f
|
@ -461,11 +461,6 @@ static std::string getScopeName(const std::list<ScopeInfo2> &scopeInfo)
|
|||
ret += (ret.empty() ? "" : " :: ") + i.name;
|
||||
return ret;
|
||||
}
|
||||
static std::string getFullName(const std::list<ScopeInfo2> &scopeInfo, const std::string &name)
|
||||
{
|
||||
const std::string &scopeName = getScopeName(scopeInfo);
|
||||
return scopeName + (scopeName.empty() ? "" : " :: ") + name;
|
||||
}
|
||||
|
||||
static void setScopeInfo(const Token *tok, std::list<ScopeInfo2> *scopeInfo)
|
||||
{
|
||||
|
@ -517,7 +512,7 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDecla
|
|||
if (forward) {
|
||||
const int namepos = getTemplateNamePosition(parmEnd, forward);
|
||||
if (namepos > 0)
|
||||
declarations.emplace_back(tok, getScopeName(scopeInfo), getFullName(scopeInfo, parmEnd->strAt(namepos)));
|
||||
declarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -526,7 +521,7 @@ std::list<TemplateSimplifier::TokenAndName> TemplateSimplifier::getTemplateDecla
|
|||
if (!forward) {
|
||||
const int namepos = getTemplateNamePosition(parmEnd, forward);
|
||||
if (namepos > 0)
|
||||
declarations.emplace_back(tok, getScopeName(scopeInfo), getFullName(scopeInfo, parmEnd->strAt(namepos)));
|
||||
declarations.emplace_back(tok, getScopeName(scopeInfo), parmEnd->strAt(namepos));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -577,7 +572,7 @@ void TemplateSimplifier::getTemplateInstantiations()
|
|||
for (; tok2 && tok2 != tok; tok2 = tok2->previous()) {
|
||||
if (Token::Match(tok2, ", %name% <") &&
|
||||
templateParameters(tok2->tokAt(2))) {
|
||||
mTemplateInstantiations.emplace_back(tok2->next(), getScopeName(scopeList), getFullName(scopeList, tok2->strAt(1)));
|
||||
mTemplateInstantiations.emplace_back(tok2->next(), getScopeName(scopeList), tok2->strAt(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,6 +807,11 @@ void TemplateSimplifier::simplifyTemplateAliases()
|
|||
// Replace template alias code..
|
||||
aliasUsage.name = templateAlias.name;
|
||||
if (aliasUsage.name.find(' ') == std::string::npos) {
|
||||
const Token *temp = aliasToken1;
|
||||
while (temp && temp != templateAlias.token) {
|
||||
aliasUsage.token->insertToken(temp->str(), "", true);
|
||||
temp = temp->next();
|
||||
}
|
||||
aliasUsage.token->str(templateAlias.token->str());
|
||||
} else {
|
||||
tok2 = TokenList::copyTokens(aliasUsage.token, aliasToken1, templateAlias.token, true);
|
||||
|
@ -957,8 +957,9 @@ int TemplateSimplifier::getTemplateNamePosition(const Token *tok, bool forward)
|
|||
|
||||
|
||||
void TemplateSimplifier::expandTemplate(
|
||||
const TokenAndName &templateDeclaration,
|
||||
const Token *templateDeclarationToken,
|
||||
const std::string &fullName,
|
||||
const TokenAndName &templateInstantiation,
|
||||
const std::vector<const Token *> &typeParametersInDeclaration,
|
||||
const std::string &newName,
|
||||
bool copy)
|
||||
|
@ -968,6 +969,15 @@ void TemplateSimplifier::expandTemplate(
|
|||
const Token *startOfTemplateDeclaration = nullptr;
|
||||
const Token *endOfTemplateDefinition = nullptr;
|
||||
const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt(getTemplateNamePosition(templateDeclarationToken));
|
||||
const bool isClass = Token::Match(templateDeclarationToken->next(), "class|struct|union %name% <|{|:");
|
||||
|
||||
// add forward declaration for classes
|
||||
if (copy && isClass) {
|
||||
templateDeclaration.token->insertToken(templateDeclarationToken->strAt(1), "", true);
|
||||
templateDeclaration.token->insertToken(newName, "", true);
|
||||
templateDeclaration.token->insertToken(";", "", true);
|
||||
}
|
||||
|
||||
for (Token *tok3 = mTokenList.front(); tok3; tok3 = tok3 ? tok3->next() : nullptr) {
|
||||
if (Token::Match(tok3, "}|namespace|class|struct|union")) {
|
||||
setScopeInfo(tok3, &scopeInfo);
|
||||
|
@ -1006,7 +1016,7 @@ void TemplateSimplifier::expandTemplate(
|
|||
// member function implemented outside class definition
|
||||
else if (inTemplateDefinition &&
|
||||
Token::Match(tok3, "%name% <") &&
|
||||
fullName == getFullName(scopeInfo, tok3->str()) &&
|
||||
templateInstantiation.name == tok3->str() &&
|
||||
instantiateMatch(tok3, typeParametersInDeclaration.size(), ":: ~| %name% (")) {
|
||||
// there must be template..
|
||||
bool istemplate = false;
|
||||
|
@ -1033,7 +1043,7 @@ void TemplateSimplifier::expandTemplate(
|
|||
// copy return type
|
||||
while (tok5 && tok5 != tok3) {
|
||||
// replace name if found
|
||||
if (Token::Match(tok5, "%name% <") && tok5->str() == fullName) {
|
||||
if (Token::Match(tok5, "%name% <") && tok5->str() == templateInstantiation.name) {
|
||||
if (copy) {
|
||||
mTokenList.addtoken(newName, tok5->linenr(), tok5->fileIndex());
|
||||
tok5 = tok5->next()->findClosingBracket();
|
||||
|
@ -1048,6 +1058,7 @@ void TemplateSimplifier::expandTemplate(
|
|||
}
|
||||
if (copy)
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
|
||||
while (tok3 && tok3->str() != "::")
|
||||
tok3 = tok3->next();
|
||||
|
||||
|
@ -1065,7 +1076,8 @@ void TemplateSimplifier::expandTemplate(
|
|||
std::stack<Token *> brackets; // holds "(", "[" and "{" tokens
|
||||
|
||||
// FIXME use full name matching somehow
|
||||
const std::string lastName = (fullName.find(' ') != std::string::npos) ? fullName.substr(fullName.rfind(' ')+1) : fullName;
|
||||
const std::string lastName = (templateInstantiation.name.find(' ') != std::string::npos) ? templateInstantiation.name.substr(templateInstantiation.name.rfind(' ')+1) : templateInstantiation.name;
|
||||
|
||||
|
||||
for (; tok3; tok3 = tok3->next()) {
|
||||
if (tok3->isName()) {
|
||||
|
@ -1099,22 +1111,39 @@ void TemplateSimplifier::expandTemplate(
|
|||
|
||||
// replace name..
|
||||
if (tok3->str() == lastName) {
|
||||
if (!Token::simpleMatch(tok3->next(), "<")) {
|
||||
if (copy)
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
else if (tok3->strAt(1) != ":")
|
||||
tok3->str(newName);
|
||||
else
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
continue;
|
||||
} else if (tok3 == templateDeclarationNameToken) {
|
||||
if (copy) {
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
tok3 = tok3->next()->findClosingBracket();
|
||||
} else {
|
||||
tok3->str(newName);
|
||||
eraseTokens(tok3, tok3->next()->findClosingBracket()->next());
|
||||
if (Token::simpleMatch(tok3->next(), "<")) {
|
||||
// replace multi token name with single token name
|
||||
if (tok3 == templateDeclarationNameToken || Token::Match(tok3, newName.c_str())) {
|
||||
Token *closingBracket = tok3->next()->findClosingBracket();
|
||||
if (closingBracket) {
|
||||
if (copy) {
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
tok3 = closingBracket;
|
||||
} else {
|
||||
tok3->str(newName);
|
||||
eraseTokens(tok3, closingBracket->next());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (copy) {
|
||||
// add namespace if necessary
|
||||
if (!templateDeclaration.scope.empty() && (isClass ? tok3->strAt(1) != "(" : true)) {
|
||||
std::string::size_type start = 0;
|
||||
std::string::size_type end = 0;
|
||||
std::string temp;
|
||||
while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) {
|
||||
std::string token = templateDeclaration.scope.substr(start, end - start);
|
||||
mTokenList.addtoken(token, tok3->linenr(), tok3->fileIndex());
|
||||
start = end + 1;
|
||||
}
|
||||
mTokenList.addtoken(templateDeclaration.scope.substr(start), tok3->linenr(), tok3->fileIndex());
|
||||
mTokenList.addtoken("::", tok3->linenr(), tok3->fileIndex());
|
||||
}
|
||||
mTokenList.addtoken(newName, tok3->linenr(), tok3->fileIndex());
|
||||
} else if (!Token::Match(tok3->next(), ":|{"))
|
||||
tok3->str(newName);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1142,7 +1171,7 @@ void TemplateSimplifier::expandTemplate(
|
|||
std::string name = tok3->str();
|
||||
for (const Token *prev = tok3->tokAt(-2); Token::Match(prev, "%name% ::"); prev = prev->tokAt(-2))
|
||||
name = prev->str() + " :: " + name;
|
||||
mTemplateInstantiations.emplace_back(mTokenList.back(), getScopeName(scopeInfo), getFullName(scopeInfo, name));
|
||||
mTemplateInstantiations.emplace_back(mTokenList.back(), getScopeName(scopeInfo), name);
|
||||
}
|
||||
|
||||
// link() newly tokens manually
|
||||
|
@ -1704,7 +1733,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
|||
|
||||
if (expandedtemplates.find(newName) == expandedtemplates.end()) {
|
||||
expandedtemplates.insert(newName);
|
||||
expandTemplate(tok, instantiation.name, typeParametersInDeclaration, newName, !specialized);
|
||||
expandTemplate(templateDeclaration, tok, instantiation, typeParametersInDeclaration, newName, !specialized);
|
||||
instantiated = true;
|
||||
}
|
||||
|
||||
|
@ -1785,7 +1814,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
|
|||
const std::string newName(templateDeclaration.name + " < " + typeForNewName + " >");
|
||||
if (expandedtemplates.find(newName) == expandedtemplates.end()) {
|
||||
expandedtemplates.insert(newName);
|
||||
expandTemplate(tok, templateDeclaration.name, typeParametersInDeclaration, newName, !specialized);
|
||||
expandTemplate(templateDeclaration, tok, templateDeclaration, typeParametersInDeclaration, newName, !specialized);
|
||||
instantiated = true;
|
||||
}
|
||||
|
||||
|
@ -1808,10 +1837,11 @@ static bool matchTemplateParameters(const Token *nameTok, const std::list<std::s
|
|||
return it == strings.end() && tok && tok->str() == ">";
|
||||
}
|
||||
|
||||
void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
||||
const std::string &templateName,
|
||||
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
||||
const std::string &newName)
|
||||
void TemplateSimplifier::replaceTemplateUsage(
|
||||
Token * const instantiationToken,
|
||||
const std::string &templateName,
|
||||
const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
|
||||
const std::string &newName)
|
||||
{
|
||||
std::list<ScopeInfo2> scopeInfo;
|
||||
std::list< std::pair<Token *, Token *> > removeTokens;
|
||||
|
@ -1867,8 +1897,6 @@ void TemplateSimplifier::replaceTemplateUsage(Token * const instantiationToken,
|
|||
// Foo < int > => Foo<int>
|
||||
if (tok2->str() == ">" && typeCountInInstantiation == mTypesUsedInTemplateInstantiation.size()) {
|
||||
const Token * const nameTok1 = nameTok;
|
||||
while (Token::Match(nameTok->tokAt(-2), "%name% :: %name%"))
|
||||
nameTok = nameTok->tokAt(-2);
|
||||
nameTok->str(newName);
|
||||
for (std::list<TokenAndName>::iterator it = mTemplateInstantiations.begin(); it != mTemplateInstantiations.end(); ++it) {
|
||||
if (it->token == nameTok1)
|
||||
|
|
|
@ -167,14 +167,17 @@ private:
|
|||
|
||||
/**
|
||||
* Expand a template. Create "expanded" class/function at end of tokenlist.
|
||||
* @param fullName Full name of template
|
||||
* @param templateDeclaration Template declaration information
|
||||
* @param templateDeclarationToken Template declaration token
|
||||
* @param templateInstantiation Full name of template
|
||||
* @param typeParametersInDeclaration The type parameters of the template
|
||||
* @param newName New name of class/function.
|
||||
* @param copy copy or expand in place
|
||||
*/
|
||||
void expandTemplate(
|
||||
const TokenAndName &templateDeclaration,
|
||||
const Token *templateDeclarationToken,
|
||||
const std::string &fullName,
|
||||
const TokenAndName &templateInstantiation,
|
||||
const std::vector<const Token *> &typeParametersInDeclaration,
|
||||
const std::string &newName,
|
||||
bool copy);
|
||||
|
|
|
@ -106,6 +106,8 @@ private:
|
|||
TEST_CASE(template66); // #8725
|
||||
TEST_CASE(template67); // #8122
|
||||
TEST_CASE(template68); // union
|
||||
TEST_CASE(template69); // #8791
|
||||
TEST_CASE(template70); // #5289
|
||||
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
|
||||
|
@ -122,6 +124,8 @@ private:
|
|||
TEST_CASE(template_namespace_3);
|
||||
TEST_CASE(template_namespace_4);
|
||||
TEST_CASE(template_namespace_5);
|
||||
TEST_CASE(template_namespace_6);
|
||||
TEST_CASE(template_namespace_7); // #8768
|
||||
|
||||
// Test TemplateSimplifier::templateParameters
|
||||
TEST_CASE(templateParameters);
|
||||
|
@ -648,7 +652,8 @@ private:
|
|||
"{};\n"
|
||||
"\n"
|
||||
"bitset<1> z;";
|
||||
const char expected[] = "bitset<1> z ; "
|
||||
const char expected[] = "class bitset<1> ; "
|
||||
"bitset<1> z ; "
|
||||
"class bitset<1> : B<4> { } ; "
|
||||
"struct B<4> { int a [ 4 ] ; } ;";
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
|
@ -666,15 +671,16 @@ private:
|
|||
"bitset<1> z;";
|
||||
|
||||
const char actual[] = "template < int n > struct B { int a [ n ] ; } ; "
|
||||
"class bitset<1> ; "
|
||||
"bitset<1> z ; "
|
||||
"class bitset<1> : B < 4 > { } ;";
|
||||
|
||||
const char expected[] = "bitset<1> z ; "
|
||||
const char expected[] = "class bitset<1> ; "
|
||||
"bitset<1> z ; "
|
||||
"class bitset<1> : B < 4 > { } ; "
|
||||
"struct B < 4 > { int a [ 4 ] ; } ;";
|
||||
|
||||
TODO_ASSERT_EQUALS(expected, actual, tok(code));
|
||||
|
||||
}
|
||||
|
||||
void template26() {
|
||||
|
@ -687,7 +693,7 @@ private:
|
|||
"\n"
|
||||
"C<2> a;\n";
|
||||
// TODO: expand A also
|
||||
ASSERT_EQUALS("template < class T > class A { public: T x ; } ; C<2> a ; class C<2> : public A < char [ 2 ] > { } ;", tok(code));
|
||||
ASSERT_EQUALS("template < class T > class A { public: T x ; } ; class C<2> ; C<2> a ; class C<2> : public A < char [ 2 ] > { } ;", tok(code));
|
||||
}
|
||||
|
||||
void template27() {
|
||||
|
@ -732,6 +738,7 @@ private:
|
|||
"\n"
|
||||
"B<int> b;\n";
|
||||
ASSERT_EQUALS("template < class T1 , class T2 , class T3 , class T4 > struct A { } ; "
|
||||
"struct B<int> ; "
|
||||
"B<int> b ; "
|
||||
"struct B<int> { public: A < int , Pair < int , int > , int > a ; } ;", tok(code));
|
||||
}
|
||||
|
@ -743,7 +750,9 @@ private:
|
|||
"template<class T> struct B { };\n"
|
||||
"template<class T> struct C { A<B<X<T> > > ab; };\n"
|
||||
"C<int> c;";
|
||||
ASSERT_EQUALS("C<int> c ; "
|
||||
ASSERT_EQUALS("struct B<X<int>> ; "
|
||||
"struct C<int> ; "
|
||||
"C<int> c ; "
|
||||
"struct C<int> { A<B<X<int>>> ab ; } ; "
|
||||
"struct B<X<int>> { } ; " // <- redundant.. but nevermind
|
||||
"struct A<B<X<int>>> { } ;", tok(code));
|
||||
|
@ -757,7 +766,9 @@ private:
|
|||
"C< B<A> > c;";
|
||||
ASSERT_EQUALS("struct A { } ; "
|
||||
"template < class T > struct B { } ; " // <- redundant.. but nevermind
|
||||
"C<B<A>> c ; struct C<B<A>> { } ;",
|
||||
"struct C<B<A>> ; "
|
||||
"C<B<A>> c ; "
|
||||
"struct C<B<A>> { } ;",
|
||||
tok(code));
|
||||
}
|
||||
}
|
||||
|
@ -768,10 +779,7 @@ private:
|
|||
"template <typename T> struct X { void f(X<T> &x) {} };\n"
|
||||
"}\n"
|
||||
"template <> int X<int>::Y(0);";
|
||||
ASSERT_EQUALS("namespace abc { "
|
||||
"template < typename T > struct X { void f ( X < T > & x ) { } } ; "
|
||||
"} "
|
||||
"template < > int X < int > :: Y ( 0 ) ;", tok(code));
|
||||
tok(code);
|
||||
}
|
||||
|
||||
void template35() { // #4074 - "A<'x'> a;" is not recognized as template instantiation
|
||||
|
@ -784,7 +792,8 @@ private:
|
|||
const char code[] = "template <class T> struct X { T t; };\n"
|
||||
"template <class C> struct Y { Foo < X< Bar<C> > > _foo; };\n" // <- Bar is unknown
|
||||
"Y<int> bar;";
|
||||
ASSERT_EQUALS("Y<int> bar ; "
|
||||
ASSERT_EQUALS("struct Y<int> ; "
|
||||
"Y<int> bar ; "
|
||||
"struct Y<int> { Foo < X<Bar<int>> > _foo ; } ; "
|
||||
"struct X<Bar<int>> { Bar < int > t ; } ;",
|
||||
tok(code));
|
||||
|
@ -796,7 +805,7 @@ private:
|
|||
"template<class T> class B {};\n"
|
||||
"B<class A> b1;\n"
|
||||
"B<A> b2;";
|
||||
ASSERT_EQUALS("class A { } ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
ASSERT_EQUALS("class A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
tok(code));
|
||||
}
|
||||
{
|
||||
|
@ -804,7 +813,7 @@ private:
|
|||
"template<class T> class B {};\n"
|
||||
"B<struct A> b1;\n"
|
||||
"B<A> b2;";
|
||||
ASSERT_EQUALS("struct A { } ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
ASSERT_EQUALS("struct A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
tok(code));
|
||||
}
|
||||
{
|
||||
|
@ -812,7 +821,7 @@ private:
|
|||
"template<class T> class B {};\n"
|
||||
"B<enum A> b1;\n"
|
||||
"B<A> b2;";
|
||||
ASSERT_EQUALS("enum A { } ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
ASSERT_EQUALS("enum A { } ; class B<A> ; B<A> b1 ; B<A> b2 ; class B<A> { } ;",
|
||||
tok(code));
|
||||
}
|
||||
}
|
||||
|
@ -1128,7 +1137,8 @@ private:
|
|||
" Foo<Bar<T>> f2() { }\n"
|
||||
"};\n"
|
||||
"Bar<int> c;";
|
||||
const char exp[] = "Bar<int> c ; "
|
||||
const char exp[] = "struct Bar<int> ; "
|
||||
"Bar<int> c ; "
|
||||
"struct Bar<int> {"
|
||||
" void f1 ( Bar<int> x ) { }"
|
||||
" Foo<Bar<int>> f2 ( ) { } "
|
||||
|
@ -1144,6 +1154,7 @@ private:
|
|||
"template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; }\n"
|
||||
"C3<int,6> c3;";
|
||||
const char exp[] = "template < class T > void f ( ) { x = y ? ( C1 < int > :: allocate ( 1 ) ) : 0 ; } "
|
||||
"class C3<int,6> ; "
|
||||
"C3<int,6> c3 ; "
|
||||
"class C3<int,6> { } ; "
|
||||
"C3<int,6> :: C3<int,6> ( const C3<int,6> & v ) { C1<int*> c1 ; } "
|
||||
|
@ -1252,12 +1263,45 @@ private:
|
|||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template69() { // #8791
|
||||
const char code[] = "class Test {\n"
|
||||
" int test;\n"
|
||||
" template <class T> T lookup() { return test; }\n"
|
||||
" int Fun() { return lookup<int>(); }\n"
|
||||
"};";
|
||||
const char exp [] = "class Test { "
|
||||
"int test ; "
|
||||
"int Fun ( ) { return lookup<int> ( ) ; } "
|
||||
"} ; "
|
||||
"int Test :: lookup<int> ( ) { return test ; }";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template70() { // #5289
|
||||
const char code[] = "template<typename T, typename V, int KeySize = 0> class Bar;\n"
|
||||
"template<>\n"
|
||||
"class Bar<void, void> {\n"
|
||||
"};\n"
|
||||
"template<typename K, typename V, int KeySize>\n"
|
||||
"class Bar : private Bar<void, void> {\n"
|
||||
" void foo() { }\n"
|
||||
"};";
|
||||
const char exp [] = "template < typename T , typename V , int KeySize = 0 > class Bar ; "
|
||||
"class Bar<void,void> { "
|
||||
"} ; "
|
||||
"template < typename K , typename V , int KeySize = 0 > "
|
||||
"class Bar : private Bar<void,void> { "
|
||||
"void foo ( ) { } "
|
||||
"} ;";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
|
||||
const char code[] = "template <typename T> struct C {};\n"
|
||||
"template <typename T> struct S {a};\n"
|
||||
"template <typename T> struct S<C<T>> {b};\n"
|
||||
"S<int> s;";
|
||||
const char exp[] = "template < typename T > struct C { } ; template < typename T > struct S < C < T > > { b } ; S<int> s ; struct S<int> { a } ;";
|
||||
const char exp[] = "template < typename T > struct C { } ; struct S<int> ; template < typename T > struct S < C < T > > { b } ; S<int> s ; struct S<int> { a } ;";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
|
@ -1266,7 +1310,7 @@ private:
|
|||
"template <typename T> struct S {a};\n"
|
||||
"template <typename T> struct S<C<T>> {b};\n"
|
||||
"S<C<int>> s;";
|
||||
const char exp[] = "template < typename T > struct C { } ; template < typename T > struct S { a } ; S<C<int>> s ; struct S<C<int>> { b } ;";
|
||||
const char exp[] = "template < typename T > struct C { } ; template < typename T > struct S { a } ; struct S<C<int>> ; S<C<int>> s ; struct S<C<int>> { b } ;";
|
||||
ASSERT_EQUALS(exp, tok(code));
|
||||
}
|
||||
|
||||
|
@ -1407,6 +1451,7 @@ private:
|
|||
"thv_table_c<void * , void * , DefaultMemory < void * , void *>> id_table_m ; "
|
||||
"class thv_table_c<void * , void * , DefaultMemory < void * , void * >> { } ;";
|
||||
const char curr[] = "template < class T , class U > class DefaultMemory { } ; "
|
||||
"class thv_table_c<void*,void*,DefaultMemory<Key,Val>> ; "
|
||||
"thv_table_c<void*,void*,DefaultMemory<Key,Val>> id_table_m ; "
|
||||
"class thv_table_c<void*,void*,DefaultMemory<Key,Val>> { } ;";
|
||||
TODO_ASSERT_EQUALS(exp, curr, tok(code));
|
||||
|
@ -1426,7 +1471,9 @@ private:
|
|||
" A<int> a2;\n"
|
||||
"}\n";
|
||||
|
||||
const char wanted[] = "void f ( ) "
|
||||
const char wanted[] = "class A<int,2> ; "
|
||||
"class A<int,3> ; "
|
||||
"void f ( ) "
|
||||
"{"
|
||||
" A<int,2> a1 ;"
|
||||
" A<int,3> a2 ; "
|
||||
|
@ -1436,6 +1483,8 @@ private:
|
|||
"class A<int,3> "
|
||||
"{ int ar [ 3 ] ; } ;";
|
||||
const char current[] = "template < class T , int n = 3 > class A ; "
|
||||
"class A<int,2> ; "
|
||||
"class A<int,3> ; "
|
||||
"void f ( ) "
|
||||
"{"
|
||||
" A<int,2> a1 ;"
|
||||
|
@ -1459,7 +1508,9 @@ private:
|
|||
" A<int> a2;\n"
|
||||
"}\n";
|
||||
|
||||
const char wanted[] = "void f ( ) "
|
||||
const char wanted[] = "class A<int,2> ; "
|
||||
"class A<int,3> ; "
|
||||
"void f ( ) "
|
||||
"{"
|
||||
" A<int,2> a1 ;"
|
||||
" A<int,3> a2 ; "
|
||||
|
@ -1469,6 +1520,8 @@ private:
|
|||
"class A<int,3> "
|
||||
"{ int ar [ 3 ] ; } ;";
|
||||
const char current[] = "template < class , int = 3 > class A ; "
|
||||
"class A<int,2> ; "
|
||||
"class A<int,3> ; "
|
||||
"void f ( ) "
|
||||
"{"
|
||||
" A<int,2> a1 ;"
|
||||
|
@ -1638,8 +1691,11 @@ private:
|
|||
" template<class T> struct S { };\n"
|
||||
"}\n"
|
||||
"X::S<int> s;";
|
||||
ASSERT_EQUALS("X::S<int> s ; "
|
||||
"struct X::S<int> { } ;", tok(code));
|
||||
ASSERT_EQUALS("namespace X { "
|
||||
"struct S<int> ; "
|
||||
"} "
|
||||
"X :: S<int> s ; "
|
||||
"struct X :: S<int> { } ;", tok(code));
|
||||
}
|
||||
|
||||
void template_namespace_3() {
|
||||
|
@ -1650,11 +1706,12 @@ private:
|
|||
" void *test() { return foo<int>::bar(); }\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("namespace test16 {"
|
||||
" struct foo<int> ;"
|
||||
" void * test ( ) {"
|
||||
" return test16::foo<int> :: bar ( ) ;"
|
||||
" return foo<int> :: bar ( ) ;"
|
||||
" } "
|
||||
"} "
|
||||
"struct test16::foo<int> {"
|
||||
"struct test16 :: foo<int> {"
|
||||
" static void * bar ( ) ; "
|
||||
"} ;", tok(code));
|
||||
}
|
||||
|
@ -1669,13 +1726,14 @@ private:
|
|||
" };\n"
|
||||
"}";
|
||||
ASSERT_EQUALS("namespace foo {"
|
||||
" struct S : public foo::A<int> {"
|
||||
" class A<int> ;"
|
||||
" struct S : public A<int> {"
|
||||
" void f ( ) {"
|
||||
" foo::A<int> :: dostuff ( ) ;"
|
||||
" A<int> :: dostuff ( ) ;"
|
||||
" }"
|
||||
" } ; "
|
||||
"} "
|
||||
"class foo::A<int> { void dostuff ( ) { } } ;", tok(code));
|
||||
"class foo :: A<int> { void dostuff ( ) { } } ;", tok(code));
|
||||
}
|
||||
|
||||
void template_namespace_5() {
|
||||
|
@ -1684,6 +1742,66 @@ private:
|
|||
ASSERT_EQUALS("namespace X { S<int> s ; } struct S<int> { } ;", tok(code));
|
||||
}
|
||||
|
||||
void template_namespace_6() {
|
||||
const char code[] = "namespace NS {\n"
|
||||
"template <typename T> union C {\n"
|
||||
" char dummy[sizeof(T)];\n"
|
||||
" T value;\n"
|
||||
" C();\n"
|
||||
" ~C();\n"
|
||||
" C(const C &);\n"
|
||||
" C & operator = (const C &);\n"
|
||||
"};\n"
|
||||
"}\n"
|
||||
"NS::C<int> intC;\n"
|
||||
"template <typename T> NS::C<T>::C() {}\n"
|
||||
"template <typename T> NS::C<T>::~C() {}\n"
|
||||
"template <typename T> NS::C<T>::C(const NS::C<T> &) {}\n"
|
||||
"template <typename T> NS::C<T> & NS::C<T>::operator=(const NS::C<T> &) {}";
|
||||
ASSERT_EQUALS("namespace NS { "
|
||||
"union C<int> ; "
|
||||
"} "
|
||||
"NS :: C<int> intC ; union NS :: C<int> { "
|
||||
"char dummy [ 4 ] ; "
|
||||
"int value ; "
|
||||
"C<int> ( ) ; "
|
||||
"~ C<int> ( ) ; "
|
||||
"C<int> ( const NS :: C<int> & ) ; "
|
||||
"NS :: C<int> & operator= ( const NS :: C<int> & ) ; "
|
||||
"} ; "
|
||||
"NS :: C<int> :: C<int> ( ) { } "
|
||||
"NS :: C<int> :: ~ C<int> ( ) { } "
|
||||
"NS :: C<int> :: C<int> ( const NS :: C<int> & ) { } "
|
||||
"NS :: C<int> & NS :: C<int> :: operator= ( const NS :: C<int> & ) { }", tok(code));
|
||||
}
|
||||
|
||||
void template_namespace_7() { // #8768
|
||||
const char code[] = "namespace N1 {\n"
|
||||
"namespace N2 {\n"
|
||||
" struct C { };\n"
|
||||
" template <class T> struct CT { };\n"
|
||||
" C c1;\n"
|
||||
" CT<int> ct1;\n"
|
||||
"}\n"
|
||||
"N2::C c2;\n"
|
||||
"N2::CT<int> ct2;\n"
|
||||
"}\n"
|
||||
"N1::N2::C c3;\n"
|
||||
"N1::N2::CT<int> ct3;";
|
||||
ASSERT_EQUALS("namespace N1 { "
|
||||
"namespace N2 { "
|
||||
"struct C { } ; "
|
||||
"struct CT<int> ; "
|
||||
"C c1 ; "
|
||||
"CT<int> ct1 ; "
|
||||
"} "
|
||||
"N2 :: C c2 ; "
|
||||
"N2 :: CT<int> ct2 ; "
|
||||
"} "
|
||||
"N1 :: N2 :: C c3 ; "
|
||||
"N1 :: N2 :: CT<int> ct3 ; struct N1 :: N2 :: CT<int> { } ;", tok(code));
|
||||
}
|
||||
|
||||
unsigned int templateParameters(const char code[]) {
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
|
||||
|
@ -1956,7 +2074,10 @@ private:
|
|||
"template<class T> using Bar = A::Foo<T,3>;\n"
|
||||
"Bar<int> b;\n";
|
||||
|
||||
const char expected[] = "; A::Foo<int,3> b ; struct A::Foo<int,3> { } ;";
|
||||
const char expected[] = "namespace A { struct Foo<int,3> ; } "
|
||||
"; "
|
||||
"A :: Foo<int,3> b ; "
|
||||
"struct A :: Foo<int,3> { } ;";
|
||||
|
||||
ASSERT_EQUALS(expected, tok(code));
|
||||
}
|
||||
|
|
|
@ -4408,8 +4408,8 @@ private:
|
|||
" void foo() {\n"
|
||||
" }\n"
|
||||
"};");
|
||||
ASSERT(db && db->findScopeByName("Bar") && !db->findScopeByName("Bar")->functionList.front().isImplicitlyVirtual(false));
|
||||
if (db)
|
||||
ASSERT(db && db->findScopeByName("Bar") && !db->findScopeByName("Bar")->functionList.empty() && !db->findScopeByName("Bar")->functionList.front().isImplicitlyVirtual(false));
|
||||
if (db && db->findScopeByName("Bar"))
|
||||
ASSERT_EQUALS(1, db->findScopeByName("Bar")->functionList.size());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue