diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 5e166b83b2bdc98f08622e356a817a11f77c5bae..dd341db6d9af3b79e3196f5e5fef3c069cd6bbc9 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -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; +} + diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 556f898f6d770700061626902edbc09581092cb2..41c630aea86003fc94535a56a12771bd2891da31 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -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 diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 8ff5d0e9d7e02c4e8eb9b5cddecab43914a4a3d6..086b12b1c9b66ebd33372560bedd92d8fbff906d 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -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; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp index 69e3daf6156af40f6fad172f42690898554f7196..efeb2c57e0eefd24e137c336ca1720ab941331ab 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp @@ -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; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index 105f236070bbedce08b392be66a55c689507a47f..02cdb9f068925f75cfd62e2524bac014178699b0 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -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; +} + diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h index eee507b9419d7b45c6799bfbdf1f70487840a72a..ebb18884e301b63158675381c633d0a8466a502a 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.h +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h @@ -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); diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index b4d413efd8ae2b931f5cb910845ad547f36ca90f..ce55ccfe813767a8c6b5e0ed16845e25023efae2 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -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; diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 69ce44c8f17b983cb9d785125ec78c8130f3f7f4..983f09fc29c26ccf26539328704cdbd720a18f88 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -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); +} + diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h index d9578a406144d5fcce78b4be4c28d367b7f02eb1..66c6c011f4c5a160f2fa9605defb7dd3fd7e7521 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.h +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h @@ -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 *) {} diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h index 7b79947cb927f803449cf6814015a9f80e7853ce..a3382c89d60eb2ae933267935af8b0d65f3212d8 100644 --- a/src/libs/3rdparty/cplusplus/ASTfwd.h +++ b/src/libs/3rdparty/cplusplus/ASTfwd.h @@ -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 ObjCPropertyAttributeListAST; typedef List ObjCMessageArgumentDeclarationListAST; typedef List ObjCSynthesizedPropertyListAST; +typedef List DesignatorListAST; + } // namespace CPlusPlus diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index dfd6d1e49aa2208f23ef3ff7b55f2bef3f82d6ea..0163046176c6f76d59560eed4d8052fbd755bb46 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -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) diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index ea49df5e5616b471d3417fba60540c5b4c7a8e8b..c18a079e4ef0b082d52bb71879fbdc6269b00d3a 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -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(); diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index ec10483852012a4b22c7d791e13f7e33394b33a8..d4a2901c34705b69964e6fe7c3279f3110d6bb6d 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -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; }; }; }; diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index e159f774b30619987cf501980e33a7c25c448a5f..9a18343eda54fc3acf9068f1d04ef23425624a60 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -288,6 +288,7 @@ Document::Document(const QString &fileName) features.qtKeywordsEnabled = true; features.cxx11Enabled = true; features.objCEnabled = true; + features.c99Enabled = true; _translationUnit = new TranslationUnit(_control, fileId); _translationUnit->setLanguageFeatures(features); (void) _control->switchTranslationUnit(_translationUnit); diff --git a/src/plugins/cppeditor/cppautocompleter.cpp b/src/plugins/cppeditor/cppautocompleter.cpp index aa37b846aa6d5a9a3b2905090fc811bb39ce61d8..23c546004ff62000b230f2d18afbc92dc0a4035b 100644 --- a/src/plugins/cppeditor/cppautocompleter.cpp +++ b/src/plugins/cppeditor/cppautocompleter.cpp @@ -106,6 +106,7 @@ bool CppAutoCompleter::isInCommentHelper(const QTextCursor &cursor, Token *retTo features.qtKeywordsEnabled = false; features.qtMocRunEnabled = false; features.cxx11Enabled = true; + features.c99Enabled = true; SimpleLexer tokenize; tokenize.setLanguageFeatures(features); diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp index 2617d262b339d37b190ef2836efa8db6dce61098..241619ded0d752a8fca4395ec66914eaeb297a0c 100644 --- a/src/plugins/cppeditor/cpphighlighter.cpp +++ b/src/plugins/cppeditor/cpphighlighter.cpp @@ -77,6 +77,7 @@ void CppHighlighter::highlightBlock(const QString &text) // FIXME: Check defaults or get from document. LanguageFeatures features; features.cxx11Enabled = true; + features.c99Enabled = true; SimpleLexer tokenize; tokenize.setLanguageFeatures(features); diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index acc5c7f7d22bdc5d541a6bfca884d493c296dcb9..3f69c86ac3dec5a6c2ff3abd3d855309c199d63f 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -495,6 +495,13 @@ bool CheckSymbols::visit(EnumeratorAST *ast) return true; } +bool CheckSymbols::visit(DesignatorAST *ast) +{ + if (ast->type == DesignatorAST::Dot) + addUse(ast->u.dot.identifier_token, CppHighlightingSupport::FieldUse); + return true; +} + bool CheckSymbols::visit(SimpleDeclarationAST *ast) { NameAST *declrIdNameAST = 0; diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h index 3fcf1ee6985febcd46b4e5c3830d28d06099875c..3d3a7302c4bfdde2c0fdaf96bad2836b06e1e139 100644 --- a/src/plugins/cpptools/cppchecksymbols.h +++ b/src/plugins/cpptools/cppchecksymbols.h @@ -160,6 +160,8 @@ protected: virtual bool visit(CPlusPlus::MemInitializerAST *ast); virtual bool visit(CPlusPlus::EnumeratorAST *ast); + virtual bool visit(CPlusPlus::DesignatorAST *ast); + CPlusPlus::NameAST *declaratorId(CPlusPlus::DeclaratorAST *ast) const; static unsigned referenceToken(CPlusPlus::NameAST *name); diff --git a/src/plugins/cpptools/cpphighlightingsupportinternal.cpp b/src/plugins/cpptools/cpphighlightingsupportinternal.cpp index 26dc9cf2539e1f941a2074ab091176b23df9db89..852868cc7782dce0e443b6ff5afd3d87d17ca1e7 100644 --- a/src/plugins/cpptools/cpphighlightingsupportinternal.cpp +++ b/src/plugins/cpptools/cpphighlightingsupportinternal.cpp @@ -83,6 +83,7 @@ QFuture CppHighlightingSupportInternal::highligh // FIXME: Check default values or get from document. LanguageFeatures features; features.cxx11Enabled = true; + features.c99Enabled = true; SimpleLexer tokenize; tokenize.setLanguageFeatures(features); diff --git a/tests/auto/cplusplus/c99/c99.pro b/tests/auto/cplusplus/c99/c99.pro new file mode 100644 index 0000000000000000000000000000000000000000..b40c99036db6249e86bc9981d4ead8ef651029c9 --- /dev/null +++ b/tests/auto/cplusplus/c99/c99.pro @@ -0,0 +1,8 @@ +include(../shared/shared.pri) + +# Inject the source dir for referencing test data from shadow builds. +DEFINES += SRCDIR=\\\"$$PWD\\\" + +SOURCES += tst_c99.cpp +OTHER_FILES += \ + data/designatedInitializer.1.c diff --git a/tests/auto/cplusplus/c99/c99.qbs b/tests/auto/cplusplus/c99/c99.qbs new file mode 100644 index 0000000000000000000000000000000000000000..24da3535cf3113a30789412ace1da3ca31f9dced --- /dev/null +++ b/tests/auto/cplusplus/c99/c99.qbs @@ -0,0 +1,21 @@ +import qbs +import "../cplusplusautotest.qbs" as CPlusPlusAutotest + +CPlusPlusAutotest { + name: "C99 autotest" + Group { + name: "Source Files" + files: "tst_c99.cpp" + } + + Group { + name: "Data Files" + prefix: "data/" + fileTags: ["data"] + files: [ + "designatedInitializer.1.c", + ] + } + + cpp.defines: base.concat(['SRCDIR="' + path + '"']) +} diff --git a/tests/auto/cplusplus/c99/data/designatedInitializer.1.c b/tests/auto/cplusplus/c99/data/designatedInitializer.1.c new file mode 100644 index 0000000000000000000000000000000000000000..43db4b66477e8a9dc9a07fd45f7003aad8b78ad1 --- /dev/null +++ b/tests/auto/cplusplus/c99/data/designatedInitializer.1.c @@ -0,0 +1,9 @@ +int aa[4] = { [2] = 3, [1] = 6 }; +static short grid[3] [4] = { [0][0]=8, [0][1]=6, + [0][2]=4, [0][3]=1, + [2][0]=9, [2][1]=3, + [2][2]=1, [2][3]=1 }; +int a[10] = {2, 4, [8]=9, 10}; +int a[MAX] = { + 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 +}; diff --git a/tests/auto/cplusplus/c99/data/designatedInitializer.2.c b/tests/auto/cplusplus/c99/data/designatedInitializer.2.c new file mode 100644 index 0000000000000000000000000000000000000000..cf2d84f5a3bce4fc7e40723123cff1d8ea08ff42 --- /dev/null +++ b/tests/auto/cplusplus/c99/data/designatedInitializer.2.c @@ -0,0 +1,12 @@ +struct xyz { + int a; + int b; + int c; +} klm = { .a = 99, .c = 100 }; +struct a { + struct b { + int c; + int d; + } e; + float f; +} g = {.e.c = 3 }; diff --git a/tests/auto/cplusplus/c99/tst_c99.cpp b/tests/auto/cplusplus/c99/tst_c99.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e7afb65c6e3f4c59c2763314efc851fec2644d5 --- /dev/null +++ b/tests/auto/cplusplus/c99/tst_c99.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +//TESTED_COMPONENT=src/libs/cplusplus +using namespace CPlusPlus; + +#define VERIFY_ERRORS() \ + do { \ + QByteArray expectedErrors; \ + if (!errorFile.isEmpty()) { \ + QFile e(testdata(errorFile)); \ + if (e.open(QFile::ReadOnly)) \ + expectedErrors = QTextStream(&e).readAll().toUtf8(); \ + } \ + QCOMPARE(QString::fromLatin1(errors), QString::fromLatin1(expectedErrors)); \ + } while (0) + + +class tst_c99: public QObject +{ + Q_OBJECT + + /* + Returns the path to some testdata file or directory. + */ + static QString testdata(const QString &name = QString()) + { + static const QString dataDirectory = QLatin1String(SRCDIR "/data"); + + QString result = dataDirectory; + if (!name.isEmpty()) { + result += QLatin1Char('/'); + result += name; + } + return result; + } + + struct Client: CPlusPlus::DiagnosticClient { + QByteArray *errors; + + Client(QByteArray *errors) + : errors(errors) + { + } + + virtual void report(int level, + const StringLiteral *fileName, + unsigned line, unsigned column, + const char *format, va_list ap) + { + if (! errors) + return; + + static const char *const pretty[] = { "warning", "error", "fatal" }; + + QString str; + str.sprintf("%s:%d:%d: %s: ", fileName->chars(), line, column, pretty[level]); + errors->append(str.toUtf8()); + + str.vsprintf(format, ap); + errors->append(str.toUtf8()); + + errors->append('\n'); + } + }; + + Document::Ptr document(const QString &fileName, QByteArray *errors = 0) + { + Document::Ptr doc = Document::create(fileName); + QFile file(testdata(fileName)); + if (file.open(QFile::ReadOnly)) { + LanguageFeatures features; + features.c99Enabled = true; + Client client(errors); + doc->control()->setDiagnosticClient(&client); + doc->setUtf8Source(QTextStream(&file).readAll().toUtf8()); + doc->translationUnit()->setLanguageFeatures(features); + doc->check(); + doc->control()->setDiagnosticClient(0); + } else { + qWarning() << "could not read file" << fileName; + } + return doc; + } + +private Q_SLOTS: + // + // checks for the syntax + // + void parse_data(); + void parse(); +}; + + +void tst_c99::parse_data() +{ + QTest::addColumn("file"); + QTest::addColumn("errorFile"); + + QTest::newRow("designatedInitializer.1") << "designatedInitializer.1.c" << ""; + QTest::newRow("designatedInitializer.2") << "designatedInitializer.2.c" << ""; +} + +void tst_c99::parse() +{ + QFETCH(QString, file); + QFETCH(QString, errorFile); + + QByteArray errors; + Document::Ptr doc = document(file, &errors); + + if (! qgetenv("DEBUG").isNull()) + printf("%s\n", errors.constData()); + + VERIFY_ERRORS(); +} + +QTEST_APPLESS_MAIN(tst_c99) +#include "tst_c99.moc" diff --git a/tests/auto/cplusplus/cplusplus.pro b/tests/auto/cplusplus/cplusplus.pro index 3cbc0dfdf2f2587f4f1ad213b919c713976527f5..b44d24b6cf261749da2cdee9b7000fb4ca44cc95 100644 --- a/tests/auto/cplusplus/cplusplus.pro +++ b/tests/auto/cplusplus/cplusplus.pro @@ -10,6 +10,7 @@ SUBDIRS = \ semantic \ typeprettyprinter \ misc \ + c99 \ cxx11 \ checksymbols \ lexer \ diff --git a/tests/auto/cplusplus/cplusplus.qbs b/tests/auto/cplusplus/cplusplus.qbs index 338a7c9b4b1825fa5628e5c71a1236356e8baf00..973ec1bd459c6335da5286843da25ed26749b3c1 100644 --- a/tests/auto/cplusplus/cplusplus.qbs +++ b/tests/auto/cplusplus/cplusplus.qbs @@ -4,6 +4,7 @@ Project { name: "CPlusPlus autotests" references: [ "ast/ast.qbs", + "c99/c99.qbs", "checksymbols/checksymbols.qbs", "codeformatter/codeformatter.qbs", "cxx11/cxx11.qbs", diff --git a/tests/tools/cplusplus-ast2png/dumpers.inc b/tests/tools/cplusplus-ast2png/dumpers.inc index caf4b8d77212a95850ef2f5974a5c0817c912e12..8cc0aedcfe5593a60c52af6edc05b12f122a4510 100644 --- a/tests/tools/cplusplus-ast2png/dumpers.inc +++ b/tests/tools/cplusplus-ast2png/dumpers.inc @@ -1698,3 +1698,18 @@ virtual bool visit(BracedInitializerAST *ast) return false; } +virtual bool visit(DesignatorAST *ast) +{ + return false; +} + +virtual bool visit(DesignatedInitializerAST *ast) +{ + for (DesignatorListAST *iter = ast->designator_list; iter; iter = iter->next) + nonterminal(iter->value); + if (ast->equal_token) + terminal(ast->equal_token, ast); + nonterminal(ast->initializer); + return false; +} +