forked from qt-creator/qt-creator
C++11: Fix parsing of trailing-type-specifier.
In particular "auto foo() -> typename Foo<T>::X;" didn't parse. Change-Id: I7665c9b387e222e4107f053a529d502813ebf617 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
36
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
36
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -1314,31 +1314,47 @@ bool Parser::parseTemplateArgument(ExpressionAST *&node)
|
|||||||
return parsed;
|
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 Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
|
||||||
bool onlyTypeSpecifiers,
|
bool noStorageSpecifiers,
|
||||||
bool simplified)
|
bool onlySimpleTypeSpecifiers)
|
||||||
{
|
{
|
||||||
DEBUG_THIS_RULE();
|
DEBUG_THIS_RULE();
|
||||||
bool has_type_specifier = false;
|
bool has_type_specifier = false;
|
||||||
NameAST *named_type_specifier = 0;
|
NameAST *named_type_specifier = 0;
|
||||||
SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
|
SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (lookAtCVQualifier()) {
|
if (! noStorageSpecifiers && ! onlySimpleTypeSpecifiers && lookAtStorageClassSpecifier()) {
|
||||||
|
// storage-class-specifier
|
||||||
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
|
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
|
||||||
spec->specifier_token = consumeToken();
|
spec->specifier_token = consumeToken();
|
||||||
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
|
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
|
||||||
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
||||||
} else if (! onlyTypeSpecifiers && lookAtStorageClassSpecifier()) {
|
} else if (lookAtCVQualifier()) {
|
||||||
|
// cv-qualifier
|
||||||
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
|
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
|
||||||
spec->specifier_token = consumeToken();
|
spec->specifier_token = consumeToken();
|
||||||
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
|
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(spec);
|
||||||
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
||||||
} else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) {
|
} else if (! named_type_specifier && lookAtBuiltinTypeSpecifier()) {
|
||||||
|
// parts of simple-type-specifier
|
||||||
parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
|
parseBuiltinTypeSpecifier(*decl_specifier_seq_ptr);
|
||||||
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
||||||
has_type_specifier = true;
|
has_type_specifier = true;
|
||||||
} else if (! has_type_specifier && (LA() == T_COLON_COLON ||
|
} else if (! has_type_specifier && (LA() == T_COLON_COLON ||
|
||||||
LA() == T_IDENTIFIER)) {
|
LA() == T_IDENTIFIER)) {
|
||||||
|
// parts of simple-type-specifier
|
||||||
if (! parseName(named_type_specifier))
|
if (! parseName(named_type_specifier))
|
||||||
return false;
|
return false;
|
||||||
NamedTypeSpecifierAST *spec = new (_pool) NamedTypeSpecifierAST;
|
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 = new (_pool) SpecifierListAST(spec);
|
||||||
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
||||||
has_type_specifier = true;
|
has_type_specifier = true;
|
||||||
} else if (! simplified && ! has_type_specifier && (LA() == T_TYPENAME ||
|
} else if (! onlySimpleTypeSpecifiers && ! has_type_specifier &&
|
||||||
LA() == T_ENUM ||
|
(LA() == T_TYPENAME || LA() == T_ENUM || lookAtClassKey())) {
|
||||||
lookAtClassKey())) {
|
// typename-specifier, elaborated-type-specifier
|
||||||
unsigned startOfElaboratedTypeSpecifier = cursor();
|
unsigned startOfElaboratedTypeSpecifier = cursor();
|
||||||
if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
|
if (! parseElaboratedTypeSpecifier(*decl_specifier_seq_ptr)) {
|
||||||
error(startOfElaboratedTypeSpecifier,
|
error(startOfElaboratedTypeSpecifier,
|
||||||
@@ -6472,12 +6488,6 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::parseTrailingTypeSpecifierSeq(SpecifierListAST *&node)
|
|
||||||
{
|
|
||||||
DEBUG_THIS_RULE();
|
|
||||||
return parseSimpleTypeSpecifier(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::rewind(unsigned cursor)
|
void Parser::rewind(unsigned cursor)
|
||||||
{
|
{
|
||||||
#ifndef CPLUSPLUS_NO_DEBUG_RULE
|
#ifndef CPLUSPLUS_NO_DEBUG_RULE
|
||||||
|
|||||||
16
src/libs/3rdparty/cplusplus/Parser.h
vendored
16
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -167,15 +167,18 @@ public:
|
|||||||
bool parseAttributeSpecifier(SpecifierListAST *&node);
|
bool parseAttributeSpecifier(SpecifierListAST *&node);
|
||||||
bool parseAttributeList(AttributeListAST *&node);
|
bool parseAttributeList(AttributeListAST *&node);
|
||||||
|
|
||||||
|
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
|
||||||
|
bool noStorageSpecifiers = false,
|
||||||
|
bool onlySimpleTypeSpecifiers = false);
|
||||||
|
|
||||||
|
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)
|
bool parseSimpleTypeSpecifier(SpecifierListAST *&node)
|
||||||
{ return parseDeclSpecifierSeq(node, true, true); }
|
{ return parseDeclSpecifierSeq(node, true, true); }
|
||||||
|
|
||||||
bool parseTypeSpecifier(SpecifierListAST *&node)
|
|
||||||
{ return parseDeclSpecifierSeq(node, true); }
|
|
||||||
|
|
||||||
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
|
|
||||||
bool onlyTypeSpecifiers = false,
|
|
||||||
bool simplified = false);
|
|
||||||
bool parseUnaryExpression(ExpressionAST *&node);
|
bool parseUnaryExpression(ExpressionAST *&node);
|
||||||
bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true);
|
bool parseUnqualifiedName(NameAST *&node, bool acceptTemplateId = true);
|
||||||
bool parseUsing(DeclarationAST *&node);
|
bool parseUsing(DeclarationAST *&node);
|
||||||
@@ -202,7 +205,6 @@ public:
|
|||||||
bool parseCapture(CaptureAST *&node);
|
bool parseCapture(CaptureAST *&node);
|
||||||
bool parseCaptureList(CaptureListAST *&node);
|
bool parseCaptureList(CaptureListAST *&node);
|
||||||
bool parseTrailingReturnType(TrailingReturnTypeAST *&node);
|
bool parseTrailingReturnType(TrailingReturnTypeAST *&node);
|
||||||
bool parseTrailingTypeSpecifierSeq(SpecifierListAST *&node);
|
|
||||||
|
|
||||||
// ObjC++
|
// ObjC++
|
||||||
bool parseObjCExpression(ExpressionAST *&node);
|
bool parseObjCExpression(ExpressionAST *&node);
|
||||||
|
|||||||
5
tests/auto/cplusplus/cxx11/data/trailingtypespec.1.cpp
Normal file
5
tests/auto/cplusplus/cxx11/data/trailingtypespec.1.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
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("packExpansion.1") << "packExpansion.1.cpp" << "";
|
||||||
QTest::newRow("declType.1") << "declType.1.cpp" << "";
|
QTest::newRow("declType.1") << "declType.1.cpp" << "";
|
||||||
QTest::newRow("threadLocal.1") << "threadLocal.1.cpp" << "";
|
QTest::newRow("threadLocal.1") << "threadLocal.1.cpp" << "";
|
||||||
|
QTest::newRow("trailingtypespec.1") << "trailingtypespec.1.cpp" << "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_cxx11::parse()
|
void tst_cxx11::parse()
|
||||||
|
|||||||
Reference in New Issue
Block a user