forked from qt-creator/qt-creator
C: Parser: Support parsing of c99 designated initializers
In case:
int a[6] = { [4] = 29, [2] = 15 };
struct point { int x, y; };
struct point p = { .y = 3, .x = 2 };
Grammar change when c99 language feature is enabled:
old grammar:
braced-init-list :: '{' initializer-list '}'
new grammar:
braced-init-list :: '{' designated-initializer-list '}'
designated-initializer-list :: designated-initializer (',' designated-initializer )*
designated-initializer :: designator* initializer-clause
designator :: '.' identifier
| '[' constant-expression ']'
Task-number: QTCREATORBUG-1902
Change-Id: Ib99d6f553f8d0f50ba3eff86f3a2e86d73372426
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
66
src/libs/3rdparty/cplusplus/AST.cpp
vendored
66
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -4450,3 +4450,69 @@ unsigned AliasDeclarationAST::lastToken() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** \generated */
|
||||
unsigned DesignatedInitializerAST::firstToken() const
|
||||
{
|
||||
if (designator_list)
|
||||
if (unsigned candidate = designator_list->firstToken())
|
||||
return candidate;
|
||||
if (equal_token)
|
||||
return equal_token;
|
||||
if (initializer)
|
||||
if (unsigned candidate = initializer->firstToken())
|
||||
return candidate;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \generated */
|
||||
unsigned DesignatedInitializerAST::lastToken() const
|
||||
{
|
||||
if (initializer)
|
||||
if (unsigned candidate = initializer->lastToken())
|
||||
return candidate;
|
||||
if (equal_token)
|
||||
return equal_token + 1;
|
||||
if (designator_list)
|
||||
if (unsigned candidate = designator_list->lastToken())
|
||||
return candidate;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned DesignatorAST::firstToken() const
|
||||
{
|
||||
if (type == DesignatorAST::Dot) {
|
||||
if (u.dot.dot_token)
|
||||
return u.dot.dot_token;
|
||||
if (u.dot.identifier_token)
|
||||
return u.dot.identifier_token;
|
||||
} else if (type == DesignatorAST::Bracket) {
|
||||
if (u.bracket.lbracket_token)
|
||||
return u.bracket.lbracket_token;
|
||||
if (u.bracket.expression)
|
||||
if (unsigned candidate = u.bracket.expression->firstToken())
|
||||
return candidate;
|
||||
if (u.bracket.rbracket_token)
|
||||
return u.bracket.rbracket_token;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned DesignatorAST::lastToken() const
|
||||
{
|
||||
if (type == DesignatorAST::Dot) {
|
||||
if (u.dot.identifier_token)
|
||||
return u.dot.identifier_token + 1;
|
||||
if (u.dot.dot_token)
|
||||
return u.dot.dot_token + 1;
|
||||
} else if (type == DesignatorAST::Bracket) {
|
||||
if (u.bracket.rbracket_token)
|
||||
return u.bracket.rbracket_token + 1;
|
||||
if (u.bracket.expression)
|
||||
if (unsigned candidate = u.bracket.expression->lastToken())
|
||||
return candidate;
|
||||
if (u.bracket.lbracket_token)
|
||||
return u.bracket.lbracket_token + 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
68
src/libs/3rdparty/cplusplus/AST.h
vendored
68
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -161,6 +161,8 @@ public:
|
||||
virtual DeclaratorIdAST *asDeclaratorId() { return 0; }
|
||||
virtual DecltypeSpecifierAST *asDecltypeSpecifier() { return 0; }
|
||||
virtual DeleteExpressionAST *asDeleteExpression() { return 0; }
|
||||
virtual DesignatedInitializerAST *asDesignatedInitializer() { return 0; }
|
||||
virtual DesignatorAST *asDesignator() { return 0; }
|
||||
virtual DestructorNameAST *asDestructorName() { return 0; }
|
||||
virtual DoStatementAST *asDoStatement() { return 0; }
|
||||
virtual DynamicExceptionSpecificationAST *asDynamicExceptionSpecification() { return 0; }
|
||||
@@ -4527,6 +4529,72 @@ protected:
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
class DesignatorAST: public AST
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Invalid,
|
||||
Dot,
|
||||
Bracket
|
||||
};
|
||||
Type type;
|
||||
union Designator
|
||||
{
|
||||
struct DotDesignator
|
||||
{
|
||||
unsigned dot_token;
|
||||
unsigned identifier_token;
|
||||
} dot;
|
||||
struct BracketDesignator
|
||||
{
|
||||
unsigned lbracket_token;
|
||||
ExpressionAST *expression;
|
||||
unsigned rbracket_token;
|
||||
} bracket;
|
||||
} u;
|
||||
|
||||
public:
|
||||
DesignatorAST()
|
||||
: type(Invalid)
|
||||
{}
|
||||
|
||||
virtual DesignatorAST *asDesignator() { return this; }
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
|
||||
virtual DesignatorAST *clone(MemoryPool *pool) const;
|
||||
|
||||
protected:
|
||||
virtual void accept0(ASTVisitor *visitor);
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
class DesignatedInitializerAST: public ExpressionAST
|
||||
{
|
||||
public:
|
||||
DesignatorListAST *designator_list;
|
||||
unsigned equal_token;
|
||||
ExpressionAST *initializer;
|
||||
|
||||
public:
|
||||
DesignatedInitializerAST()
|
||||
: designator_list(0)
|
||||
, equal_token(0)
|
||||
, initializer(0)
|
||||
{}
|
||||
|
||||
virtual DesignatedInitializerAST *asDesignatedInitializer() { return this; }
|
||||
virtual unsigned firstToken() const;
|
||||
virtual unsigned lastToken() const;
|
||||
|
||||
virtual DesignatedInitializerAST *clone(MemoryPool *pool) const;
|
||||
|
||||
protected:
|
||||
virtual void accept0(ASTVisitor *visitor);
|
||||
virtual bool match0(AST *, ASTMatcher *);
|
||||
};
|
||||
|
||||
} // namespace CPlusPlus
|
||||
|
||||
#endif // CPLUSPLUS_AST_H
|
||||
|
||||
18
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
18
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -1762,3 +1762,21 @@ BracedInitializerAST *BracedInitializerAST::clone(MemoryPool *pool) const
|
||||
return ast;
|
||||
}
|
||||
|
||||
DesignatorAST *DesignatorAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
DesignatorAST *ast = new (pool) DesignatorAST;
|
||||
return ast;
|
||||
}
|
||||
|
||||
DesignatedInitializerAST *DesignatedInitializerAST::clone(MemoryPool *pool) const
|
||||
{
|
||||
DesignatedInitializerAST *ast = new (pool) DesignatedInitializerAST;
|
||||
for (DesignatorListAST *iter = designator_list, **ast_iter = &ast->designator_list;
|
||||
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
|
||||
*ast_iter = new (pool) DesignatorListAST((iter->value) ? iter->value->clone(pool) : 0);
|
||||
ast->equal_token = equal_token;
|
||||
if (initializer)
|
||||
ast->initializer = initializer->clone(pool);
|
||||
return ast;
|
||||
}
|
||||
|
||||
|
||||
16
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
16
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -1192,3 +1192,19 @@ bool BracedInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DesignatorAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (DesignatorAST *_other = pattern->asDesignator())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DesignatedInitializerAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
{
|
||||
if (DesignatedInitializerAST *_other = pattern->asDesignatedInitializer())
|
||||
return matcher->match(this, _other);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
28
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
28
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -2999,3 +2999,31 @@ bool ASTMatcher::match(BracedInitializerAST *node, BracedInitializerAST *pattern
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTMatcher::match(DesignatorAST *node, DesignatorAST *pattern)
|
||||
{
|
||||
(void) node;
|
||||
(void) pattern;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTMatcher::match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern)
|
||||
{
|
||||
(void) node;
|
||||
(void) pattern;
|
||||
|
||||
if (! pattern->designator_list)
|
||||
pattern->designator_list = node->designator_list;
|
||||
else if (! AST::match(node->designator_list, pattern->designator_list, this))
|
||||
return false;
|
||||
|
||||
pattern->equal_token = node->equal_token;
|
||||
|
||||
if (! pattern->initializer)
|
||||
pattern->initializer = node->initializer;
|
||||
else if (! AST::match(node->initializer, pattern->initializer, this))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
2
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
2
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -66,6 +66,8 @@ public:
|
||||
virtual bool match(DeclaratorIdAST *node, DeclaratorIdAST *pattern);
|
||||
virtual bool match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern);
|
||||
virtual bool match(DeleteExpressionAST *node, DeleteExpressionAST *pattern);
|
||||
virtual bool match(DesignatedInitializerAST *node, DesignatedInitializerAST *pattern);
|
||||
virtual bool match(DesignatorAST *node, DesignatorAST *pattern);
|
||||
virtual bool match(DestructorNameAST *node, DestructorNameAST *pattern);
|
||||
virtual bool match(DoStatementAST *node, DoStatementAST *pattern);
|
||||
virtual bool match(DynamicExceptionSpecificationAST *node, DynamicExceptionSpecificationAST *pattern);
|
||||
|
||||
22
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
22
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
@@ -1147,6 +1147,20 @@ public:
|
||||
return __ast;
|
||||
}
|
||||
|
||||
DesignatorAST *Designator()
|
||||
{
|
||||
DesignatorAST *__ast = new (&pool) DesignatorAST;
|
||||
return __ast;
|
||||
}
|
||||
|
||||
DesignatedInitializerAST *DesignatedInitializer(DesignatorListAST *designator_list = 0, ExpressionAST *initializer = 0)
|
||||
{
|
||||
DesignatedInitializerAST *__ast = new (&pool) DesignatedInitializerAST;
|
||||
__ast->designator_list = designator_list;
|
||||
__ast->initializer = initializer;
|
||||
return __ast;
|
||||
}
|
||||
|
||||
AttributeListAST *AttributeList(AttributeAST *value, AttributeListAST *next = 0)
|
||||
{
|
||||
AttributeListAST *__list = new (&pool) AttributeListAST;
|
||||
@@ -1195,6 +1209,14 @@ public:
|
||||
return __list;
|
||||
}
|
||||
|
||||
DesignatorListAST *DesignatorList(DesignatorAST *value, DesignatorListAST *next = 0)
|
||||
{
|
||||
DesignatorListAST *__list = new (&pool) DesignatorListAST;
|
||||
__list->next = next;
|
||||
__list->value = value;
|
||||
return __list;
|
||||
}
|
||||
|
||||
EnumeratorListAST *EnumeratorList(EnumeratorAST *value, EnumeratorListAST *next = 0)
|
||||
{
|
||||
EnumeratorListAST *__list = new (&pool) EnumeratorListAST;
|
||||
|
||||
16
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
16
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -1279,3 +1279,19 @@ void BracedInitializerAST::accept0(ASTVisitor *visitor)
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
void DesignatorAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
void DesignatedInitializerAST::accept0(ASTVisitor *visitor)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
accept(designator_list, visitor);
|
||||
accept(initializer, visitor);
|
||||
}
|
||||
visitor->endVisit(this);
|
||||
}
|
||||
|
||||
|
||||
4
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
4
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -108,6 +108,8 @@ public:
|
||||
virtual bool visit(DeclaratorIdAST *) { return true; }
|
||||
virtual bool visit(DecltypeSpecifierAST *) { return true; }
|
||||
virtual bool visit(DeleteExpressionAST *) { return true; }
|
||||
virtual bool visit(DesignatedInitializerAST *) { return true; }
|
||||
virtual bool visit(DesignatorAST *) { return true; }
|
||||
virtual bool visit(DestructorNameAST *) { return true; }
|
||||
virtual bool visit(DoStatementAST *) { return true; }
|
||||
virtual bool visit(DynamicExceptionSpecificationAST *) { return true; }
|
||||
@@ -254,6 +256,8 @@ public:
|
||||
virtual void endVisit(DeclaratorIdAST *) {}
|
||||
virtual void endVisit(DecltypeSpecifierAST *) {}
|
||||
virtual void endVisit(DeleteExpressionAST *) {}
|
||||
virtual void endVisit(DesignatedInitializerAST *) {}
|
||||
virtual void endVisit(DesignatorAST *) {}
|
||||
virtual void endVisit(DestructorNameAST *) {}
|
||||
virtual void endVisit(DoStatementAST *) {}
|
||||
virtual void endVisit(DynamicExceptionSpecificationAST *) {}
|
||||
|
||||
4
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
4
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -68,6 +68,8 @@ class DeclaratorAST;
|
||||
class DeclaratorIdAST;
|
||||
class DecltypeSpecifierAST;
|
||||
class DeleteExpressionAST;
|
||||
class DesignatedInitializerAST;
|
||||
class DesignatorAST;
|
||||
class DestructorNameAST;
|
||||
class DoStatementAST;
|
||||
class DynamicExceptionSpecificationAST;
|
||||
@@ -215,6 +217,8 @@ typedef List<ObjCPropertyAttributeAST *> ObjCPropertyAttributeListAST;
|
||||
typedef List<ObjCMessageArgumentDeclarationAST *> ObjCMessageArgumentDeclarationListAST;
|
||||
typedef List<ObjCSynthesizedPropertyAST *> ObjCSynthesizedPropertyListAST;
|
||||
|
||||
typedef List<DesignatorAST *> DesignatorListAST;
|
||||
|
||||
} // namespace CPlusPlus
|
||||
|
||||
|
||||
|
||||
48
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
48
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -2664,7 +2664,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
|
||||
ExpressionListAST **expression_list_ptr = &node;
|
||||
ExpressionAST *expression = 0;
|
||||
|
||||
if (parseInitializerClause0x(expression)) {
|
||||
if (parseDesignatedInitializer(expression)) {
|
||||
*expression_list_ptr = new (_pool) ExpressionListAST;
|
||||
(*expression_list_ptr)->value = expression;
|
||||
expression_list_ptr = &(*expression_list_ptr)->next;
|
||||
@@ -2675,7 +2675,7 @@ bool Parser::parseInitializerList0x(ExpressionListAST *&node)
|
||||
while (LA() == T_COMMA && LA(2) != T_RBRACE) {
|
||||
consumeToken(); // consume T_COMMA
|
||||
|
||||
if (parseInitializerClause0x(expression)) {
|
||||
if (parseDesignatedInitializer(expression)) {
|
||||
*expression_list_ptr = new (_pool) ExpressionListAST;
|
||||
(*expression_list_ptr)->value = expression;
|
||||
|
||||
@@ -5484,6 +5484,50 @@ bool Parser::lookAtObjCSelector() const
|
||||
return false;
|
||||
}
|
||||
|
||||
// designated-initializer ::= designator* T_EQUAL initializer-clause
|
||||
//
|
||||
bool Parser::parseDesignatedInitializer(ExpressionAST *&node)
|
||||
{
|
||||
DEBUG_THIS_RULE();
|
||||
if (!_languageFeatures.c99Enabled || (LA() != T_DOT && LA() != T_LBRACKET))
|
||||
return parseInitializerClause0x(node);
|
||||
|
||||
DesignatedInitializerAST *ast = new (_pool) DesignatedInitializerAST;
|
||||
DesignatorListAST **designator_list_ptr = &ast->designator_list;
|
||||
DesignatorAST *designator = 0;
|
||||
while (parseDesignator(designator)) {
|
||||
*designator_list_ptr = new (_pool) DesignatorListAST;
|
||||
(*designator_list_ptr)->value = designator;
|
||||
designator_list_ptr = &(*designator_list_ptr)->next;
|
||||
}
|
||||
match(T_EQUAL, &ast->equal_token);
|
||||
parseInitializerClause0x(ast->initializer);
|
||||
node = ast;
|
||||
return true;
|
||||
}
|
||||
|
||||
// designator ::= T_DOT T_IDENTIFIER
|
||||
// T_LBRACKET constant-expression T_BRACKET
|
||||
//
|
||||
bool Parser::parseDesignator(DesignatorAST *&node)
|
||||
{
|
||||
DesignatorAST *ast = new (_pool) DesignatorAST;
|
||||
if (LA() == T_DOT) {
|
||||
ast->type = DesignatorAST::Dot;
|
||||
ast->u.dot.dot_token = consumeToken();
|
||||
match(T_IDENTIFIER, &ast->u.dot.identifier_token);
|
||||
} else if (LA() == T_LBRACKET) {
|
||||
ast->type = DesignatorAST::Bracket;
|
||||
ast->u.bracket.lbracket_token = consumeToken();
|
||||
parseConstantExpression(ast->u.bracket.expression);
|
||||
match(T_RBRACKET, &ast->u.bracket.rbracket_token);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
node = ast;
|
||||
return true;
|
||||
}
|
||||
|
||||
// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON
|
||||
//
|
||||
bool Parser::parseObjCClassForwardDeclaration(DeclarationAST *&node)
|
||||
|
||||
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -246,6 +246,11 @@ public:
|
||||
|
||||
bool lookAtObjCSelector() const;
|
||||
|
||||
// c99
|
||||
bool parseDesignatedInitializerList(ExpressionListAST *&node);
|
||||
bool parseDesignatedInitializer(ExpressionAST *&node);
|
||||
bool parseDesignator(DesignatorAST *&node);
|
||||
|
||||
bool skipUntil(int token);
|
||||
void skipUntilDeclaration();
|
||||
bool skipUntilStatement();
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/Token.h
vendored
1
src/libs/3rdparty/cplusplus/Token.h
vendored
@@ -390,6 +390,7 @@ struct LanguageFeatures
|
||||
unsigned int qtKeywordsEnabled : 1; // If Qt is used but QT_NO_KEYWORDS defined
|
||||
unsigned int cxx11Enabled : 1;
|
||||
unsigned int objCEnabled : 1;
|
||||
unsigned int c99Enabled : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user