I'm currently working on a MS compatibility bug that I am pretty stuck with, that I was hoping someone could give me a hand on how to figure out. This is currently blocking MySQL from building in MS compatibility mode. First, the reproducer:
template<class T> struct Struct{
typedef int TypeDef;
};
template<class TMP> void foo() {
Struct<TMP>::TypeDef varname;
}
void foo2()
{
foo<int>();
}
The result is:
typename_test.cpp:8:9: error: expected ';' after expression
Struct<TMP>::TypeDef varname;
This is due to Parser::ParseStatementOrDeclarationAfterAttributes (ParseStmt.cpp:152) deciding that it is an expression. I've dug into this, and I see it go into the case tok::identifier's branch "Next.isNot(tok::coloncolon)". Inside that, TryAnnotateName annotates the Tok token as "annot_primary_expr".
I would expect it to be annot_typename or something similar, such that the call to isCXXDeclarationSpecifier (via isDeclarationStatement()) succeeds.
So I guess my question is: Am I better off trying to comprehend this functionality in TryAnnotateName, or just alter isCXXDeclarationSpecifier to give a different answer? Is there a better option that I'm missing?
Also, can anyone give me a tip on how to begin with either? I'm in a little bit of a foreign land attempting to mess with parsing this much.
Thanks,
Erich
I'm currently working on a MS compatibility bug that I am pretty stuck with, that I was hoping someone could give me a hand on how to figure out. This is currently blocking MySQL from building in MS compatibility mode. First, the reproducer:
template<class T> struct Struct{
typedef int TypeDef;
};
template<class TMP> void foo() {
Struct<TMP>::TypeDef varname;
}
void foo2()
{
foo<int>();
}
The result is:
typename_test.cpp:8:9: error: expected ';' after expression
Struct<TMP>::TypeDef varname;
This is due to Parser::ParseStatementOrDeclarationAfterAttributes (ParseStmt.cpp:152) deciding that it is an expression. I've dug into this, and I see it go into the case tok::identifier's branch "Next.isNot(tok::coloncolon)". Inside that, TryAnnotateName annotates the Tok token as "annot_primary_expr".
I would expect it to be annot_typename or something similar, such that the call to isCXXDeclarationSpecifier (via isDeclarationStatement()) succeeds.
If you assume the code is well-formed, and see just the tokens "Struct<TMP>::TypeDef", it's pretty clearly not a typename according to normal C++ parsing rules. Of course, your testcase isn't well-formed, so you want to look ahead, figure out that "Struct<TMP>::TypeDef varname" can't be an expression, then print a diagnostic and force "Struct<TMP>::TypeDef" to parse as a type.
So I guess my question is: Am I better off trying to comprehend this functionality in TryAnnotateName, or just alter isCXXDeclarationSpecifier to give a different answer? Is there a better option that I'm missing?
If you change "Next.isNot(tok::coloncolon)" to "Next.isNot(tok::coloncolon) && Next.isNot(tok::less)", it throws you onto the right codepath for your testcase. I'm not sure that's precisely what you want, but maybe a start.
-Eli
Ah, wow, thank you very much!
My code example compiles in MSVC due to the messed up 'typename' rules, so I am trying to more appropriately match that functionality.
I was running down "TryAnnotateName" for a while, and discovered that if "ClassifyName" returns NC_TypeTemplate, everything works too. However, it seems like I can get the same result with your suggested change!
I'll continue working on this to get it to be a MSVC option only and do my best to validate the use case.
Thanks again!
-Erich