Commit eee94667 authored by Christian Kamm's avatar Christian Kamm

C++11: Fix parsing of trailing-type-specifier.

In particular "auto foo() -> typename Foo<T>::X;" didn't parse.

Change-Id: I7665c9b387e222e4107f053a529d502813ebf617
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent 4ea8499f
......@@ -1314,31 +1314,47 @@ bool Parser::parseTemplateArgument(ExpressionAST *&node)
return parsed;
}
/** Parses a sequence of
*
* storage-class-specifier (unless noStorageSpecifier is true)
* trailing-type-specifier, which contains
* cv-qualifier
* simple-type-specifier
* typename-specifier
* elaborated-type-specifier
*
* If onlySimpleTypeSpecifiers is true, it only eats simple-type-specifiers
* and cv-qualifiers.
*/
bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
bool onlyTypeSpecifiers,
bool simplified)
bool noStorageSpecifiers,
bool onlySimpleTypeSpecifiers)
{
DEBUG_THIS_RULE();
bool has_type_specifier = false;
NameAST *named_type_specifier = 0;
SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
for (;;) {
if (lookAtCVQualifier()) {
if (! noStorageSpecifiers && ! onlySimpleTypeSpecifiers && lookAtStorageClassSpecifier()) {
// storage-class-specifier
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
spec->specifier_token = consumeToken();
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
} else if (! onlyTypeSpecifiers && lookAtStorageClassSpecifier()) {
} else if (lookAtCVQualifier()) {
// cv-qualifier
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
spec->specifier_token = consumeToken();
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
} else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) {
// parts of simple-type-specifier
parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
has_type_specifier = true;
} else if (! has_type_specifier && (LA() == T_COLON_COLON ||
LA() == T_IDENTIFIER)) {
// parts of simple-type-specifier
if (! parseName(named_type_specifier))
return false;
NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
......@@ -1346,9 +1362,9 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
has_type_specifier = true;
} else if (! simplified && ! has_type_specifier && (LA() == T_TYPENAME ||
LA() == T_ENUM ||
lookAtClassKey())) {
} else if (! onlySimpleTypeSpecifiers && ! has_type_specifier &&
(LA() == T_TYPENAME || LA() == T_ENUM || lookAtClassKey())) {
// typename-specifier, elaborated-type-specifier
unsigned startOfElaboratedTypeSpecifier = cursor();
if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
error(startOfElaboratedTypeSpecifier,
......@@ -6472,12 +6488,6 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node)
return true;
}
bool Parser::parseTrailingTypeSpecifierSeq(SpecifierListAST *&node)
{
DEBUG_THIS_RULE();
return parseSimpleTypeSpecifier(node);
}
void Parser::rewind(unsigned cursor)
{
#ifndef CPLUSPLUS_NO_DEBUG_RULE
......
......@@ -167,15 +167,18 @@ public:
bool parseAttributeSpecifier(SpecifierListAST *&node);
bool parseAttributeList(AttributeListAST *&node);
bool parseSimpleTypeSpecifier(SpecifierListAST *&node)
{ return parseDeclSpecifierSeq(node, true, true); }
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
bool noStorageSpecifiers = false,
bool onlySimpleTypeSpecifiers = false);
bool parseTypeSpecifier(SpecifierListAST *&node)
bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node)
{ return parseDeclSpecifierSeq(node, true); }
/// This actually parses a trailing-type-specifier sequence
bool parseTypeSpecifier(SpecifierListAST *&node)
{ return parseTrailingTypeSpecifierSeq(node); }
bool parseSimpleTypeSpecifier(SpecifierListAST *&node)
{ return parseDeclSpecifierSeq(node, true, true); }
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
bool onlyTypeSpecifiers = false,
bool simplified = false);
bool parseUnaryExpression(ExpressionAST *&node);
bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true);
bool parseUsing(DeclarationAST *&node);
......@@ -202,7 +205,6 @@ public:
bool parseCapture(CaptureAST *&node);
bool parseCaptureList(CaptureListAST *&node);
bool parseTrailingReturnType(TrailingReturnTypeAST *&node);
bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node);
// ObjC++
bool parseObjCExpression(ExpressionAST *&node);
......
auto foo()
-> const typename XYZ::abc<T>::def;
auto foo()
-> class XYZ::def;
......@@ -152,6 +152,7 @@ void tst_cxx11::parse_data()
QTest::newRow("packExpansion.1") << "packExpansion.1.cpp" << "";
QTest::newRow("declType.1") << "declType.1.cpp" << "";
QTest::newRow("threadLocal.1") << "threadLocal.1.cpp" << "";
QTest::newRow("trailingtypespec.1") << "trailingtypespec.1.cpp" << "";
}
void tst_cxx11::parse()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment