Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
fe2c9cc1
Commit
fe2c9cc1
authored
Oct 19, 2009
by
Roberto Raggi
Browse files
Improved parsing of ambiguous statements.
Done with Erik Verbruggen
parent
aa893177
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/shared/cplusplus/Parser.cpp
View file @
fe2c9cc1
...
...
@@ -56,7 +56,7 @@
#include
<cstdlib>
#include
<cstring>
#include
<cassert>
#include
<QDebug>
CPLUSPLUS_BEGIN_NAMESPACE
Parser
::
Parser
(
TranslationUnit
*
unit
)
...
...
@@ -2041,10 +2041,68 @@ bool Parser::maybeSimpleExpression(SimpleDeclarationAST *simpleDecl) const
{
if
(
!
simpleDecl
->
declarators
)
{
SpecifierAST
*
spec
=
simpleDecl
->
decl_specifier_seq
;
if
(
spec
&&
!
spec
->
next
&&
spec
->
asNamedTypeSpecifier
())
{
if
(
spec
&&
!
spec
->
next
&&
spec
->
asNamedTypeSpecifier
())
return
true
;
}
return
false
;
}
bool
Parser
::
isPointerDeclaration
(
DeclarationStatementAST
*
ast
)
const
{
if
(
!
ast
)
return
false
;
if
(
SimpleDeclarationAST
*
declaration
=
ast
->
declaration
->
asSimpleDeclaration
())
{
if
(
SpecifierAST
*
spec
=
declaration
->
decl_specifier_seq
)
{
if
(
spec
->
asNamedTypeSpecifier
()
&&
!
spec
->
next
)
{
if
(
DeclaratorListAST
*
declarators
=
declaration
->
declarators
)
{
if
(
DeclaratorAST
*
declarator
=
declarators
->
declarator
)
{
if
(
declarator
->
ptr_operators
&&
declarator
->
equals_token
&&
declarator
->
initializer
)
{
return
true
;
}
}
}
}
}
}
return
false
;
}
bool
Parser
::
maybeAmbiguousStatement
(
DeclarationStatementAST
*
ast
)
const
{
if
(
!
ast
)
return
false
;
if
(
SimpleDeclarationAST
*
declaration
=
ast
->
declaration
->
asSimpleDeclaration
())
{
if
(
SpecifierAST
*
spec
=
declaration
->
decl_specifier_seq
)
{
if
(
spec
->
asNamedTypeSpecifier
()
&&
!
spec
->
next
)
{
if
(
DeclaratorListAST
*
declarators
=
declaration
->
declarators
)
{
if
(
DeclaratorAST
*
declarator
=
declarators
->
declarator
)
{
if
(
declarator
->
core_declarator
&&
declarator
->
core_declarator
->
asNestedDeclarator
())
{
// recognized name(id-expression)
return
true
;
}
}
}
}
}
else
if
(
DeclaratorListAST
*
declarators
=
declaration
->
declarators
)
{
// no decl_specifiers...
if
(
DeclaratorAST
*
declarator
=
declarators
->
declarator
)
{
if
(
declarator
->
postfix_declarators
&&
declarator
->
postfix_declarators
->
asFunctionDeclarator
()
&&
!
declarator
->
initializer
)
{
return
false
;
}
}
return
true
;
}
}
return
false
;
}
...
...
@@ -2055,31 +2113,35 @@ bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
unsigned
start
=
cursor
();
bool
blocked
=
blockErrors
(
true
);
if
(
parseDeclarationStatement
(
node
))
{
DeclarationStatementAST
*
stmt
=
static_cast
<
DeclarationStatementAST
*>
(
node
);
SimpleDeclarationAST
*
simpleDecl
=
0
;
if
(
stmt
->
declaration
)
simpleDecl
=
stmt
->
declaration
->
asSimpleDeclaration
();
if
(
simpleDecl
&&
simpleDecl
->
decl_specifier_seq
&&
!
maybeFunctionCall
(
simpleDecl
)
&&
!
maybeSimpleExpression
(
simpleDecl
))
{
if
(
isPointerDeclaration
(
stmt
))
{
blockErrors
(
blocked
);
return
true
;
}
if
(
!
maybeAmbiguousStatement
(
stmt
))
{
unsigned
end_of_declaration_statement
=
cursor
();
rewind
(
start
);
StatementAST
*
expression
=
0
;
if
(
!
parseExpressionStatement
(
expression
)
||
cursor
()
!=
end_of_declaration_statement
)
{
rewind
(
end_of_declaration_statement
);
}
else
{
ExpressionOrDeclarationStatementAST
*
ast
=
new
(
_pool
)
ExpressionOrDeclarationStatementAST
;
if
(
parseExpressionStatement
(
expression
)
&&
cursor
()
==
end_of_declaration_statement
)
{
// it's an ambiguous expression-or-declaration statement.
ExpressionOrDeclarationStatementAST
*
ast
=
new
(
_pool
)
ExpressionOrDeclarationStatementAST
;
ast
->
declaration
=
node
;
ast
->
expression
=
expression
;
node
=
ast
;
}
rewind
(
end_of_declaration_statement
);
blockErrors
(
blocked
);
return
true
;
}
}
// it's not a declaration statement.
blockErrors
(
blocked
);
rewind
(
start
);
return
parseExpressionStatement
(
node
);
...
...
@@ -2653,6 +2715,12 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
return
false
;
}
// if there is no valid declarator
// and it doesn't look like a fwd or a class declaration
// then it's not a declarations
if
(
!
declarator
&&
!
maybeForwardOrClassDeclaration
(
decl_specifier_seq
))
return
false
;
DeclaratorAST
*
firstDeclarator
=
declarator
;
if
(
declarator
)
{
...
...
@@ -2709,6 +2777,19 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node,
return
false
;
}
bool
Parser
::
maybeForwardOrClassDeclaration
(
SpecifierAST
*
decl_specifier_seq
)
const
{
// look at the decl_specifier for possible fwd or class declarations.
if
(
SpecifierAST
*
spec
=
decl_specifier_seq
)
{
if
(
!
spec
->
next
&&
(
spec
->
asElaboratedTypeSpecifier
()
||
spec
->
asEnumSpecifier
()
||
spec
->
asClassSpecifier
()))
return
true
;
}
return
false
;
}
bool
Parser
::
parseFunctionBody
(
StatementAST
*&
node
)
{
if
(
_translationUnit
->
skipFunctionBody
())
{
...
...
src/shared/cplusplus/Parser.h
View file @
fe2c9cc1
...
...
@@ -264,8 +264,11 @@ public:
void
match
(
int
kind
,
unsigned
*
token
);
bool
maybeAmbiguousStatement
(
DeclarationStatementAST
*
ast
)
const
;
bool
maybeFunctionCall
(
SimpleDeclarationAST
*
simpleDecl
)
const
;
bool
maybeSimpleExpression
(
SimpleDeclarationAST
*
simpleDecl
)
const
;
bool
maybeForwardOrClassDeclaration
(
SpecifierAST
*
decl_specifier_seq
)
const
;
bool
isPointerDeclaration
(
DeclarationStatementAST
*
ast
)
const
;
private:
bool
switchTemplateArguments
(
bool
templateArguments
);
...
...
tests/auto/cplusplus/ast/tst_ast.cpp
View file @
fe2c9cc1
...
...
@@ -58,6 +58,12 @@ private slots:
void
while_condition_statement
();
void
for_statement
();
void
cpp_initializer_or_function_declaration
();
void
simple_declaration_1
();
void
function_call_1
();
void
function_call_2
();
void
function_call_3
();
void
nested_deref_expression
();
void
assignment_1
();
// objc++
void
objc_attributes_followed_by_at_keyword
();
...
...
@@ -78,6 +84,19 @@ void tst_AST::gcc_attributes_1()
));
}
void
tst_AST
::
simple_declaration_1
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"
\n
"
"a * b = 10;"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
);
DeclarationStatementAST
*
declStmt
=
ast
->
asDeclarationStatement
();
QVERIFY
(
declStmt
);
}
void
tst_AST
::
simple_name
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseExpression
(
"a"
));
...
...
@@ -161,7 +180,7 @@ void tst_AST::new_expression_2()
void
tst_AST
::
condition_1
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseExpression
(
"
\n
"
"(x < 0 && y > (int) a"
"(x < 0 && y > (int) a
)
"
));
AST
*
ast
=
unit
->
ast
();
...
...
@@ -178,6 +197,46 @@ void tst_AST::init_1()
QVERIFY
(
ast
!=
0
);
}
void
tst_AST
::
function_call_1
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"retranslateUi(blah);"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
QVERIFY
(
ast
->
asExpressionStatement
());
}
void
tst_AST
::
function_call_2
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"retranslateUi(10);"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
QVERIFY
(
ast
->
asExpressionStatement
());
}
void
tst_AST
::
function_call_3
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"(*blah) = 10;"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
QVERIFY
(
ast
->
asExpressionStatement
());
}
void
tst_AST
::
nested_deref_expression
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"(*blah);"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
QVERIFY
(
ast
->
asExpressionStatement
());
}
void
tst_AST
::
assignment_1
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"a(x) = 3;"
));
AST
*
ast
=
unit
->
ast
();
QVERIFY
(
ast
!=
0
);
QVERIFY
(
ast
->
asExpressionStatement
());
}
void
tst_AST
::
if_statement
()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseStatement
(
"if (a) b;"
));
...
...
@@ -195,7 +254,7 @@ void tst_AST::if_statement()
QCOMPARE
(
stmt
->
else_token
,
0U
);
QVERIFY
(
stmt
->
else_statement
==
0
);
// check the `then' statement
// check the `then' statement
1
ExpressionStatementAST
*
then_stmt
=
stmt
->
statement
->
asExpressionStatement
();
QVERIFY
(
then_stmt
!=
0
);
QVERIFY
(
then_stmt
->
expression
!=
0
);
...
...
@@ -435,7 +494,7 @@ void tst_AST::normal_array_access()
{
QSharedPointer
<
TranslationUnit
>
unit
(
parseDeclaration
(
"
\n
"
"int f() {
\n
"
" int a[1
5
];
\n
"
" int a[1
0
];
\n
"
" int b = 1;
\n
"
" return a[b];
\n
"
"}"
...
...
@@ -447,7 +506,10 @@ void tst_AST::normal_array_access()
QVERIFY
(
func
);
StatementListAST
*
bodyStatements
=
func
->
function_body
->
asCompoundStatement
()
->
statements
;
QVERIFY
(
bodyStatements
&&
bodyStatements
->
next
&&
bodyStatements
->
next
->
next
&&
bodyStatements
->
next
->
next
->
statement
);
QVERIFY
(
bodyStatements
);
QVERIFY
(
bodyStatements
->
next
);
QVERIFY
(
bodyStatements
->
next
->
next
);
QVERIFY
(
bodyStatements
->
next
->
next
->
statement
);
ExpressionAST
*
expr
=
bodyStatements
->
next
->
next
->
statement
->
asReturnStatement
()
->
expression
;
QVERIFY
(
expr
);
...
...
@@ -536,9 +598,9 @@ void tst_AST::objc_msg_send_expression()
QVERIFY
(
bodyStatements
&&
bodyStatements
->
next
&&
!
bodyStatements
->
next
->
next
&&
bodyStatements
->
next
->
statement
);
{
// check the NSObject declaration
ExpressionOr
DeclarationStatementAST
*
firstStatement
=
bodyStatements
->
statement
->
as
ExpressionOr
DeclarationStatement
();
QVERIFY
(
firstStatement
&&
firstStatement
->
declaration
&&
firstStatement
->
declaration
->
asDeclarationStatement
()
);
DeclarationAST
*
objDecl
=
firstStatement
->
declaration
->
asDeclarationStatement
()
->
declaration
;
DeclarationStatementAST
*
firstStatement
=
bodyStatements
->
statement
->
asDeclarationStatement
();
QVERIFY
(
firstStatement
);
DeclarationAST
*
objDecl
=
firstStatement
->
declaration
;
QVERIFY
(
objDecl
);
SimpleDeclarationAST
*
simpleDecl
=
objDecl
->
asSimpleDeclaration
();
QVERIFY
(
simpleDecl
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment