diff options
author | Volodymyr Zibarov <gogan419@gmail.com> | 2020-05-14 23:07:05 +0300 |
---|---|---|
committer | Volodymyr Zibarov <gogan419@gmail.com> | 2020-05-29 12:39:28 +0000 |
commit | 9ee693ee229d28bd618e8dd44bc6b12750d43a29 (patch) | |
tree | 7a2a4dd6679fd3647228b5c39d1fc2724ff133a3 /src/libs/3rdparty/cplusplus | |
parent | be97943372bc80d2440daa20cd658599d765b9a9 (diff) | |
download | qt-creator-9ee693ee229d28bd618e8dd44bc6b12750d43a29.tar.gz |
C++: fix built-in code model to work with shared_ptr on MSVC 2017
These changes target Find Usages feature to work with shared_ptr.
Improve libs/3rdparty/cplusplus and plugins/cplusplus:
parse __declspec() attribute,
call to variadic function template without specified template arguments,
if constexpr,
c++11 attributes [[value]],
function templates with default parameters,
resolve order for function vs template with default parameter,
template operator->() with default arguments,
template specialization with numeric values,
find best partial specialization,
fix partial specialization for non-first specialized argument
Fixes: QTCREATORBUG-7866
Fixes: QTCREATORBUG-20781
Fixes: QTCREATORBUG-22857
Fixes: QTCREATORBUG-17825
Change-Id: I31a080f7729edfb2ee9650f1aff48daeba5a673b
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Nikolai Kosjar <pinaceae.pinus@gmail.com>
Diffstat (limited to 'src/libs/3rdparty/cplusplus')
27 files changed, 466 insertions, 18 deletions
diff --git a/src/libs/3rdparty/cplusplus/AST.cpp b/src/libs/3rdparty/cplusplus/AST.cpp index 3b91838eec..a48067ab75 100644 --- a/src/libs/3rdparty/cplusplus/AST.cpp +++ b/src/libs/3rdparty/cplusplus/AST.cpp @@ -73,6 +73,16 @@ int GnuAttributeSpecifierAST::firstToken() const return attribute_token; } +int MsvcDeclspecSpecifierAST::firstToken() const +{ + return attribute_token; +} + +int StdAttributeSpecifierAST::firstToken() const +{ + return first_lbracket_token; +} + int BaseSpecifierAST::firstToken() const { if (virtual_token && access_specifier_token) @@ -1524,6 +1534,8 @@ int IfStatementAST::firstToken() const { if (if_token) return if_token; + if (constexpr_token) + return constexpr_token; if (lparen_token) return lparen_token; if (condition) @@ -1560,6 +1572,8 @@ int IfStatementAST::lastToken() const return candidate; if (lparen_token) return lparen_token + 1; + if (constexpr_token) + return constexpr_token + 1; if (if_token) return if_token + 1; return 1; @@ -4214,6 +4228,36 @@ int GnuAttributeSpecifierAST::lastToken() const return 1; } +int MsvcDeclspecSpecifierAST::lastToken() const +{ + if (rparen_token) + return rparen_token + 1; + if (attribute_list) + if (int candidate = attribute_list->lastToken()) + return candidate; + if (lparen_token) + return lparen_token + 1; + if (attribute_token) + return attribute_token + 1; + return 1; +} + +int StdAttributeSpecifierAST::lastToken() const +{ + if (second_rbracket_token) + return second_rbracket_token + 1; + if (first_rbracket_token) + return first_rbracket_token + 1; + if (attribute_list) + if (int candidate = attribute_list->lastToken()) + return candidate; + if (second_lbracket_token) + return second_lbracket_token + 1; + if (first_lbracket_token) + return first_lbracket_token + 1; + return 1; +} + /** \generated */ int PointerLiteralAST::firstToken() const { diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index f3eb70aa4a..a03f5b5f82 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -195,6 +195,7 @@ public: virtual LinkageSpecificationAST *asLinkageSpecification() { return nullptr; } virtual MemInitializerAST *asMemInitializer() { return nullptr; } virtual MemberAccessAST *asMemberAccess() { return nullptr; } + virtual MsvcDeclspecSpecifierAST *asMsvcDeclspecSpecifier() { return nullptr; } virtual NameAST *asName() { return nullptr; } virtual NamedTypeSpecifierAST *asNamedTypeSpecifier() { return nullptr; } virtual NamespaceAST *asNamespace() { return nullptr; } @@ -265,6 +266,7 @@ public: virtual SpecifierAST *asSpecifier() { return nullptr; } virtual StatementAST *asStatement() { return nullptr; } virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return nullptr; } + virtual StdAttributeSpecifierAST *asStdAttributeSpecifier() { return nullptr; } virtual StringLiteralAST *asStringLiteral() { return nullptr; } virtual SwitchStatementAST *asSwitchStatement() { return nullptr; } virtual TemplateDeclarationAST *asTemplateDeclaration() { return nullptr; } @@ -475,6 +477,49 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +class CPLUSPLUS_EXPORT MsvcDeclspecSpecifierAST: public AttributeSpecifierAST +{ +public: + int attribute_token = 0; + int lparen_token = 0; + GnuAttributeListAST *attribute_list = nullptr; + int rparen_token = 0; + +public: + virtual MsvcDeclspecSpecifierAST *asMsvcDeclspecSpecifier() { return this; } + + virtual int firstToken() const; + virtual int lastToken() const; + + virtual MsvcDeclspecSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT StdAttributeSpecifierAST: public AttributeSpecifierAST +{ +public: + int first_lbracket_token = 0; + int second_lbracket_token = 0; + GnuAttributeListAST *attribute_list = nullptr; + int first_rbracket_token = 0; + int second_rbracket_token = 0; + +public: + virtual StdAttributeSpecifierAST *asStdAttributeSpecifier() { return this; } + + virtual int firstToken() const; + virtual int lastToken() const; + + virtual StdAttributeSpecifierAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + class CPLUSPLUS_EXPORT GnuAttributeAST: public AST { public: @@ -1610,6 +1655,7 @@ class CPLUSPLUS_EXPORT IfStatementAST: public StatementAST { public: int if_token = 0; + int constexpr_token = 0; int lparen_token = 0; ExpressionAST *condition = nullptr; int rparen_token = 0; diff --git a/src/libs/3rdparty/cplusplus/ASTClone.cpp b/src/libs/3rdparty/cplusplus/ASTClone.cpp index 65350e3eab..9ca371f3a9 100644 --- a/src/libs/3rdparty/cplusplus/ASTClone.cpp +++ b/src/libs/3rdparty/cplusplus/ASTClone.cpp @@ -81,6 +81,31 @@ GnuAttributeSpecifierAST *GnuAttributeSpecifierAST::clone(MemoryPool *pool) cons return ast; } +MsvcDeclspecSpecifierAST *MsvcDeclspecSpecifierAST::clone(MemoryPool *pool) const +{ + MsvcDeclspecSpecifierAST *ast = new (pool) MsvcDeclspecSpecifierAST; + ast->attribute_token = attribute_token; + ast->lparen_token = lparen_token; + for (GnuAttributeListAST *iter = attribute_list, **ast_iter = &ast->attribute_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) GnuAttributeListAST((iter->value) ? iter->value->clone(pool) : nullptr); + ast->rparen_token = rparen_token; + return ast; +} + +StdAttributeSpecifierAST *StdAttributeSpecifierAST::clone(MemoryPool *pool) const +{ + StdAttributeSpecifierAST *ast = new (pool) StdAttributeSpecifierAST; + ast->first_lbracket_token = first_lbracket_token; + ast->second_lbracket_token = second_lbracket_token; + for (GnuAttributeListAST *iter = attribute_list, **ast_iter = &ast->attribute_list; + iter; iter = iter->next, ast_iter = &(*ast_iter)->next) + *ast_iter = new (pool) GnuAttributeListAST((iter->value) ? iter->value->clone(pool) : nullptr); + ast->first_rbracket_token = first_rbracket_token; + ast->second_rbracket_token = second_rbracket_token; + return ast; +} + GnuAttributeAST *GnuAttributeAST::clone(MemoryPool *pool) const { GnuAttributeAST *ast = new (pool) GnuAttributeAST; @@ -730,6 +755,7 @@ IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const { IfStatementAST *ast = new (pool) IfStatementAST; ast->if_token = if_token; + ast->constexpr_token = constexpr_token; ast->lparen_token = lparen_token; if (condition) ast->condition = condition->clone(pool); diff --git a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp index 66c6a1be4d..1a82d29f6e 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatch0.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatch0.cpp @@ -72,6 +72,22 @@ bool GnuAttributeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +bool MsvcDeclspecSpecifierAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (MsvcDeclspecSpecifierAST *_other = pattern->asMsvcDeclspecSpecifier()) + return matcher->match(this, _other); + + return false; +} + +bool StdAttributeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (StdAttributeSpecifierAST *_other = pattern->asStdAttributeSpecifier()) + return matcher->match(this, _other); + + return false; +} + bool GnuAttributeAST::match0(AST *pattern, ASTMatcher *matcher) { if (GnuAttributeAST *_other = pattern->asGnuAttribute()) diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp index d76180a8ca..321d14a263 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.cpp +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.cpp @@ -117,6 +117,46 @@ bool ASTMatcher::match(GnuAttributeSpecifierAST *node, GnuAttributeSpecifierAST return true; } +bool ASTMatcher::match(MsvcDeclspecSpecifierAST *node, MsvcDeclspecSpecifierAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->attribute_token = node->attribute_token; + + pattern->lparen_token = node->lparen_token; + + if (! pattern->attribute_list) + pattern->attribute_list = node->attribute_list; + else if (! AST::match(node->attribute_list, pattern->attribute_list, this)) + return false; + + pattern->rparen_token = node->rparen_token; + + return true; +} + +bool ASTMatcher::match(StdAttributeSpecifierAST *node, StdAttributeSpecifierAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->first_lbracket_token = node->first_lbracket_token; + + pattern->second_lbracket_token = node->second_lbracket_token; + + if (! pattern->attribute_list) + pattern->attribute_list = node->attribute_list; + else if (! AST::match(node->attribute_list, pattern->attribute_list, this)) + return false; + + pattern->first_rbracket_token = node->first_rbracket_token; + + pattern->second_rbracket_token = node->second_rbracket_token; + + return true; +} + bool ASTMatcher::match(GnuAttributeAST *node, GnuAttributeAST *pattern) { (void) node; @@ -1246,6 +1286,8 @@ bool ASTMatcher::match(IfStatementAST *node, IfStatementAST *pattern) pattern->if_token = node->if_token; + pattern->constexpr_token = node->constexpr_token; + pattern->lparen_token = node->lparen_token; if (! pattern->condition) diff --git a/src/libs/3rdparty/cplusplus/ASTMatcher.h b/src/libs/3rdparty/cplusplus/ASTMatcher.h index f6f3eae8d9..47d9ecf5bf 100644 --- a/src/libs/3rdparty/cplusplus/ASTMatcher.h +++ b/src/libs/3rdparty/cplusplus/ASTMatcher.h @@ -96,6 +96,7 @@ public: virtual bool match(LinkageSpecificationAST *node, LinkageSpecificationAST *pattern); virtual bool match(MemInitializerAST *node, MemInitializerAST *pattern); virtual bool match(MemberAccessAST *node, MemberAccessAST *pattern); + virtual bool match(MsvcDeclspecSpecifierAST *node, MsvcDeclspecSpecifierAST *pattern); virtual bool match(NamedTypeSpecifierAST *node, NamedTypeSpecifierAST *pattern); virtual bool match(NamespaceAST *node, NamespaceAST *pattern); virtual bool match(NamespaceAliasDefinitionAST *node, NamespaceAliasDefinitionAST *pattern); @@ -160,6 +161,7 @@ public: virtual bool match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern); virtual bool match(SizeofExpressionAST *node, SizeofExpressionAST *pattern); virtual bool match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *pattern); + virtual bool match(StdAttributeSpecifierAST *node, StdAttributeSpecifierAST *pattern); virtual bool match(StringLiteralAST *node, StringLiteralAST *pattern); virtual bool match(SwitchStatementAST *node, SwitchStatementAST *pattern); virtual bool match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern); diff --git a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h index c2888b3e2e..9e2a263533 100644 --- a/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h +++ b/src/libs/3rdparty/cplusplus/ASTPatternBuilder.h @@ -76,6 +76,20 @@ public: return ast; } + MsvcDeclspecSpecifierAST *MsvcDeclspecSpecifier(GnuAttributeListAST *attribute_list = nullptr) + { + MsvcDeclspecSpecifierAST *ast = new (&pool) MsvcDeclspecSpecifierAST; + ast->attribute_list = attribute_list; + return ast; + } + + StdAttributeSpecifierAST *StdAttributeSpecifier(GnuAttributeListAST *attribute_list = nullptr) + { + StdAttributeSpecifierAST *ast = new (&pool) StdAttributeSpecifierAST; + ast->attribute_list = attribute_list; + return ast; + } + GnuAttributeAST *GnuAttribute(ExpressionListAST *expression_list = nullptr) { GnuAttributeAST *ast = new (&pool) GnuAttributeAST; diff --git a/src/libs/3rdparty/cplusplus/ASTVisit.cpp b/src/libs/3rdparty/cplusplus/ASTVisit.cpp index 5ebe6ba3a5..b9e954972e 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisit.cpp +++ b/src/libs/3rdparty/cplusplus/ASTVisit.cpp @@ -70,6 +70,22 @@ void GnuAttributeSpecifierAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +void MsvcDeclspecSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(attribute_list, visitor); + } + visitor->endVisit(this); +} + +void StdAttributeSpecifierAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(attribute_list, visitor); + } + visitor->endVisit(this); +} + void GnuAttributeAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/libs/3rdparty/cplusplus/ASTVisitor.h b/src/libs/3rdparty/cplusplus/ASTVisitor.h index a1740e12cd..7f45d4d06d 100644 --- a/src/libs/3rdparty/cplusplus/ASTVisitor.h +++ b/src/libs/3rdparty/cplusplus/ASTVisitor.h @@ -138,6 +138,7 @@ public: virtual bool visit(LinkageSpecificationAST *) { return true; } virtual bool visit(MemInitializerAST *) { return true; } virtual bool visit(MemberAccessAST *) { return true; } + virtual bool visit(MsvcDeclspecSpecifierAST *) { return true; } virtual bool visit(NamedTypeSpecifierAST *) { return true; } virtual bool visit(NamespaceAST *) { return true; } virtual bool visit(NamespaceAliasDefinitionAST *) { return true; } @@ -202,6 +203,7 @@ public: virtual bool visit(SimpleSpecifierAST *) { return true; } virtual bool visit(SizeofExpressionAST *) { return true; } virtual bool visit(StaticAssertDeclarationAST *) { return true; } + virtual bool visit(StdAttributeSpecifierAST *) { return true; } virtual bool visit(StringLiteralAST *) { return true; } virtual bool visit(SwitchStatementAST *) { return true; } virtual bool visit(TemplateDeclarationAST *) { return true; } @@ -289,6 +291,7 @@ public: virtual void endVisit(LinkageSpecificationAST *) {} virtual void endVisit(MemInitializerAST *) {} virtual void endVisit(MemberAccessAST *) {} + virtual void endVisit(MsvcDeclspecSpecifierAST *) {} virtual void endVisit(NamedTypeSpecifierAST *) {} virtual void endVisit(NamespaceAST *) {} virtual void endVisit(NamespaceAliasDefinitionAST *) {} @@ -353,6 +356,7 @@ public: virtual void endVisit(SimpleSpecifierAST *) {} virtual void endVisit(SizeofExpressionAST *) {} virtual void endVisit(StaticAssertDeclarationAST *) {} + virtual void endVisit(StdAttributeSpecifierAST *) {} virtual void endVisit(StringLiteralAST *) {} virtual void endVisit(SwitchStatementAST *) {} virtual void endVisit(TemplateDeclarationAST *) {} diff --git a/src/libs/3rdparty/cplusplus/ASTfwd.h b/src/libs/3rdparty/cplusplus/ASTfwd.h index 2c55fd27d6..fb6de59abd 100644 --- a/src/libs/3rdparty/cplusplus/ASTfwd.h +++ b/src/libs/3rdparty/cplusplus/ASTfwd.h @@ -102,6 +102,7 @@ class LinkageBodyAST; class LinkageSpecificationAST; class MemInitializerAST; class MemberAccessAST; +class MsvcDeclspecSpecifierAST; class NameAST; class NamedTypeSpecifierAST; class NamespaceAST; @@ -172,6 +173,7 @@ class SizeofExpressionAST; class SpecifierAST; class StatementAST; class StaticAssertDeclarationAST; +class StdAttributeSpecifierAST; class StringLiteralAST; class SwitchStatementAST; class TemplateDeclarationAST; diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 486efffc3d..53a14f6def 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -918,6 +918,19 @@ void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lp for (ParameterDeclarationListAST *it = ast->parameter_declaration_list; it; it = it->next) { this->declaration(it->value); + + // Check for '...' in last parameter declarator for variadic template + // (i.e. template<class ... T> void foo(T ... args);) + // those last dots are part of parameter declarator, not the parameter declaration clause + if (! it->next + && it->value->declarator != nullptr + && it->value->declarator->core_declarator != nullptr){ + DeclaratorIdAST* declId = it->value->declarator->core_declarator->asDeclaratorId(); + if (declId && declId->dot_dot_dot_token != 0){ + fun->setVariadic(true); + fun->setVariadicTemplate(true); + } + } } if (ast->dot_dot_dot_token) @@ -2767,10 +2780,27 @@ bool Bind::visit(DestructorNameAST *ast) bool Bind::visit(TemplateIdAST *ast) { // collect the template parameters - std::vector<FullySpecifiedType> templateArguments; + std::vector<TemplateArgument> templateArguments; for (ExpressionListAST *it = ast->template_argument_list; it; it = it->next) { ExpressionTy value = this->expression(it->value); - templateArguments.push_back(value); + if (value.isValid()) { + templateArguments.emplace_back(value); + } else { + // special case for numeric values + if (it->value->asNumericLiteral()) { + templateArguments + .emplace_back(value, + tokenAt(it->value->asNumericLiteral()->literal_token).number); + } else if (it->value->asBoolLiteral()) { + templateArguments + .emplace_back(value, tokenAt(it->value->asBoolLiteral()->literal_token).number); + } else { + // fall back to non-valid type in templateArguments + // for ast->template_argument_list and templateArguments sizes match + // TODO support other literals/expressions as default arguments + templateArguments.emplace_back(value); + } + } } const Identifier *id = identifier(ast->identifier_token); @@ -3014,6 +3044,22 @@ bool Bind::visit(GnuAttributeSpecifierAST *ast) return false; } +bool Bind::visit(MsvcDeclspecSpecifierAST *ast) +{ + for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) { + this->attribute(it->value); + } + return false; +} + +bool Bind::visit(StdAttributeSpecifierAST *ast) +{ + for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) { + this->attribute(it->value); + } + return false; +} + bool Bind::visit(TypeofSpecifierAST *ast) { ExpressionTy expression = this->expression(ast->expression); diff --git a/src/libs/3rdparty/cplusplus/Bind.h b/src/libs/3rdparty/cplusplus/Bind.h index ddeb46532e..f3f83f7088 100644 --- a/src/libs/3rdparty/cplusplus/Bind.h +++ b/src/libs/3rdparty/cplusplus/Bind.h @@ -253,6 +253,8 @@ protected: virtual bool visit(SimpleSpecifierAST *ast); virtual bool visit(AlignmentSpecifierAST *ast); virtual bool visit(GnuAttributeSpecifierAST *ast); + virtual bool visit(MsvcDeclspecSpecifierAST *ast); + virtual bool visit(StdAttributeSpecifierAST *ast); virtual bool visit(TypeofSpecifierAST *ast); virtual bool visit(DecltypeSpecifierAST *ast); virtual bool visit(ClassSpecifierAST *ast); diff --git a/src/libs/3rdparty/cplusplus/Control.cpp b/src/libs/3rdparty/cplusplus/Control.cpp index 2bbe00c293..ff966ee332 100644 --- a/src/libs/3rdparty/cplusplus/Control.cpp +++ b/src/libs/3rdparty/cplusplus/Control.cpp @@ -629,7 +629,7 @@ const NumericLiteral *Control::numericLiteral(const char *chars) const TemplateNameId *Control::templateNameId(const Identifier *id, bool isSpecialization, - const FullySpecifiedType *const args, + const TemplateArgument *const args, int argv) { return d->findOrInsertTemplateNameId(id, isSpecialization, args, args + argv); diff --git a/src/libs/3rdparty/cplusplus/Control.h b/src/libs/3rdparty/cplusplus/Control.h index 348864a402..5556c41fdd 100644 --- a/src/libs/3rdparty/cplusplus/Control.h +++ b/src/libs/3rdparty/cplusplus/Control.h @@ -54,7 +54,7 @@ public: /// Returns the canonical template name id. const TemplateNameId *templateNameId(const Identifier *id, bool isSpecialization, - const FullySpecifiedType *const args = nullptr, + const TemplateArgument *const args = nullptr, int argc = 0); /// Returns the canonical destructor name id. diff --git a/src/libs/3rdparty/cplusplus/Keywords.cpp b/src/libs/3rdparty/cplusplus/Keywords.cpp index 9fb6185c6f..1637333b42 100644 --- a/src/libs/3rdparty/cplusplus/Keywords.cpp +++ b/src/libs/3rdparty/cplusplus/Keywords.cpp @@ -1079,6 +1079,23 @@ static inline int classify9(const char *s, LanguageFeatures features) } } } + else if (s[1] == 'd') { + if (s[2] == 'e') { + if (s[3] == 'c') { + if (s[4] == 'l') { + if (s[5] == 's') { + if (s[6] == 'p') { + if (s[7] == 'e') { + if (s[8] == 'c') { + return T__DECLSPEC; + } + } + } + } + } + } + } + } } else if (features.cxx11Enabled && s[0] == 'c') { if (s[1] == 'o') { @@ -1178,11 +1195,20 @@ static inline int classify10(const char *s, LanguageFeatures features) { if (s[0] == '_') { if (s[1] == '_') { - if (features.cxxEnabled && s[2] == 'd') { + if (s[2] == 'd') { if (s[3] == 'e') { if (s[4] == 'c') { if (s[5] == 'l') { - if (s[6] == 't') { + if (s[6] == 's') { + if (s[7] == 'p') { + if (s[8] == 'e') { + if (s[9] == 'c') { + return T___DECLSPEC; + } + } + } + } + else if (features.cxxEnabled && s[6] == 't') { if (s[7] == 'y') { if (s[8] == 'p') { if (s[9] == 'e') { diff --git a/src/libs/3rdparty/cplusplus/Keywords.kwgen b/src/libs/3rdparty/cplusplus/Keywords.kwgen index 26c8bcd81b..36300a8776 100644 --- a/src/libs/3rdparty/cplusplus/Keywords.kwgen +++ b/src/libs/3rdparty/cplusplus/Keywords.kwgen @@ -37,6 +37,8 @@ __asm__ __attribute __attribute__ __alignof__ +_declspec +__declspec __const __const__ __inline diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index 89e0ce512d..e0fee4feac 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -1052,10 +1052,17 @@ void Lexer::scanIdentifier(Token *tok, unsigned extraProcessedChars) yyinp(); } int yylen = _currentChar - yytext; - if (f._scanKeywords) + if (f._scanKeywords) { tok->f.kind = classify(yytext, yylen, _languageFeatures); - else + + if (tok->f.kind == T_FALSE || tok->f.kind == T_TRUE) { + if (control()) { + tok->number = control()->numericLiteral(yytext, yylen); + } + } + } else { tok->f.kind = T_IDENTIFIER; + } if (tok->f.kind == T_IDENTIFIER) { tok->f.kind = classifyOperator(yytext, yylen); diff --git a/src/libs/3rdparty/cplusplus/Matcher.cpp b/src/libs/3rdparty/cplusplus/Matcher.cpp index 8ef26017c6..298a24d79b 100644 --- a/src/libs/3rdparty/cplusplus/Matcher.cpp +++ b/src/libs/3rdparty/cplusplus/Matcher.cpp @@ -324,8 +324,8 @@ bool Matcher::match(const TemplateNameId *name, const TemplateNameId *otherName) if (name->templateArgumentCount() != otherName->templateArgumentCount()) return false; for (unsigned i = 0, ei = name->templateArgumentCount(); i != ei; ++i) { - const FullySpecifiedType &l = name->templateArgumentAt(i); - const FullySpecifiedType &r = otherName->templateArgumentAt(i); + const TemplateArgument &l = name->templateArgumentAt(i); + const TemplateArgument &r = otherName->templateArgumentAt(i); if (! l.match(r, this)) return false; } diff --git a/src/libs/3rdparty/cplusplus/Names.cpp b/src/libs/3rdparty/cplusplus/Names.cpp index 6bcc988f37..dc77d47c0b 100644 --- a/src/libs/3rdparty/cplusplus/Names.cpp +++ b/src/libs/3rdparty/cplusplus/Names.cpp @@ -93,10 +93,17 @@ bool TemplateNameId::match0(const Name *otherName, Matcher *matcher) const const Identifier *TemplateNameId::identifier() const { return _identifier; } +bool TemplateArgument::match(const TemplateArgument &otherTy, Matcher *matcher) const +{ + if (_numericLiteral != otherTy._numericLiteral) + return false; + return type().match(otherTy.type(), matcher); +} + int TemplateNameId::templateArgumentCount() const { return int(_templateArguments.size()); } -const FullySpecifiedType &TemplateNameId::templateArgumentAt(int index) const +const TemplateArgument &TemplateNameId::templateArgumentAt(int index) const { return _templateArguments[index]; } bool TemplateNameId::Compare::operator()(const TemplateNameId *name, diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h index cea93911c6..b615394438 100644 --- a/src/libs/3rdparty/cplusplus/Names.h +++ b/src/libs/3rdparty/cplusplus/Names.h @@ -73,6 +73,51 @@ private: const Name *_name; }; +class CPLUSPLUS_EXPORT TemplateArgument +{ +public: + TemplateArgument() + : _expressionTy(nullptr) + , _numericLiteral(nullptr) + {} + + TemplateArgument(const FullySpecifiedType &type, const NumericLiteral *numericLiteral = nullptr) + : _expressionTy(type) + , _numericLiteral(numericLiteral) + {} + + bool hasType() const { return _expressionTy.isValid(); } + + bool hasNumericLiteral() const { return _numericLiteral != nullptr; } + + const FullySpecifiedType &type() const { return _expressionTy; } + FullySpecifiedType &type() { return _expressionTy; } + + const NumericLiteral *numericLiteral() const { return _numericLiteral; } + + bool operator==(const TemplateArgument &other) const + { + return _expressionTy == other._expressionTy && _numericLiteral == other._numericLiteral; + } + bool operator!=(const TemplateArgument &other) const + { + return _expressionTy != other._expressionTy || _numericLiteral != other._numericLiteral; + } + bool operator<(const TemplateArgument &other) const + { + if (_expressionTy == other._expressionTy) { + return _numericLiteral < other._numericLiteral; + } + return _expressionTy < other._expressionTy; + } + + bool match(const TemplateArgument &otherTy, Matcher *matcher = nullptr) const; + +private: + FullySpecifiedType _expressionTy; + const NumericLiteral *_numericLiteral = nullptr; +}; + class CPLUSPLUS_EXPORT TemplateNameId: public Name { public: @@ -89,12 +134,12 @@ public: // ### find a better name int templateArgumentCount() const; - const FullySpecifiedType &templateArgumentAt(int index) const; + const TemplateArgument &templateArgumentAt(int index) const; virtual const TemplateNameId *asTemplateNameId() const { return this; } - typedef std::vector<FullySpecifiedType>::const_iterator TemplateArgumentIterator; + typedef std::vector<TemplateArgument>::const_iterator TemplateArgumentIterator; TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); } TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); } @@ -111,7 +156,7 @@ protected: private: const Identifier *_identifier; - std::vector<FullySpecifiedType> _templateArguments; + std::vector<TemplateArgument> _templateArguments; // now TemplateNameId can be a specialization or an instantiation bool _isSpecialization; }; diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index fd7b963a87..28dddc507e 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -770,6 +770,18 @@ bool Parser::parseDeclaration(DeclarationAST *&node) else if (LA() == T_AT_PROPERTY) return parseObjCPropertyDeclaration(node, attributes); rewind(start); + } else if (LA() == T___DECLSPEC) { + const int start = cursor(); + SpecifierListAST *attributes = nullptr, **attr = &attributes; + while (parseMsvcDeclspecSpecifier(*attr)) + attr = &(*attr)->next; + rewind(start); + } else if (lookAtStdAttribute()) { + const int start = cursor(); + SpecifierListAST *attributes = nullptr, **attr = &attributes; + while (parseStdAttributeSpecifier(*attr)) + attr = &(*attr)->next; + rewind(start); } if (LA() == T_EXTERN && LA(2) == T_TEMPLATE) @@ -3761,6 +3773,11 @@ bool Parser::parseIfStatement(StatementAST *&node) if (LA() == T_IF) { IfStatementAST *ast = new (_pool) IfStatementAST; ast->if_token = consumeToken(); + if (LA() == T_CONSTEXPR) { + // "if constexpr" added in cxx17, but we don't check cxx version here + // because msvc 2019 compiler uses "if constexpr" in headers despite cxx version set for the project + ast->constexpr_token = consumeToken(); + } match(T_LPAREN, &ast->lparen_token); parseCondition(ast->condition); match(T_RPAREN, &ast->rparen_token); @@ -3961,6 +3978,8 @@ bool Parser::lookAtBuiltinTypeSpecifier() const // [gcc] extensions case T___TYPEOF__: case T___ATTRIBUTE__: + // [msvc] extensions + case T___DECLSPEC: return true; default: return false; @@ -4020,8 +4039,22 @@ bool Parser::parseAttributeSpecifier(SpecifierListAST *&attribute_list) attr_ptr = &(*attr_ptr)->next; } return true; + case T___DECLSPEC: + while (LA() == T___DECLSPEC) { + parseMsvcDeclspecSpecifier(*attr_ptr); + attr_ptr = &(*attr_ptr)->next; + } + return true; default: - return false; + { + bool foundAttributes = false; + while (lookAtStdAttribute()) { + parseStdAttributeSpecifier(*attr_ptr); + attr_ptr = &(*attr_ptr)->next; + foundAttributes = true; + } + return foundAttributes; + } } } @@ -4078,11 +4111,46 @@ bool Parser::parseGnuAttributeList(GnuAttributeListAST *&node) return true; } +bool Parser::parseMsvcDeclspecSpecifier(SpecifierListAST *&node) +{ + DEBUG_THIS_RULE(); + if (LA() != T___DECLSPEC) + return false; + + MsvcDeclspecSpecifierAST *ast = new (_pool) MsvcDeclspecSpecifierAST; + ast->attribute_token = consumeToken(); + match(T_LPAREN, &ast->lparen_token); + parseGnuAttributeList(ast->attribute_list); + match(T_RPAREN, &ast->rparen_token); + node = new (_pool) SpecifierListAST(ast); + return true; +} + +bool Parser::parseStdAttributeSpecifier(SpecifierListAST *&node) +{ + DEBUG_THIS_RULE(); + if (!lookAtStdAttribute()) + return false; + + StdAttributeSpecifierAST *ast = new (_pool) StdAttributeSpecifierAST; + match(T_LBRACKET, &ast->first_lbracket_token); + match(T_LBRACKET, &ast->second_lbracket_token); + parseGnuAttributeList(ast->attribute_list); + match(T_RBRACKET, &ast->first_rbracket_token); + match(T_RBRACKET, &ast->second_rbracket_token); + node = new (_pool) SpecifierListAST(ast); + return true; +} + bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node) { DEBUG_THIS_RULE(); if (LA() == T___ATTRIBUTE__) { return parseGnuAttributeSpecifier(node); + } else if (LA() == T___DECLSPEC) { + return parseMsvcDeclspecSpecifier(node); + } else if (lookAtStdAttribute()) { + return parseStdAttributeSpecifier(node); } else if (LA() == T___TYPEOF__) { TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST; ast->typeof_token = consumeToken(); @@ -5748,6 +5816,11 @@ bool Parser::parseNoExceptOperatorExpression(ExpressionAST *&node) return false; } +bool Parser::lookAtStdAttribute() const +{ + return _languageFeatures.cxx11Enabled && LA() == T_LBRACKET && LA(2) == T_LBRACKET; +} + bool Parser::lookAtObjCSelector() const { switch (LA()) { @@ -6797,6 +6870,8 @@ bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node) SpecifierListAST **attr = &ast->attributes; while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; + while (parseStdAttributeSpecifier(*attr)) + attr = &(*attr)->next; if (LA() == T_MUTABLE) ast->mutable_token = consumeToken(); @@ -6821,6 +6896,8 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node) SpecifierListAST **attr = &ast->attributes; while (parseGnuAttributeSpecifier(*attr)) attr = &(*attr)->next; + while (parseStdAttributeSpecifier(*attr)) + attr = &(*attr)->next; parseTrailingTypeSpecifierSeq(ast->type_specifier_list); parseAbstractDeclarator(ast->declarator, ast->type_specifier_list); diff --git a/src/libs/3rdparty/cplusplus/Parser.h b/src/libs/3rdparty/cplusplus/Parser.h index 750c590b40..b8efe2765e 100644 --- a/src/libs/3rdparty/cplusplus/Parser.h +++ b/src/libs/3rdparty/cplusplus/Parser.h @@ -170,6 +170,9 @@ public: bool parseGnuAttributeSpecifier(SpecifierListAST *&node); bool parseGnuAttributeList(GnuAttributeListAST *&node); + bool parseMsvcDeclspecSpecifier(SpecifierListAST *&node); + bool parseStdAttributeSpecifier(SpecifierListAST *&node); + bool parseDeclSpecifierSeq(SpecifierListAST *&node, bool noStorageSpecifiers = false, bool onlySimpleTypeSpecifiers = false); @@ -247,6 +250,8 @@ public: bool peekAtObjCContextKeyword(int kind); bool parseObjCContextKeyword(int kind, int &in_token); + bool lookAtStdAttribute() const; + bool lookAtObjCSelector() const; // c99 diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp index aba1be3494..22f355dce4 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.cpp +++ b/src/libs/3rdparty/cplusplus/Symbols.cpp @@ -191,7 +191,7 @@ Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original) if (const TemplateNameId * templateNameId = namedType->name()->asTemplateNameId()) { if (templateNameId->templateArgumentCount()) { - newType = clone->type(templateNameId->templateArgumentAt(0), nullptr); + newType = clone->type(templateNameId->templateArgumentAt(0).type(), nullptr); newType = FullySpecifiedType(clone->control()->pointerType(newType)); } } @@ -469,6 +469,12 @@ bool Function::isVariadic() const void Function::setVariadic(bool isVariadic) { f._isVariadic = isVariadic; } +bool Function::isVariadicTemplate() const +{ return f._isVariadicTemplate; } + +void Function::setVariadicTemplate(bool isVariadicTemplate) +{ f._isVariadicTemplate = isVariadicTemplate; } + bool Function::isConst() const { return f._isConst; } @@ -523,6 +529,9 @@ bool Function::maybeValidPrototype(int actualArgumentCount) const break; } + if (isVariadicTemplate()) + --minNumberArguments; + if (actualArgumentCount < minNumberArguments) { // not enough arguments. return false; diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h index 71a076ac80..a5e833696c 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.h +++ b/src/libs/3rdparty/cplusplus/Symbols.h @@ -346,6 +346,9 @@ public: bool isVariadic() const; void setVariadic(bool isVariadic); + bool isVariadicTemplate() const; + void setVariadicTemplate(bool isVariadicTemplate); + bool isConst() const; void setConst(bool isConst); @@ -397,6 +400,7 @@ private: unsigned _isOverride: 1; unsigned _isFinal: 1; unsigned _isVariadic: 1; + unsigned _isVariadicTemplate: 1; unsigned _isPureVirtual: 1; unsigned _isConst: 1; unsigned _isVolatile: 1; diff --git a/src/libs/3rdparty/cplusplus/Templates.cpp b/src/libs/3rdparty/cplusplus/Templates.cpp index 75ee4e95fa..92e5ab14fc 100644 --- a/src/libs/3rdparty/cplusplus/Templates.cpp +++ b/src/libs/3rdparty/cplusplus/Templates.cpp @@ -439,9 +439,9 @@ void CloneName::visit(const AnonymousNameId *name) void CloneName::visit(const TemplateNameId *name) { - std::vector<FullySpecifiedType> args(name->templateArgumentCount()); + std::vector<TemplateArgument> args(name->templateArgumentCount()); for (int i = 0; i < int(args.size()); ++i) - args[i] = _clone->type(name->templateArgumentAt(i), _subst); + args[i].type() = _clone->type(name->templateArgumentAt(i).type(), _subst); if (args.empty()) _name = _control->templateNameId(_clone->identifier(name->identifier()), name->isSpecialization()); else diff --git a/src/libs/3rdparty/cplusplus/Token.cpp b/src/libs/3rdparty/cplusplus/Token.cpp index 0159b1ed7d..1d9127b2dd 100644 --- a/src/libs/3rdparty/cplusplus/Token.cpp +++ b/src/libs/3rdparty/cplusplus/Token.cpp @@ -177,6 +177,9 @@ const char *token_names[] = { ("__thread"), ("__typeof__"), + // msvc + ("__declspec"), + // objc @keywords ("@catch"), ("@class"), diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index 44efde0553..f545978669 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -186,6 +186,8 @@ enum Kind { T___THREAD, T___TYPEOF__, + T___DECLSPEC, + // obj c++ @ keywords T_FIRST_OBJC_AT_KEYWORD, @@ -298,6 +300,7 @@ enum Kind { T_FOREACH = T_Q_FOREACH, T_SIGNALS = T_Q_SIGNALS, T_Q_OVERRIDE = T_Q_PROPERTY, + T__DECLSPEC = T___DECLSPEC, }; class CPLUSPLUS_EXPORT Token |