forked from qt-creator/qt-creator
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>
This commit is contained in:
44
src/libs/3rdparty/cplusplus/AST.cpp
vendored
44
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -73,6 +73,16 @@ int GnuAttributeSpecifierAST::firstToken() const
|
|||||||
return attribute_token;
|
return attribute_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MsvcDeclspecSpecifierAST::firstToken() const
|
||||||
|
{
|
||||||
|
return attribute_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StdAttributeSpecifierAST::firstToken() const
|
||||||
|
{
|
||||||
|
return first_lbracket_token;
|
||||||
|
}
|
||||||
|
|
||||||
int BaseSpecifierAST::firstToken() const
|
int BaseSpecifierAST::firstToken() const
|
||||||
{
|
{
|
||||||
if (virtual_token && access_specifier_token)
|
if (virtual_token && access_specifier_token)
|
||||||
@@ -1524,6 +1534,8 @@ int IfStatementAST::firstToken() const
|
|||||||
{
|
{
|
||||||
if (if_token)
|
if (if_token)
|
||||||
return if_token;
|
return if_token;
|
||||||
|
if (constexpr_token)
|
||||||
|
return constexpr_token;
|
||||||
if (lparen_token)
|
if (lparen_token)
|
||||||
return lparen_token;
|
return lparen_token;
|
||||||
if (condition)
|
if (condition)
|
||||||
@@ -1560,6 +1572,8 @@ int IfStatementAST::lastToken() const
|
|||||||
return candidate;
|
return candidate;
|
||||||
if (lparen_token)
|
if (lparen_token)
|
||||||
return lparen_token + 1;
|
return lparen_token + 1;
|
||||||
|
if (constexpr_token)
|
||||||
|
return constexpr_token + 1;
|
||||||
if (if_token)
|
if (if_token)
|
||||||
return if_token + 1;
|
return if_token + 1;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -4214,6 +4228,36 @@ int GnuAttributeSpecifierAST::lastToken() const
|
|||||||
return 1;
|
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 */
|
/** \generated */
|
||||||
int PointerLiteralAST::firstToken() const
|
int PointerLiteralAST::firstToken() const
|
||||||
{
|
{
|
||||||
|
|||||||
46
src/libs/3rdparty/cplusplus/AST.h
vendored
46
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -195,6 +195,7 @@ public:
|
|||||||
virtual LinkageSpecificationAST *asLinkageSpecification() { return nullptr; }
|
virtual LinkageSpecificationAST *asLinkageSpecification() { return nullptr; }
|
||||||
virtual MemInitializerAST *asMemInitializer() { return nullptr; }
|
virtual MemInitializerAST *asMemInitializer() { return nullptr; }
|
||||||
virtual MemberAccessAST *asMemberAccess() { return nullptr; }
|
virtual MemberAccessAST *asMemberAccess() { return nullptr; }
|
||||||
|
virtual MsvcDeclspecSpecifierAST *asMsvcDeclspecSpecifier() { return nullptr; }
|
||||||
virtual NameAST *asName() { return nullptr; }
|
virtual NameAST *asName() { return nullptr; }
|
||||||
virtual NamedTypeSpecifierAST *asNamedTypeSpecifier() { return nullptr; }
|
virtual NamedTypeSpecifierAST *asNamedTypeSpecifier() { return nullptr; }
|
||||||
virtual NamespaceAST *asNamespace() { return nullptr; }
|
virtual NamespaceAST *asNamespace() { return nullptr; }
|
||||||
@@ -265,6 +266,7 @@ public:
|
|||||||
virtual SpecifierAST *asSpecifier() { return nullptr; }
|
virtual SpecifierAST *asSpecifier() { return nullptr; }
|
||||||
virtual StatementAST *asStatement() { return nullptr; }
|
virtual StatementAST *asStatement() { return nullptr; }
|
||||||
virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return nullptr; }
|
virtual StaticAssertDeclarationAST *asStaticAssertDeclaration() { return nullptr; }
|
||||||
|
virtual StdAttributeSpecifierAST *asStdAttributeSpecifier() { return nullptr; }
|
||||||
virtual StringLiteralAST *asStringLiteral() { return nullptr; }
|
virtual StringLiteralAST *asStringLiteral() { return nullptr; }
|
||||||
virtual SwitchStatementAST *asSwitchStatement() { return nullptr; }
|
virtual SwitchStatementAST *asSwitchStatement() { return nullptr; }
|
||||||
virtual TemplateDeclarationAST *asTemplateDeclaration() { return nullptr; }
|
virtual TemplateDeclarationAST *asTemplateDeclaration() { return nullptr; }
|
||||||
@@ -475,6 +477,49 @@ protected:
|
|||||||
virtual bool match0(AST *, ASTMatcher *);
|
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
|
class CPLUSPLUS_EXPORT GnuAttributeAST: public AST
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1610,6 +1655,7 @@ class CPLUSPLUS_EXPORT IfStatementAST: public StatementAST
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int if_token = 0;
|
int if_token = 0;
|
||||||
|
int constexpr_token = 0;
|
||||||
int lparen_token = 0;
|
int lparen_token = 0;
|
||||||
ExpressionAST *condition = nullptr;
|
ExpressionAST *condition = nullptr;
|
||||||
int rparen_token = 0;
|
int rparen_token = 0;
|
||||||
|
|||||||
26
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
26
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -81,6 +81,31 @@ GnuAttributeSpecifierAST *GnuAttributeSpecifierAST::clone(MemoryPool *pool) cons
|
|||||||
return ast;
|
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 *GnuAttributeAST::clone(MemoryPool *pool) const
|
||||||
{
|
{
|
||||||
GnuAttributeAST *ast = new (pool) GnuAttributeAST;
|
GnuAttributeAST *ast = new (pool) GnuAttributeAST;
|
||||||
@@ -730,6 +755,7 @@ IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const
|
|||||||
{
|
{
|
||||||
IfStatementAST *ast = new (pool) IfStatementAST;
|
IfStatementAST *ast = new (pool) IfStatementAST;
|
||||||
ast->if_token = if_token;
|
ast->if_token = if_token;
|
||||||
|
ast->constexpr_token = constexpr_token;
|
||||||
ast->lparen_token = lparen_token;
|
ast->lparen_token = lparen_token;
|
||||||
if (condition)
|
if (condition)
|
||||||
ast->condition = condition->clone(pool);
|
ast->condition = condition->clone(pool);
|
||||||
|
|||||||
16
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
16
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -72,6 +72,22 @@ bool GnuAttributeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
|
|||||||
return false;
|
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)
|
bool GnuAttributeAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||||
{
|
{
|
||||||
if (GnuAttributeAST *_other = pattern->asGnuAttribute())
|
if (GnuAttributeAST *_other = pattern->asGnuAttribute())
|
||||||
|
|||||||
42
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
42
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -117,6 +117,46 @@ bool ASTMatcher::match(GnuAttributeSpecifierAST *node, GnuAttributeSpecifierAST
|
|||||||
return true;
|
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)
|
bool ASTMatcher::match(GnuAttributeAST *node, GnuAttributeAST *pattern)
|
||||||
{
|
{
|
||||||
(void) node;
|
(void) node;
|
||||||
@@ -1246,6 +1286,8 @@ bool ASTMatcher::match(IfStatementAST *node, IfStatementAST *pattern)
|
|||||||
|
|
||||||
pattern->if_token = node->if_token;
|
pattern->if_token = node->if_token;
|
||||||
|
|
||||||
|
pattern->constexpr_token = node->constexpr_token;
|
||||||
|
|
||||||
pattern->lparen_token = node->lparen_token;
|
pattern->lparen_token = node->lparen_token;
|
||||||
|
|
||||||
if (! pattern->condition)
|
if (! pattern->condition)
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
2
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -96,6 +96,7 @@ public:
|
|||||||
virtual bool match(LinkageSpecificationAST *node, LinkageSpecificationAST *pattern);
|
virtual bool match(LinkageSpecificationAST *node, LinkageSpecificationAST *pattern);
|
||||||
virtual bool match(MemInitializerAST *node, MemInitializerAST *pattern);
|
virtual bool match(MemInitializerAST *node, MemInitializerAST *pattern);
|
||||||
virtual bool match(MemberAccessAST *node, MemberAccessAST *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(NamedTypeSpecifierAST *node, NamedTypeSpecifierAST *pattern);
|
||||||
virtual bool match(NamespaceAST *node, NamespaceAST *pattern);
|
virtual bool match(NamespaceAST *node, NamespaceAST *pattern);
|
||||||
virtual bool match(NamespaceAliasDefinitionAST *node, NamespaceAliasDefinitionAST *pattern);
|
virtual bool match(NamespaceAliasDefinitionAST *node, NamespaceAliasDefinitionAST *pattern);
|
||||||
@@ -160,6 +161,7 @@ public:
|
|||||||
virtual bool match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern);
|
virtual bool match(SimpleSpecifierAST *node, SimpleSpecifierAST *pattern);
|
||||||
virtual bool match(SizeofExpressionAST *node, SizeofExpressionAST *pattern);
|
virtual bool match(SizeofExpressionAST *node, SizeofExpressionAST *pattern);
|
||||||
virtual bool match(StaticAssertDeclarationAST *node, StaticAssertDeclarationAST *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(StringLiteralAST *node, StringLiteralAST *pattern);
|
||||||
virtual bool match(SwitchStatementAST *node, SwitchStatementAST *pattern);
|
virtual bool match(SwitchStatementAST *node, SwitchStatementAST *pattern);
|
||||||
virtual bool match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern);
|
virtual bool match(TemplateDeclarationAST *node, TemplateDeclarationAST *pattern);
|
||||||
|
|||||||
14
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
14
src/libs/3rdparty/cplusplus/ASTPatternBuilder.h
vendored
@@ -76,6 +76,20 @@ public:
|
|||||||
return ast;
|
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 *GnuAttribute(ExpressionListAST *expression_list = nullptr)
|
||||||
{
|
{
|
||||||
GnuAttributeAST *ast = new (&pool) GnuAttributeAST;
|
GnuAttributeAST *ast = new (&pool) GnuAttributeAST;
|
||||||
|
|||||||
16
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
16
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -70,6 +70,22 @@ void GnuAttributeSpecifierAST::accept0(ASTVisitor *visitor)
|
|||||||
visitor->endVisit(this);
|
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)
|
void GnuAttributeAST::accept0(ASTVisitor *visitor)
|
||||||
{
|
{
|
||||||
if (visitor->visit(this)) {
|
if (visitor->visit(this)) {
|
||||||
|
|||||||
4
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
4
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -138,6 +138,7 @@ public:
|
|||||||
virtual bool visit(LinkageSpecificationAST *) { return true; }
|
virtual bool visit(LinkageSpecificationAST *) { return true; }
|
||||||
virtual bool visit(MemInitializerAST *) { return true; }
|
virtual bool visit(MemInitializerAST *) { return true; }
|
||||||
virtual bool visit(MemberAccessAST *) { return true; }
|
virtual bool visit(MemberAccessAST *) { return true; }
|
||||||
|
virtual bool visit(MsvcDeclspecSpecifierAST *) { return true; }
|
||||||
virtual bool visit(NamedTypeSpecifierAST *) { return true; }
|
virtual bool visit(NamedTypeSpecifierAST *) { return true; }
|
||||||
virtual bool visit(NamespaceAST *) { return true; }
|
virtual bool visit(NamespaceAST *) { return true; }
|
||||||
virtual bool visit(NamespaceAliasDefinitionAST *) { return true; }
|
virtual bool visit(NamespaceAliasDefinitionAST *) { return true; }
|
||||||
@@ -202,6 +203,7 @@ public:
|
|||||||
virtual bool visit(SimpleSpecifierAST *) { return true; }
|
virtual bool visit(SimpleSpecifierAST *) { return true; }
|
||||||
virtual bool visit(SizeofExpressionAST *) { return true; }
|
virtual bool visit(SizeofExpressionAST *) { return true; }
|
||||||
virtual bool visit(StaticAssertDeclarationAST *) { return true; }
|
virtual bool visit(StaticAssertDeclarationAST *) { return true; }
|
||||||
|
virtual bool visit(StdAttributeSpecifierAST *) { return true; }
|
||||||
virtual bool visit(StringLiteralAST *) { return true; }
|
virtual bool visit(StringLiteralAST *) { return true; }
|
||||||
virtual bool visit(SwitchStatementAST *) { return true; }
|
virtual bool visit(SwitchStatementAST *) { return true; }
|
||||||
virtual bool visit(TemplateDeclarationAST *) { return true; }
|
virtual bool visit(TemplateDeclarationAST *) { return true; }
|
||||||
@@ -289,6 +291,7 @@ public:
|
|||||||
virtual void endVisit(LinkageSpecificationAST *) {}
|
virtual void endVisit(LinkageSpecificationAST *) {}
|
||||||
virtual void endVisit(MemInitializerAST *) {}
|
virtual void endVisit(MemInitializerAST *) {}
|
||||||
virtual void endVisit(MemberAccessAST *) {}
|
virtual void endVisit(MemberAccessAST *) {}
|
||||||
|
virtual void endVisit(MsvcDeclspecSpecifierAST *) {}
|
||||||
virtual void endVisit(NamedTypeSpecifierAST *) {}
|
virtual void endVisit(NamedTypeSpecifierAST *) {}
|
||||||
virtual void endVisit(NamespaceAST *) {}
|
virtual void endVisit(NamespaceAST *) {}
|
||||||
virtual void endVisit(NamespaceAliasDefinitionAST *) {}
|
virtual void endVisit(NamespaceAliasDefinitionAST *) {}
|
||||||
@@ -353,6 +356,7 @@ public:
|
|||||||
virtual void endVisit(SimpleSpecifierAST *) {}
|
virtual void endVisit(SimpleSpecifierAST *) {}
|
||||||
virtual void endVisit(SizeofExpressionAST *) {}
|
virtual void endVisit(SizeofExpressionAST *) {}
|
||||||
virtual void endVisit(StaticAssertDeclarationAST *) {}
|
virtual void endVisit(StaticAssertDeclarationAST *) {}
|
||||||
|
virtual void endVisit(StdAttributeSpecifierAST *) {}
|
||||||
virtual void endVisit(StringLiteralAST *) {}
|
virtual void endVisit(StringLiteralAST *) {}
|
||||||
virtual void endVisit(SwitchStatementAST *) {}
|
virtual void endVisit(SwitchStatementAST *) {}
|
||||||
virtual void endVisit(TemplateDeclarationAST *) {}
|
virtual void endVisit(TemplateDeclarationAST *) {}
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
2
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -102,6 +102,7 @@ class LinkageBodyAST;
|
|||||||
class LinkageSpecificationAST;
|
class LinkageSpecificationAST;
|
||||||
class MemInitializerAST;
|
class MemInitializerAST;
|
||||||
class MemberAccessAST;
|
class MemberAccessAST;
|
||||||
|
class MsvcDeclspecSpecifierAST;
|
||||||
class NameAST;
|
class NameAST;
|
||||||
class NamedTypeSpecifierAST;
|
class NamedTypeSpecifierAST;
|
||||||
class NamespaceAST;
|
class NamespaceAST;
|
||||||
@@ -172,6 +173,7 @@ class SizeofExpressionAST;
|
|||||||
class SpecifierAST;
|
class SpecifierAST;
|
||||||
class StatementAST;
|
class StatementAST;
|
||||||
class StaticAssertDeclarationAST;
|
class StaticAssertDeclarationAST;
|
||||||
|
class StdAttributeSpecifierAST;
|
||||||
class StringLiteralAST;
|
class StringLiteralAST;
|
||||||
class SwitchStatementAST;
|
class SwitchStatementAST;
|
||||||
class TemplateDeclarationAST;
|
class TemplateDeclarationAST;
|
||||||
|
|||||||
50
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
50
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -918,6 +918,19 @@ void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lp
|
|||||||
|
|
||||||
for (ParameterDeclarationListAST *it = ast->parameter_declaration_list; it; it = it->next) {
|
for (ParameterDeclarationListAST *it = ast->parameter_declaration_list; it; it = it->next) {
|
||||||
this->declaration(it->value);
|
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)
|
if (ast->dot_dot_dot_token)
|
||||||
@@ -2767,10 +2780,27 @@ bool Bind::visit(DestructorNameAST *ast)
|
|||||||
bool Bind::visit(TemplateIdAST *ast)
|
bool Bind::visit(TemplateIdAST *ast)
|
||||||
{
|
{
|
||||||
// collect the template parameters
|
// collect the template parameters
|
||||||
std::vector<FullySpecifiedType> templateArguments;
|
std::vector<TemplateArgument> templateArguments;
|
||||||
for (ExpressionListAST *it = ast->template_argument_list; it; it = it->next) {
|
for (ExpressionListAST *it = ast->template_argument_list; it; it = it->next) {
|
||||||
ExpressionTy value = this->expression(it->value);
|
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);
|
const Identifier *id = identifier(ast->identifier_token);
|
||||||
@@ -3014,6 +3044,22 @@ bool Bind::visit(GnuAttributeSpecifierAST *ast)
|
|||||||
return false;
|
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)
|
bool Bind::visit(TypeofSpecifierAST *ast)
|
||||||
{
|
{
|
||||||
ExpressionTy expression = this->expression(ast->expression);
|
ExpressionTy expression = this->expression(ast->expression);
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/Bind.h
vendored
2
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -253,6 +253,8 @@ protected:
|
|||||||
virtual bool visit(SimpleSpecifierAST *ast);
|
virtual bool visit(SimpleSpecifierAST *ast);
|
||||||
virtual bool visit(AlignmentSpecifierAST *ast);
|
virtual bool visit(AlignmentSpecifierAST *ast);
|
||||||
virtual bool visit(GnuAttributeSpecifierAST *ast);
|
virtual bool visit(GnuAttributeSpecifierAST *ast);
|
||||||
|
virtual bool visit(MsvcDeclspecSpecifierAST *ast);
|
||||||
|
virtual bool visit(StdAttributeSpecifierAST *ast);
|
||||||
virtual bool visit(TypeofSpecifierAST *ast);
|
virtual bool visit(TypeofSpecifierAST *ast);
|
||||||
virtual bool visit(DecltypeSpecifierAST *ast);
|
virtual bool visit(DecltypeSpecifierAST *ast);
|
||||||
virtual bool visit(ClassSpecifierAST *ast);
|
virtual bool visit(ClassSpecifierAST *ast);
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/Control.cpp
vendored
2
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -629,7 +629,7 @@ const NumericLiteral *Control::numericLiteral(const char *chars)
|
|||||||
|
|
||||||
const TemplateNameId *Control::templateNameId(const Identifier *id,
|
const TemplateNameId *Control::templateNameId(const Identifier *id,
|
||||||
bool isSpecialization,
|
bool isSpecialization,
|
||||||
const FullySpecifiedType *const args,
|
const TemplateArgument *const args,
|
||||||
int argv)
|
int argv)
|
||||||
{
|
{
|
||||||
return d->findOrInsertTemplateNameId(id, isSpecialization, args, args + argv);
|
return d->findOrInsertTemplateNameId(id, isSpecialization, args, args + argv);
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/Control.h
vendored
2
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -54,7 +54,7 @@ public:
|
|||||||
/// Returns the canonical template name id.
|
/// Returns the canonical template name id.
|
||||||
const TemplateNameId *templateNameId(const Identifier *id,
|
const TemplateNameId *templateNameId(const Identifier *id,
|
||||||
bool isSpecialization,
|
bool isSpecialization,
|
||||||
const FullySpecifiedType *const args = nullptr,
|
const TemplateArgument *const args = nullptr,
|
||||||
int argc = 0);
|
int argc = 0);
|
||||||
|
|
||||||
/// Returns the canonical destructor name id.
|
/// Returns the canonical destructor name id.
|
||||||
|
|||||||
30
src/libs/3rdparty/cplusplus/Keywords.cpp
vendored
30
src/libs/3rdparty/cplusplus/Keywords.cpp
vendored
@@ -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') {
|
else if (features.cxx11Enabled && s[0] == 'c') {
|
||||||
if (s[1] == 'o') {
|
if (s[1] == 'o') {
|
||||||
@@ -1178,11 +1195,20 @@ static inline int classify10(const char *s, LanguageFeatures features)
|
|||||||
{
|
{
|
||||||
if (s[0] == '_') {
|
if (s[0] == '_') {
|
||||||
if (s[1] == '_') {
|
if (s[1] == '_') {
|
||||||
if (features.cxxEnabled && s[2] == 'd') {
|
if (s[2] == 'd') {
|
||||||
if (s[3] == 'e') {
|
if (s[3] == 'e') {
|
||||||
if (s[4] == 'c') {
|
if (s[4] == 'c') {
|
||||||
if (s[5] == 'l') {
|
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[7] == 'y') {
|
||||||
if (s[8] == 'p') {
|
if (s[8] == 'p') {
|
||||||
if (s[9] == 'e') {
|
if (s[9] == 'e') {
|
||||||
|
|||||||
2
src/libs/3rdparty/cplusplus/Keywords.kwgen
vendored
2
src/libs/3rdparty/cplusplus/Keywords.kwgen
vendored
@@ -37,6 +37,8 @@ __asm__
|
|||||||
__attribute
|
__attribute
|
||||||
__attribute__
|
__attribute__
|
||||||
__alignof__
|
__alignof__
|
||||||
|
_declspec
|
||||||
|
__declspec
|
||||||
__const
|
__const
|
||||||
__const__
|
__const__
|
||||||
__inline
|
__inline
|
||||||
|
|||||||
11
src/libs/3rdparty/cplusplus/Lexer.cpp
vendored
11
src/libs/3rdparty/cplusplus/Lexer.cpp
vendored
@@ -1052,10 +1052,17 @@ void Lexer::scanIdentifier(Token *tok, unsigned extraProcessedChars)
|
|||||||
yyinp();
|
yyinp();
|
||||||
}
|
}
|
||||||
int yylen = _currentChar - yytext;
|
int yylen = _currentChar - yytext;
|
||||||
if (f._scanKeywords)
|
if (f._scanKeywords) {
|
||||||
tok->f.kind = classify(yytext, yylen, _languageFeatures);
|
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;
|
tok->f.kind = T_IDENTIFIER;
|
||||||
|
}
|
||||||
|
|
||||||
if (tok->f.kind == T_IDENTIFIER) {
|
if (tok->f.kind == T_IDENTIFIER) {
|
||||||
tok->f.kind = classifyOperator(yytext, yylen);
|
tok->f.kind = classifyOperator(yytext, yylen);
|
||||||
|
|||||||
4
src/libs/3rdparty/cplusplus/Matcher.cpp
vendored
4
src/libs/3rdparty/cplusplus/Matcher.cpp
vendored
@@ -324,8 +324,8 @@ bool Matcher::match(const TemplateNameId *name, const TemplateNameId *otherName)
|
|||||||
if (name->templateArgumentCount() != otherName->templateArgumentCount())
|
if (name->templateArgumentCount() != otherName->templateArgumentCount())
|
||||||
return false;
|
return false;
|
||||||
for (unsigned i = 0, ei = name->templateArgumentCount(); i != ei; ++i) {
|
for (unsigned i = 0, ei = name->templateArgumentCount(); i != ei; ++i) {
|
||||||
const FullySpecifiedType &l = name->templateArgumentAt(i);
|
const TemplateArgument &l = name->templateArgumentAt(i);
|
||||||
const FullySpecifiedType &r = otherName->templateArgumentAt(i);
|
const TemplateArgument &r = otherName->templateArgumentAt(i);
|
||||||
if (! l.match(r, this))
|
if (! l.match(r, this))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/libs/3rdparty/cplusplus/Names.cpp
vendored
9
src/libs/3rdparty/cplusplus/Names.cpp
vendored
@@ -93,10 +93,17 @@ bool TemplateNameId::match0(const Name *otherName, Matcher *matcher) const
|
|||||||
const Identifier *TemplateNameId::identifier() const
|
const Identifier *TemplateNameId::identifier() const
|
||||||
{ return _identifier; }
|
{ 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
|
int TemplateNameId::templateArgumentCount() const
|
||||||
{ return int(_templateArguments.size()); }
|
{ return int(_templateArguments.size()); }
|
||||||
|
|
||||||
const FullySpecifiedType &TemplateNameId::templateArgumentAt(int index) const
|
const TemplateArgument &TemplateNameId::templateArgumentAt(int index) const
|
||||||
{ return _templateArguments[index]; }
|
{ return _templateArguments[index]; }
|
||||||
|
|
||||||
bool TemplateNameId::Compare::operator()(const TemplateNameId *name,
|
bool TemplateNameId::Compare::operator()(const TemplateNameId *name,
|
||||||
|
|||||||
51
src/libs/3rdparty/cplusplus/Names.h
vendored
51
src/libs/3rdparty/cplusplus/Names.h
vendored
@@ -73,6 +73,51 @@ private:
|
|||||||
const Name *_name;
|
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
|
class CPLUSPLUS_EXPORT TemplateNameId: public Name
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -89,12 +134,12 @@ public:
|
|||||||
|
|
||||||
// ### find a better name
|
// ### find a better name
|
||||||
int templateArgumentCount() const;
|
int templateArgumentCount() const;
|
||||||
const FullySpecifiedType &templateArgumentAt(int index) const;
|
const TemplateArgument &templateArgumentAt(int index) const;
|
||||||
|
|
||||||
virtual const TemplateNameId *asTemplateNameId() const
|
virtual const TemplateNameId *asTemplateNameId() const
|
||||||
{ return this; }
|
{ return this; }
|
||||||
|
|
||||||
typedef std::vector<FullySpecifiedType>::const_iterator TemplateArgumentIterator;
|
typedef std::vector<TemplateArgument>::const_iterator TemplateArgumentIterator;
|
||||||
|
|
||||||
TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
|
TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
|
||||||
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
|
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
|
||||||
@@ -111,7 +156,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const Identifier *_identifier;
|
const Identifier *_identifier;
|
||||||
std::vector<FullySpecifiedType> _templateArguments;
|
std::vector<TemplateArgument> _templateArguments;
|
||||||
// now TemplateNameId can be a specialization or an instantiation
|
// now TemplateNameId can be a specialization or an instantiation
|
||||||
bool _isSpecialization;
|
bool _isSpecialization;
|
||||||
};
|
};
|
||||||
|
|||||||
79
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
79
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -770,6 +770,18 @@ bool Parser::parseDeclaration(DeclarationAST *&node)
|
|||||||
else if (LA() == T_AT_PROPERTY)
|
else if (LA() == T_AT_PROPERTY)
|
||||||
return parseObjCPropertyDeclaration(node, attributes);
|
return parseObjCPropertyDeclaration(node, attributes);
|
||||||
rewind(start);
|
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)
|
if (LA() == T_EXTERN && LA(2) == T_TEMPLATE)
|
||||||
@@ -3761,6 +3773,11 @@ bool Parser::parseIfStatement(StatementAST *&node)
|
|||||||
if (LA() == T_IF) {
|
if (LA() == T_IF) {
|
||||||
IfStatementAST *ast = new (_pool) IfStatementAST;
|
IfStatementAST *ast = new (_pool) IfStatementAST;
|
||||||
ast->if_token = consumeToken();
|
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);
|
match(T_LPAREN, &ast->lparen_token);
|
||||||
parseCondition(ast->condition);
|
parseCondition(ast->condition);
|
||||||
match(T_RPAREN, &ast->rparen_token);
|
match(T_RPAREN, &ast->rparen_token);
|
||||||
@@ -3961,6 +3978,8 @@ bool Parser::lookAtBuiltinTypeSpecifier() const
|
|||||||
// [gcc] extensions
|
// [gcc] extensions
|
||||||
case T___TYPEOF__:
|
case T___TYPEOF__:
|
||||||
case T___ATTRIBUTE__:
|
case T___ATTRIBUTE__:
|
||||||
|
// [msvc] extensions
|
||||||
|
case T___DECLSPEC:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -4020,8 +4039,22 @@ bool Parser::parseAttributeSpecifier(SpecifierListAST *&attribute_list)
|
|||||||
attr_ptr = &(*attr_ptr)->next;
|
attr_ptr = &(*attr_ptr)->next;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
case T___DECLSPEC:
|
||||||
|
while (LA() == T___DECLSPEC) {
|
||||||
|
parseMsvcDeclspecSpecifier(*attr_ptr);
|
||||||
|
attr_ptr = &(*attr_ptr)->next;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
default:
|
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;
|
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)
|
bool Parser::parseBuiltinTypeSpecifier(SpecifierListAST *&node)
|
||||||
{
|
{
|
||||||
DEBUG_THIS_RULE();
|
DEBUG_THIS_RULE();
|
||||||
if (LA() == T___ATTRIBUTE__) {
|
if (LA() == T___ATTRIBUTE__) {
|
||||||
return parseGnuAttributeSpecifier(node);
|
return parseGnuAttributeSpecifier(node);
|
||||||
|
} else if (LA() == T___DECLSPEC) {
|
||||||
|
return parseMsvcDeclspecSpecifier(node);
|
||||||
|
} else if (lookAtStdAttribute()) {
|
||||||
|
return parseStdAttributeSpecifier(node);
|
||||||
} else if (LA() == T___TYPEOF__) {
|
} else if (LA() == T___TYPEOF__) {
|
||||||
TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST;
|
TypeofSpecifierAST *ast = new (_pool) TypeofSpecifierAST;
|
||||||
ast->typeof_token = consumeToken();
|
ast->typeof_token = consumeToken();
|
||||||
@@ -5748,6 +5816,11 @@ bool Parser::parseNoExceptOperatorExpression(ExpressionAST *&node)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::lookAtStdAttribute() const
|
||||||
|
{
|
||||||
|
return _languageFeatures.cxx11Enabled && LA() == T_LBRACKET && LA(2) == T_LBRACKET;
|
||||||
|
}
|
||||||
|
|
||||||
bool Parser::lookAtObjCSelector() const
|
bool Parser::lookAtObjCSelector() const
|
||||||
{
|
{
|
||||||
switch (LA()) {
|
switch (LA()) {
|
||||||
@@ -6797,6 +6870,8 @@ bool Parser::parseLambdaDeclarator(LambdaDeclaratorAST *&node)
|
|||||||
SpecifierListAST **attr = &ast->attributes;
|
SpecifierListAST **attr = &ast->attributes;
|
||||||
while (parseGnuAttributeSpecifier(*attr))
|
while (parseGnuAttributeSpecifier(*attr))
|
||||||
attr = &(*attr)->next;
|
attr = &(*attr)->next;
|
||||||
|
while (parseStdAttributeSpecifier(*attr))
|
||||||
|
attr = &(*attr)->next;
|
||||||
|
|
||||||
if (LA() == T_MUTABLE)
|
if (LA() == T_MUTABLE)
|
||||||
ast->mutable_token = consumeToken();
|
ast->mutable_token = consumeToken();
|
||||||
@@ -6821,6 +6896,8 @@ bool Parser::parseTrailingReturnType(TrailingReturnTypeAST *&node)
|
|||||||
SpecifierListAST **attr = &ast->attributes;
|
SpecifierListAST **attr = &ast->attributes;
|
||||||
while (parseGnuAttributeSpecifier(*attr))
|
while (parseGnuAttributeSpecifier(*attr))
|
||||||
attr = &(*attr)->next;
|
attr = &(*attr)->next;
|
||||||
|
while (parseStdAttributeSpecifier(*attr))
|
||||||
|
attr = &(*attr)->next;
|
||||||
|
|
||||||
parseTrailingTypeSpecifierSeq(ast->type_specifier_list);
|
parseTrailingTypeSpecifierSeq(ast->type_specifier_list);
|
||||||
parseAbstractDeclarator(ast->declarator, ast->type_specifier_list);
|
parseAbstractDeclarator(ast->declarator, ast->type_specifier_list);
|
||||||
|
|||||||
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -170,6 +170,9 @@ public:
|
|||||||
bool parseGnuAttributeSpecifier(SpecifierListAST *&node);
|
bool parseGnuAttributeSpecifier(SpecifierListAST *&node);
|
||||||
bool parseGnuAttributeList(GnuAttributeListAST *&node);
|
bool parseGnuAttributeList(GnuAttributeListAST *&node);
|
||||||
|
|
||||||
|
bool parseMsvcDeclspecSpecifier(SpecifierListAST *&node);
|
||||||
|
bool parseStdAttributeSpecifier(SpecifierListAST *&node);
|
||||||
|
|
||||||
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
|
bool parseDeclSpecifierSeq(SpecifierListAST *&node,
|
||||||
bool noStorageSpecifiers = false,
|
bool noStorageSpecifiers = false,
|
||||||
bool onlySimpleTypeSpecifiers = false);
|
bool onlySimpleTypeSpecifiers = false);
|
||||||
@@ -247,6 +250,8 @@ public:
|
|||||||
bool peekAtObjCContextKeyword(int kind);
|
bool peekAtObjCContextKeyword(int kind);
|
||||||
bool parseObjCContextKeyword(int kind, int &in_token);
|
bool parseObjCContextKeyword(int kind, int &in_token);
|
||||||
|
|
||||||
|
bool lookAtStdAttribute() const;
|
||||||
|
|
||||||
bool lookAtObjCSelector() const;
|
bool lookAtObjCSelector() const;
|
||||||
|
|
||||||
// c99
|
// c99
|
||||||
|
|||||||
11
src/libs/3rdparty/cplusplus/Symbols.cpp
vendored
11
src/libs/3rdparty/cplusplus/Symbols.cpp
vendored
@@ -191,7 +191,7 @@ Declaration::Declaration(Clone *clone, Subst *subst, Declaration *original)
|
|||||||
if (const TemplateNameId * templateNameId =
|
if (const TemplateNameId * templateNameId =
|
||||||
namedType->name()->asTemplateNameId()) {
|
namedType->name()->asTemplateNameId()) {
|
||||||
if (templateNameId->templateArgumentCount()) {
|
if (templateNameId->templateArgumentCount()) {
|
||||||
newType = clone->type(templateNameId->templateArgumentAt(0), nullptr);
|
newType = clone->type(templateNameId->templateArgumentAt(0).type(), nullptr);
|
||||||
newType = FullySpecifiedType(clone->control()->pointerType(newType));
|
newType = FullySpecifiedType(clone->control()->pointerType(newType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,6 +469,12 @@ bool Function::isVariadic() const
|
|||||||
void Function::setVariadic(bool isVariadic)
|
void Function::setVariadic(bool isVariadic)
|
||||||
{ f._isVariadic = isVariadic; }
|
{ f._isVariadic = isVariadic; }
|
||||||
|
|
||||||
|
bool Function::isVariadicTemplate() const
|
||||||
|
{ return f._isVariadicTemplate; }
|
||||||
|
|
||||||
|
void Function::setVariadicTemplate(bool isVariadicTemplate)
|
||||||
|
{ f._isVariadicTemplate = isVariadicTemplate; }
|
||||||
|
|
||||||
bool Function::isConst() const
|
bool Function::isConst() const
|
||||||
{ return f._isConst; }
|
{ return f._isConst; }
|
||||||
|
|
||||||
@@ -523,6 +529,9 @@ bool Function::maybeValidPrototype(int actualArgumentCount) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isVariadicTemplate())
|
||||||
|
--minNumberArguments;
|
||||||
|
|
||||||
if (actualArgumentCount < minNumberArguments) {
|
if (actualArgumentCount < minNumberArguments) {
|
||||||
// not enough arguments.
|
// not enough arguments.
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
4
src/libs/3rdparty/cplusplus/Symbols.h
vendored
4
src/libs/3rdparty/cplusplus/Symbols.h
vendored
@@ -346,6 +346,9 @@ public:
|
|||||||
bool isVariadic() const;
|
bool isVariadic() const;
|
||||||
void setVariadic(bool isVariadic);
|
void setVariadic(bool isVariadic);
|
||||||
|
|
||||||
|
bool isVariadicTemplate() const;
|
||||||
|
void setVariadicTemplate(bool isVariadicTemplate);
|
||||||
|
|
||||||
bool isConst() const;
|
bool isConst() const;
|
||||||
void setConst(bool isConst);
|
void setConst(bool isConst);
|
||||||
|
|
||||||
@@ -397,6 +400,7 @@ private:
|
|||||||
unsigned _isOverride: 1;
|
unsigned _isOverride: 1;
|
||||||
unsigned _isFinal: 1;
|
unsigned _isFinal: 1;
|
||||||
unsigned _isVariadic: 1;
|
unsigned _isVariadic: 1;
|
||||||
|
unsigned _isVariadicTemplate: 1;
|
||||||
unsigned _isPureVirtual: 1;
|
unsigned _isPureVirtual: 1;
|
||||||
unsigned _isConst: 1;
|
unsigned _isConst: 1;
|
||||||
unsigned _isVolatile: 1;
|
unsigned _isVolatile: 1;
|
||||||
|
|||||||
4
src/libs/3rdparty/cplusplus/Templates.cpp
vendored
4
src/libs/3rdparty/cplusplus/Templates.cpp
vendored
@@ -439,9 +439,9 @@ void CloneName::visit(const AnonymousNameId *name)
|
|||||||
|
|
||||||
void CloneName::visit(const TemplateNameId *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)
|
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())
|
if (args.empty())
|
||||||
_name = _control->templateNameId(_clone->identifier(name->identifier()), name->isSpecialization());
|
_name = _control->templateNameId(_clone->identifier(name->identifier()), name->isSpecialization());
|
||||||
else
|
else
|
||||||
|
|||||||
3
src/libs/3rdparty/cplusplus/Token.cpp
vendored
3
src/libs/3rdparty/cplusplus/Token.cpp
vendored
@@ -177,6 +177,9 @@ const char *token_names[] = {
|
|||||||
("__thread"),
|
("__thread"),
|
||||||
("__typeof__"),
|
("__typeof__"),
|
||||||
|
|
||||||
|
// msvc
|
||||||
|
("__declspec"),
|
||||||
|
|
||||||
// objc @keywords
|
// objc @keywords
|
||||||
("@catch"),
|
("@catch"),
|
||||||
("@class"),
|
("@class"),
|
||||||
|
|||||||
3
src/libs/3rdparty/cplusplus/Token.h
vendored
3
src/libs/3rdparty/cplusplus/Token.h
vendored
@@ -186,6 +186,8 @@ enum Kind {
|
|||||||
T___THREAD,
|
T___THREAD,
|
||||||
T___TYPEOF__,
|
T___TYPEOF__,
|
||||||
|
|
||||||
|
T___DECLSPEC,
|
||||||
|
|
||||||
// obj c++ @ keywords
|
// obj c++ @ keywords
|
||||||
T_FIRST_OBJC_AT_KEYWORD,
|
T_FIRST_OBJC_AT_KEYWORD,
|
||||||
|
|
||||||
@@ -298,6 +300,7 @@ enum Kind {
|
|||||||
T_FOREACH = T_Q_FOREACH,
|
T_FOREACH = T_Q_FOREACH,
|
||||||
T_SIGNALS = T_Q_SIGNALS,
|
T_SIGNALS = T_Q_SIGNALS,
|
||||||
T_Q_OVERRIDE = T_Q_PROPERTY,
|
T_Q_OVERRIDE = T_Q_PROPERTY,
|
||||||
|
T__DECLSPEC = T___DECLSPEC,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPLUSPLUS_EXPORT Token
|
class CPLUSPLUS_EXPORT Token
|
||||||
|
|||||||
@@ -257,9 +257,9 @@ public:
|
|||||||
|
|
||||||
void visit(const TemplateNameId *name) override
|
void visit(const TemplateNameId *name) override
|
||||||
{
|
{
|
||||||
QVarLengthArray<FullySpecifiedType, 8> args(name->templateArgumentCount());
|
QVarLengthArray<TemplateArgument, 8> args(name->templateArgumentCount());
|
||||||
for (int i = 0; i < name->templateArgumentCount(); ++i)
|
for (int i = 0; i < name->templateArgumentCount(); ++i)
|
||||||
args[i] = rewrite->rewriteType(name->templateArgumentAt(i));
|
args[i] = rewrite->rewriteType(name->templateArgumentAt(i).type());
|
||||||
temps.append(control()->templateNameId(identifier(name->identifier()), name->isSpecialization(),
|
temps.append(control()->templateNameId(identifier(name->identifier()), name->isSpecialization(),
|
||||||
args.data(), args.size()));
|
args.data(), args.size()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,9 +242,9 @@ private:
|
|||||||
|
|
||||||
void visit(const TemplateNameId *name) override
|
void visit(const TemplateNameId *name) override
|
||||||
{
|
{
|
||||||
QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
|
QVarLengthArray<TemplateArgument, 8> arguments(name->templateArgumentCount());
|
||||||
for (int i = 0; i < name->templateArgumentCount(); ++i) {
|
for (int i = 0; i < name->templateArgumentCount(); ++i) {
|
||||||
FullySpecifiedType argTy = name->templateArgumentAt(i);
|
FullySpecifiedType argTy = name->templateArgumentAt(i).type();
|
||||||
arguments[i] = q->apply(argTy);
|
arguments[i] = q->apply(argTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,10 +265,10 @@ private:
|
|||||||
return id;
|
return id;
|
||||||
|
|
||||||
} else if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
} else if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
||||||
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
|
QVarLengthArray<TemplateArgument, 8> arguments(templId->templateArgumentCount());
|
||||||
for (int templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
|
for (int templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
|
||||||
++templateArgIndex) {
|
++templateArgIndex) {
|
||||||
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
|
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex).type();
|
||||||
arguments[templateArgIndex] = q->apply(argTy);
|
arguments[templateArgIndex] = q->apply(argTy);
|
||||||
}
|
}
|
||||||
const Identifier *id = control()->identifier(templId->identifier()->chars(),
|
const Identifier *id = control()->identifier(templId->identifier()->chars(),
|
||||||
@@ -404,7 +404,7 @@ FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *classN
|
|||||||
DeprecatedGenTemplateInstance::Substitution subst;
|
DeprecatedGenTemplateInstance::Substitution subst;
|
||||||
|
|
||||||
for (int i = 0; i < templId->templateArgumentCount(); ++i) {
|
for (int i = 0; i < templId->templateArgumentCount(); ++i) {
|
||||||
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
|
FullySpecifiedType templArgTy = templId->templateArgumentAt(i).type();
|
||||||
|
|
||||||
if (i < templ->templateParameterCount()) {
|
if (i < templ->templateParameterCount()) {
|
||||||
const Name *templArgName = templ->templateParameterAt(i)->name();
|
const Name *templArgName = templ->templateParameterAt(i)->name();
|
||||||
|
|||||||
@@ -1978,6 +1978,22 @@ bool FindUsages::visit(GnuAttributeSpecifierAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FindUsages::visit(MsvcDeclspecSpecifierAST *ast)
|
||||||
|
{
|
||||||
|
for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) {
|
||||||
|
this->attribute(it->value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindUsages::visit(StdAttributeSpecifierAST *ast)
|
||||||
|
{
|
||||||
|
for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) {
|
||||||
|
this->attribute(it->value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool FindUsages::visit(TypeofSpecifierAST *ast)
|
bool FindUsages::visit(TypeofSpecifierAST *ast)
|
||||||
{
|
{
|
||||||
// unsigned typeof_token = ast->typeof_token;
|
// unsigned typeof_token = ast->typeof_token;
|
||||||
|
|||||||
@@ -254,6 +254,8 @@ protected:
|
|||||||
// SpecifierAST
|
// SpecifierAST
|
||||||
virtual bool visit(SimpleSpecifierAST *ast);
|
virtual bool visit(SimpleSpecifierAST *ast);
|
||||||
virtual bool visit(GnuAttributeSpecifierAST *ast);
|
virtual bool visit(GnuAttributeSpecifierAST *ast);
|
||||||
|
virtual bool visit(MsvcDeclspecSpecifierAST *ast);
|
||||||
|
virtual bool visit(StdAttributeSpecifierAST *ast);
|
||||||
virtual bool visit(TypeofSpecifierAST *ast);
|
virtual bool visit(TypeofSpecifierAST *ast);
|
||||||
virtual bool visit(DecltypeSpecifierAST *ast);
|
virtual bool visit(DecltypeSpecifierAST *ast);
|
||||||
virtual bool visit(ClassSpecifierAST *ast);
|
virtual bool visit(ClassSpecifierAST *ast);
|
||||||
|
|||||||
@@ -773,6 +773,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
|||||||
LookupItem item;
|
LookupItem item;
|
||||||
item.setDeclaration(s);
|
item.setDeclaration(s);
|
||||||
item.setBinding(binding);
|
item.setBinding(binding);
|
||||||
|
|
||||||
|
if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
|
||||||
|
item.setType(inst->type());
|
||||||
|
|
||||||
result->append(item);
|
result->append(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,15 +815,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
|||||||
item.setType(ty); // override the type.
|
item.setType(ty); // override the type.
|
||||||
}
|
}
|
||||||
|
|
||||||
// instantiate function template
|
if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
|
||||||
if (name->isTemplateNameId() && s->isTemplate() && s->asTemplate()->declaration()
|
item.setType(inst->type());
|
||||||
&& s->asTemplate()->declaration()->isFunction()) {
|
|
||||||
const TemplateNameId *instantiation = name->asTemplateNameId();
|
|
||||||
Template *specialization = s->asTemplate();
|
|
||||||
Symbol *instantiatedFunctionTemplate = instantiateTemplateFunction(instantiation,
|
|
||||||
specialization);
|
|
||||||
item.setType(instantiatedFunctionTemplate->type()); // override the type.
|
|
||||||
}
|
|
||||||
|
|
||||||
result->append(item);
|
result->append(item);
|
||||||
}
|
}
|
||||||
@@ -1026,22 +1023,22 @@ ClassOrNamespace *ClassOrNamespace::findSpecialization(const TemplateNameId *tem
|
|||||||
// and initialization(in future it should be more clever)
|
// and initialization(in future it should be more clever)
|
||||||
if (specializationTemplateArgumentCount == initializationTemplateArgumentCount) {
|
if (specializationTemplateArgumentCount == initializationTemplateArgumentCount) {
|
||||||
for (int i = 0; i < initializationTemplateArgumentCount; ++i) {
|
for (int i = 0; i < initializationTemplateArgumentCount; ++i) {
|
||||||
const FullySpecifiedType &specializationTemplateArgument
|
const TemplateArgument &specializationTemplateArgument
|
||||||
= specializationNameId->templateArgumentAt(i);
|
= specializationNameId->templateArgumentAt(i);
|
||||||
const FullySpecifiedType &initializationTemplateArgument
|
const TemplateArgument &initializationTemplateArgument
|
||||||
= templId->templateArgumentAt(i);
|
= templId->templateArgumentAt(i);
|
||||||
PointerType *specPointer
|
PointerType *specPointer
|
||||||
= specializationTemplateArgument.type()->asPointerType();
|
= specializationTemplateArgument.type().type()->asPointerType();
|
||||||
// specialization and initialization argument have to be a pointer
|
// specialization and initialization argument have to be a pointer
|
||||||
// additionally type of pointer argument of specialization has to be namedType
|
// additionally type of pointer argument of specialization has to be namedType
|
||||||
if (specPointer && initializationTemplateArgument.type()->isPointerType()
|
if (specPointer && initializationTemplateArgument.type().type()->isPointerType()
|
||||||
&& specPointer->elementType().type()->isNamedType()) {
|
&& specPointer->elementType().type()->isNamedType()) {
|
||||||
return cit->second;
|
return cit->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayType *specArray
|
ArrayType *specArray
|
||||||
= specializationTemplateArgument.type()->asArrayType();
|
= specializationTemplateArgument.type().type()->asArrayType();
|
||||||
if (specArray && initializationTemplateArgument.type()->isArrayType()) {
|
if (specArray && initializationTemplateArgument.type().type()->isArrayType()) {
|
||||||
if (const NamedType *argumentNamedType
|
if (const NamedType *argumentNamedType
|
||||||
= specArray->elementType().type()->asNamedType()) {
|
= specArray->elementType().type()->asNamedType()) {
|
||||||
if (const Name *argumentName = argumentNamedType->name()) {
|
if (const Name *argumentName = argumentNamedType->name()) {
|
||||||
@@ -1142,7 +1139,33 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
|||||||
= findSpecialization(templId, specializations);
|
= findSpecialization(templId, specializations);
|
||||||
if (specializationWithPointer)
|
if (specializationWithPointer)
|
||||||
reference = specializationWithPointer;
|
reference = specializationWithPointer;
|
||||||
// TODO: find the best specialization(probably partial) for this instantiation
|
|
||||||
|
int maximumArgumentsMatched = 0;
|
||||||
|
|
||||||
|
for (const std::pair<const TemplateNameId *, ClassOrNamespace *> &p :
|
||||||
|
specializations) {
|
||||||
|
const TemplateNameId *templateSpecialization = p.first;
|
||||||
|
ClassOrNamespace *specializationClassOrNamespace = p.second;
|
||||||
|
|
||||||
|
const int argumentCountOfInitialization = templId->templateArgumentCount();
|
||||||
|
const int argumentCountOfSpecialization =
|
||||||
|
templateSpecialization->templateArgumentCount();
|
||||||
|
|
||||||
|
int argumentsMatched = 0;
|
||||||
|
for (int i = 0;
|
||||||
|
i < argumentCountOfInitialization && i < argumentCountOfSpecialization;
|
||||||
|
++i) {
|
||||||
|
if (templId->templateArgumentAt(i) ==
|
||||||
|
templateSpecialization->templateArgumentAt(i)) {
|
||||||
|
argumentsMatched++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentsMatched > maximumArgumentsMatched) {
|
||||||
|
reference = specializationClassOrNamespace;
|
||||||
|
maximumArgumentsMatched = argumentsMatched;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1227,12 +1250,39 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
|||||||
if (!name)
|
if (!name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
int argumentPositionInReferenceClass=i;
|
||||||
templId->templateArgumentAt(i):
|
|
||||||
|
if (referenceClass->name() && referenceClass->name()->asTemplateNameId()) {
|
||||||
|
argumentPositionInReferenceClass=-1;
|
||||||
|
const TemplateNameId* refTemp = referenceClass->name()->asTemplateNameId();
|
||||||
|
for (int argPos=0; argPos < refTemp->templateArgumentCount(); argPos++) {
|
||||||
|
const Type* argType = refTemp->templateArgumentAt(argPos).type().type();
|
||||||
|
if (argType->asNamedType()
|
||||||
|
&& argType->asNamedType()->name() == name) {
|
||||||
|
argumentPositionInReferenceClass = argPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (argType->asPointerType()
|
||||||
|
&& argType->asPointerType()->elementType().type()->asNamedType()
|
||||||
|
&& argType->asPointerType()->elementType().type()
|
||||||
|
->asNamedType()->name() == name) {
|
||||||
|
argumentPositionInReferenceClass = argPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentPositionInReferenceClass < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FullySpecifiedType ty = (argumentPositionInReferenceClass < argumentCountOfInitialization) ?
|
||||||
|
templId->templateArgumentAt(argumentPositionInReferenceClass).type():
|
||||||
cloner.type(tParam->type(), &subst);
|
cloner.type(tParam->type(), &subst);
|
||||||
|
|
||||||
if (i < templSpecArgumentCount
|
if (i < templSpecArgumentCount
|
||||||
&& templSpecId->templateArgumentAt(i)->isPointerType()) {
|
&& templSpecId->templateArgumentAt(i).type()->isPointerType()) {
|
||||||
if (PointerType *pointerType = ty->asPointerType())
|
if (PointerType *pointerType = ty->asPointerType())
|
||||||
ty = pointerType->elementType();
|
ty = pointerType->elementType();
|
||||||
}
|
}
|
||||||
@@ -1281,7 +1331,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
|||||||
const int parameterIndex = templParams.value(nameId);
|
const int parameterIndex = templParams.value(nameId);
|
||||||
if (parameterIndex < argumentCountOfInitialization) {
|
if (parameterIndex < argumentCountOfInitialization) {
|
||||||
const FullySpecifiedType &fullType =
|
const FullySpecifiedType &fullType =
|
||||||
templId->templateArgumentAt(parameterIndex);
|
templId->templateArgumentAt(parameterIndex).type();
|
||||||
if (fullType.isValid()) {
|
if (fullType.isValid()) {
|
||||||
if (NamedType *namedType = fullType.type()->asNamedType())
|
if (NamedType *namedType = fullType.type()->asNamedType())
|
||||||
baseBinding = lookupType(namedType->name());
|
baseBinding = lookupType(namedType->name());
|
||||||
@@ -1300,7 +1350,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
|||||||
for (int i = 0; i < argumentCountOfSpecialization; ++i) {
|
for (int i = 0; i < argumentCountOfSpecialization; ++i) {
|
||||||
const Name *name = templateSpecialization->templateParameterAt(i)->name();
|
const Name *name = templateSpecialization->templateParameterAt(i)->name();
|
||||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
||||||
templId->templateArgumentAt(i):
|
templId->templateArgumentAt(i).type():
|
||||||
templateSpecialization->templateParameterAt(i)->type();
|
templateSpecialization->templateParameterAt(i)->type();
|
||||||
|
|
||||||
map.bind(name, ty);
|
map.bind(name, ty);
|
||||||
@@ -1927,10 +1977,28 @@ bool CreateBindings::visit(ObjCMethod *)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instantiation,
|
Symbol *CreateBindings::instantiateTemplateFunction(const Name *instantiationName,
|
||||||
Template *specialization) const
|
Template *specialization) const
|
||||||
{
|
{
|
||||||
const int argumentCountOfInitialization = instantiation->templateArgumentCount();
|
if (!specialization || !specialization->declaration()
|
||||||
|
|| !specialization->declaration()->isFunction())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
int argumentCountOfInstantiation = 0;
|
||||||
|
const TemplateNameId *instantiation = nullptr;
|
||||||
|
if (instantiationName->isTemplateNameId()) {
|
||||||
|
instantiation = instantiationName->asTemplateNameId();
|
||||||
|
argumentCountOfInstantiation = instantiation->templateArgumentCount();
|
||||||
|
} else {
|
||||||
|
// no template arguments passed in function call
|
||||||
|
// check if all template parameters have default arguments (only check first parameter)
|
||||||
|
if (specialization->templateParameterCount() == 0)
|
||||||
|
return nullptr;
|
||||||
|
TypenameArgument *parameter = specialization->templateParameterAt(0)->asTypenameArgument();
|
||||||
|
if (!parameter || !parameter->type().isValid())
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const int argumentCountOfSpecialization = specialization->templateParameterCount();
|
const int argumentCountOfSpecialization = specialization->templateParameterCount();
|
||||||
|
|
||||||
Clone cloner(_control.data());
|
Clone cloner(_control.data());
|
||||||
@@ -1944,8 +2012,8 @@ Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instan
|
|||||||
if (!name)
|
if (!name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
FullySpecifiedType ty = (i < argumentCountOfInstantiation) ?
|
||||||
instantiation->templateArgumentAt(i):
|
instantiation->templateArgumentAt(i).type():
|
||||||
cloner.type(tParam->type(), &subst);
|
cloner.type(tParam->type(), &subst);
|
||||||
|
|
||||||
subst.bind(cloner.name(name, &subst), ty);
|
subst.bind(cloner.name(name, &subst), ty);
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ protected:
|
|||||||
virtual bool visit(ObjCMethod *);
|
virtual bool visit(ObjCMethod *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
|
Symbol *instantiateTemplateFunction(const Name *instantiationName,
|
||||||
Template *specialization) const;
|
Template *specialization) const;
|
||||||
|
|
||||||
Snapshot _snapshot;
|
Snapshot _snapshot;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ void NamePrettyPrinter::visit(const TemplateNameId *name)
|
|||||||
if (index != 0)
|
if (index != 0)
|
||||||
_name += QLatin1String(", ");
|
_name += QLatin1String(", ");
|
||||||
|
|
||||||
FullySpecifiedType argTy = name->templateArgumentAt(index);
|
FullySpecifiedType argTy = name->templateArgumentAt(index).type();
|
||||||
QString arg = overview()->prettyType(argTy);
|
QString arg = overview()->prettyType(argTy);
|
||||||
if (arg.isEmpty())
|
if (arg.isEmpty())
|
||||||
_name += QString::fromLatin1("_Tp%1").arg(index + 1);
|
_name += QString::fromLatin1("_Tp%1").arg(index + 1);
|
||||||
|
|||||||
@@ -918,6 +918,13 @@ bool ResolveExpression::visit(CallAST *ast)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_results.size()>1){
|
||||||
|
// move functions with known bindings to begin of results list
|
||||||
|
std::stable_partition(_results.begin(), _results.end(), [](const LookupItem &item) -> bool {
|
||||||
|
return item.binding();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1109,11 +1116,23 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
|||||||
continue;
|
continue;
|
||||||
Scope *functionScope = overload->enclosingScope();
|
Scope *functionScope = overload->enclosingScope();
|
||||||
|
|
||||||
if (overload->type()->isFunctionType()) {
|
FullySpecifiedType overloadType = r.type();
|
||||||
|
if (! overloadType.isValid())
|
||||||
|
overloadType = overload->type();
|
||||||
|
|
||||||
|
Function *instantiatedFunction = nullptr;
|
||||||
|
|
||||||
|
if (overloadType->isFunctionType()) {
|
||||||
FullySpecifiedType overloadTy
|
FullySpecifiedType overloadTy
|
||||||
= instantiate(binding->templateId(), overload);
|
= instantiate(binding->templateId(), overload);
|
||||||
Function *instantiatedFunction = overloadTy->asFunctionType();
|
instantiatedFunction = overloadTy->asFunctionType();
|
||||||
Q_ASSERT(instantiatedFunction != nullptr);
|
} else if (overloadType->isTemplateType()
|
||||||
|
&& overloadType->asTemplateType()->declaration()
|
||||||
|
&& overloadType->asTemplateType()->declaration()->isFunction()) {
|
||||||
|
instantiatedFunction = overloadType->asTemplateType()->declaration()->asFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instantiatedFunction != nullptr) {
|
||||||
|
|
||||||
FullySpecifiedType retTy
|
FullySpecifiedType retTy
|
||||||
= instantiatedFunction->returnType().simplified();
|
= instantiatedFunction->returnType().simplified();
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ static bool canReplaceSpecifier(TranslationUnit *translationUnit, SpecifierAST *
|
|||||||
case T_AUTO:
|
case T_AUTO:
|
||||||
case T___TYPEOF__:
|
case T___TYPEOF__:
|
||||||
case T___ATTRIBUTE__:
|
case T___ATTRIBUTE__:
|
||||||
|
case T___DECLSPEC:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -863,6 +863,7 @@ bool CodeFormatter::tryDeclaration()
|
|||||||
case T_AUTO:
|
case T_AUTO:
|
||||||
case T___TYPEOF__:
|
case T___TYPEOF__:
|
||||||
case T___ATTRIBUTE__:
|
case T___ATTRIBUTE__:
|
||||||
|
case T___DECLSPEC:
|
||||||
case T_STATIC:
|
case T_STATIC:
|
||||||
case T_FRIEND:
|
case T_FRIEND:
|
||||||
case T_CONST:
|
case T_CONST:
|
||||||
@@ -1590,7 +1591,7 @@ void QtStyleCodeFormatter::adjustIndent(const Tokens &tokens, int lexerState, in
|
|||||||
if (m_styleSettings.indentDeclarationsRelativeToAccessSpecifiers
|
if (m_styleSettings.indentDeclarationsRelativeToAccessSpecifiers
|
||||||
&& topState.type == class_open) {
|
&& topState.type == class_open) {
|
||||||
if (tokenAt(1).is(T_COLON) || tokenAt(2).is(T_COLON)
|
if (tokenAt(1).is(T_COLON) || tokenAt(2).is(T_COLON)
|
||||||
|| (tokenAt(tokenCount() - 1).is(T_COLON) && tokenAt(1).is(T___ATTRIBUTE__))) {
|
|| (tokenAt(tokenCount() - 1).is(T_COLON) && (tokenAt(1).is(T___ATTRIBUTE__) || tokenAt(1).is(T___DECLSPEC)))) {
|
||||||
*indentDepth = topState.savedIndentDepth;
|
*indentDepth = topState.savedIndentDepth;
|
||||||
if (m_styleSettings.indentAccessSpecifiers)
|
if (m_styleSettings.indentAccessSpecifiers)
|
||||||
*indentDepth += m_tabSettings.m_indentSize;
|
*indentDepth += m_tabSettings.m_indentSize;
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ QString Utils::toString(CPlusPlus::Kind kind)
|
|||||||
TOKEN_AND_ALIASES(T___ATTRIBUTE__, T___ATTRIBUTE);
|
TOKEN_AND_ALIASES(T___ATTRIBUTE__, T___ATTRIBUTE);
|
||||||
TOKEN(T___THREAD);
|
TOKEN(T___THREAD);
|
||||||
TOKEN_AND_ALIASES(T___TYPEOF__, T_TYPEOF/T___TYPEOF);
|
TOKEN_AND_ALIASES(T___TYPEOF__, T_TYPEOF/T___TYPEOF);
|
||||||
|
TOKEN_AND_ALIASES(T___DECLSPEC, T__DECLSPEC);
|
||||||
TOKEN(T_AT_CATCH);
|
TOKEN(T_AT_CATCH);
|
||||||
TOKEN(T_AT_CLASS);
|
TOKEN(T_AT_CLASS);
|
||||||
TOKEN(T_AT_COMPATIBILITY_ALIAS);
|
TOKEN(T_AT_COMPATIBILITY_ALIAS);
|
||||||
|
|||||||
@@ -98,12 +98,13 @@ static unsigned firstTypeSpecifierWithoutFollowingAttribute(
|
|||||||
case T_TYPEDEF:
|
case T_TYPEDEF:
|
||||||
case T_CONSTEXPR:
|
case T_CONSTEXPR:
|
||||||
case T___ATTRIBUTE__:
|
case T___ATTRIBUTE__:
|
||||||
|
case T___DECLSPEC:
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
// Check if attributes follow
|
// Check if attributes follow
|
||||||
for (unsigned i = index; i <= endToken; ++i) {
|
for (unsigned i = index; i <= endToken; ++i) {
|
||||||
const int tokenKind = translationUnit->tokenKind(i);
|
const int tokenKind = translationUnit->tokenKind(i);
|
||||||
if (tokenKind == T___ATTRIBUTE__)
|
if (tokenKind == T___ATTRIBUTE__ || tokenKind == T___DECLSPEC)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*found = true;
|
*found = true;
|
||||||
|
|||||||
@@ -81,6 +81,34 @@ virtual bool visit(GnuAttributeSpecifierAST *ast)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool visit(MsvcDeclspecSpecifierAST *ast)
|
||||||
|
{
|
||||||
|
if (ast->attribute_token)
|
||||||
|
terminal(ast->attribute_token, ast);
|
||||||
|
if (ast->lparen_token)
|
||||||
|
terminal(ast->lparen_token, ast);
|
||||||
|
for (GnuAttributeListAST *iter = ast->attribute_list; iter; iter = iter->next)
|
||||||
|
nonterminal(iter->value);
|
||||||
|
if (ast->rparen_token)
|
||||||
|
terminal(ast->rparen_token, ast);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(StdAttributeSpecifierAST *ast)
|
||||||
|
{
|
||||||
|
if (ast->first_lbracket_token)
|
||||||
|
terminal(ast->first_lbracket_token, ast);
|
||||||
|
if (ast->second_lbracket_token)
|
||||||
|
terminal(ast->second_lbracket_token, ast);
|
||||||
|
for (GnuAttributeListAST *iter = ast->attribute_list; iter; iter = iter->next)
|
||||||
|
nonterminal(iter->value);
|
||||||
|
if (ast->first_rbracket_token)
|
||||||
|
terminal(ast->first_rbracket_token, ast);
|
||||||
|
if (ast->second_rbracket_token)
|
||||||
|
terminal(ast->second_rbracket_token, ast);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool visit(GnuAttributeAST *ast)
|
virtual bool visit(GnuAttributeAST *ast)
|
||||||
{
|
{
|
||||||
if (ast->identifier_token)
|
if (ast->identifier_token)
|
||||||
@@ -714,6 +742,8 @@ virtual bool visit(IfStatementAST *ast)
|
|||||||
{
|
{
|
||||||
if (ast->if_token)
|
if (ast->if_token)
|
||||||
terminal(ast->if_token, ast);
|
terminal(ast->if_token, ast);
|
||||||
|
if (ast->constexpr_token)
|
||||||
|
terminal(ast->constexpr_token, ast);
|
||||||
if (ast->lparen_token)
|
if (ast->lparen_token)
|
||||||
terminal(ast->lparen_token, ast);
|
terminal(ast->lparen_token, ast);
|
||||||
nonterminal(ast->condition);
|
nonterminal(ast->condition);
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ private slots:
|
|||||||
void crash_test_1();
|
void crash_test_1();
|
||||||
void thread_local_1();
|
void thread_local_1();
|
||||||
|
|
||||||
|
void msvc_attributes_declspec();
|
||||||
|
|
||||||
// expressions
|
// expressions
|
||||||
void simple_name_1();
|
void simple_name_1();
|
||||||
void template_id_1();
|
void template_id_1();
|
||||||
@@ -141,6 +143,7 @@ private slots:
|
|||||||
void if_statement_2();
|
void if_statement_2();
|
||||||
void if_statement_3();
|
void if_statement_3();
|
||||||
void if_else_statement();
|
void if_else_statement();
|
||||||
|
void if_constexpr();
|
||||||
void while_statement();
|
void while_statement();
|
||||||
void while_condition_statement();
|
void while_condition_statement();
|
||||||
void for_statement();
|
void for_statement();
|
||||||
@@ -169,6 +172,7 @@ private slots:
|
|||||||
//! checks for both correct ellipsis tokens in
|
//! checks for both correct ellipsis tokens in
|
||||||
//! "template<class ...Args> class T : Args... {};"
|
//! "template<class ...Args> class T : Args... {};"
|
||||||
void cpp11_variadic_inheritance();
|
void cpp11_variadic_inheritance();
|
||||||
|
void cpp11_attributes();
|
||||||
|
|
||||||
// Q_PROPERTY
|
// Q_PROPERTY
|
||||||
void cpp_qproperty();
|
void cpp_qproperty();
|
||||||
@@ -281,6 +285,14 @@ void tst_AST::thread_local_1()
|
|||||||
QCOMPARE(Token::name(T___THREAD), "__thread");
|
QCOMPARE(Token::name(T___THREAD), "__thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_AST::msvc_attributes_declspec()
|
||||||
|
{
|
||||||
|
const char *inp = "class __declspec(novtable) Name{};";
|
||||||
|
QSharedPointer<TranslationUnit> unit(parseDeclaration(inp));
|
||||||
|
QVERIFY(unit->ast());
|
||||||
|
QCOMPARE(diag.errorCount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_AST::simple_declaration_1()
|
void tst_AST::simple_declaration_1()
|
||||||
{
|
{
|
||||||
QSharedPointer<TranslationUnit> unit(parseStatement("\n"
|
QSharedPointer<TranslationUnit> unit(parseStatement("\n"
|
||||||
@@ -1322,6 +1334,43 @@ void tst_AST::cpp11_variadic_inheritance()
|
|||||||
QVERIFY(ba->ellipsis_token != 0); // important
|
QVERIFY(ba->ellipsis_token != 0); // important
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_AST::cpp11_attributes()
|
||||||
|
{
|
||||||
|
QSharedPointer<TranslationUnit> unit(parseDeclaration(
|
||||||
|
"[[noreturn]] void f() {throw \"error\";}",
|
||||||
|
false, false, true));
|
||||||
|
AST *ast = unit->ast();
|
||||||
|
QVERIFY(ast != nullptr);
|
||||||
|
|
||||||
|
DeclarationAST *d = ast->asDeclaration();
|
||||||
|
QVERIFY(d != nullptr);
|
||||||
|
|
||||||
|
FunctionDefinitionAST *f = d->asFunctionDefinition();
|
||||||
|
QVERIFY(f != nullptr);
|
||||||
|
QVERIFY(f->decl_specifier_list != nullptr);
|
||||||
|
QVERIFY(f->decl_specifier_list->value != nullptr);
|
||||||
|
|
||||||
|
StdAttributeSpecifierAST *attr = f->decl_specifier_list->value->asStdAttributeSpecifier();
|
||||||
|
QVERIFY(attr != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_AST::if_constexpr()
|
||||||
|
{
|
||||||
|
QSharedPointer<TranslationUnit> unit(parseStatement("if constexpr (a) b;",true));
|
||||||
|
|
||||||
|
AST *ast = unit->ast();
|
||||||
|
QVERIFY(ast != 0);
|
||||||
|
|
||||||
|
IfStatementAST *stmt = ast->asIfStatement();
|
||||||
|
QVERIFY(stmt != 0);
|
||||||
|
QCOMPARE(stmt->if_token, 1);
|
||||||
|
QCOMPARE(stmt->constexpr_token, 2);
|
||||||
|
QCOMPARE(stmt->lparen_token, 3);
|
||||||
|
QVERIFY(stmt->condition != 0);
|
||||||
|
QCOMPARE(stmt->rparen_token, 5);
|
||||||
|
QVERIFY(stmt->statement != 0);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_AST::cpp_qproperty()
|
void tst_AST::cpp_qproperty()
|
||||||
{
|
{
|
||||||
QFETCH(QByteArray, source);
|
QFETCH(QByteArray, source);
|
||||||
|
|||||||
@@ -115,6 +115,16 @@ private Q_SLOTS:
|
|||||||
void inAlignas();
|
void inAlignas();
|
||||||
|
|
||||||
void memberAccessAsTemplate();
|
void memberAccessAsTemplate();
|
||||||
|
|
||||||
|
void variadicFunctionTemplate();
|
||||||
|
void typeTemplateParameterWithDefault();
|
||||||
|
void resolveOrder_for_templateFunction_vs_function();
|
||||||
|
void templateArrowOperator_with_defaultType();
|
||||||
|
void templateSpecialization_with_IntArgument();
|
||||||
|
void templateSpecialization_with_BoolArgument();
|
||||||
|
void templatePartialSpecialization();
|
||||||
|
void templatePartialSpecialization_2();
|
||||||
|
void template_SFINAE_1();
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_FindUsages::dump(const QList<Usage> &usages) const
|
void tst_FindUsages::dump(const QList<Usage> &usages) const
|
||||||
@@ -1076,5 +1086,499 @@ void tst_FindUsages::memberAccessAsTemplate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::variadicFunctionTemplate()
|
||||||
|
{
|
||||||
|
const QByteArray src = "struct S{int value;};\n"
|
||||||
|
"template<class ... Types> S foo(Types & ... args){return S();}\n"
|
||||||
|
"int main(){\n"
|
||||||
|
" foo().value;\n"
|
||||||
|
" foo(1).value;\n"
|
||||||
|
" foo(1,2).value;\n"
|
||||||
|
"}";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("variadicFunctionTemplate");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=1);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{ // Test "S::value"
|
||||||
|
Class *c = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(c);
|
||||||
|
QCOMPARE(c->name()->identifier()->chars(), "S");
|
||||||
|
QCOMPARE(c->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *v = c->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(v);
|
||||||
|
QCOMPARE(v->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
find(v);
|
||||||
|
QCOMPARE(find.usages().size(), 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::typeTemplateParameterWithDefault()
|
||||||
|
{
|
||||||
|
const QByteArray src = "struct X{int value;};\n"
|
||||||
|
"struct S{int value;};\n"
|
||||||
|
"template<class T = S> T foo(){return T();}\n"
|
||||||
|
"int main(){\n"
|
||||||
|
" foo<X>().value;\n"
|
||||||
|
" foo<S>().value;\n"
|
||||||
|
" foo().value;\n" // this is S.value
|
||||||
|
"}";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("typeTemplateParameterWithDefault");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=2);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{ // Test "S::value"
|
||||||
|
Class *x = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(x);
|
||||||
|
QCOMPARE(x->name()->identifier()->chars(), "X");
|
||||||
|
QCOMPARE(x->memberCount(), 1);
|
||||||
|
|
||||||
|
Class *s = doc->globalSymbolAt(1)->asClass();
|
||||||
|
QVERIFY(s);
|
||||||
|
QCOMPARE(s->name()->identifier()->chars(), "S");
|
||||||
|
QCOMPARE(s->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *xv = x->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(xv);
|
||||||
|
QCOMPARE(xv->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
Declaration *sv = s->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
find(xv);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::resolveOrder_for_templateFunction_vs_function()
|
||||||
|
{
|
||||||
|
const QByteArray src = "struct X{int value;};\n"
|
||||||
|
"struct S{int value;};\n"
|
||||||
|
"X foo(){return X();}\n"
|
||||||
|
"template<class T = S> T foo(){return T();}\n"
|
||||||
|
"int main(){\n"
|
||||||
|
" foo().value;\n" // this is X.value
|
||||||
|
"}";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("resolveOrder_for_templateFunction_vs_function");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=1);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{ // Test "S::value"
|
||||||
|
Class *x = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(x);
|
||||||
|
QCOMPARE(x->name()->identifier()->chars(), "X");
|
||||||
|
QCOMPARE(x->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *xv = x->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(xv);
|
||||||
|
QCOMPARE(xv->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
find(xv);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::templateArrowOperator_with_defaultType()
|
||||||
|
{
|
||||||
|
const QByteArray src = "struct S{int value;};\n"
|
||||||
|
"struct C{\n"
|
||||||
|
" S* s;\n"
|
||||||
|
" template<class T = S> \n"
|
||||||
|
" T* operator->(){return &s;}\n"
|
||||||
|
"};\n"
|
||||||
|
"int main(){\n"
|
||||||
|
" C().operator -> ()->value;\n"
|
||||||
|
" C()->value;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("templateArrowOperator_with_defaultType");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=1);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{ // Test "S::value"
|
||||||
|
Class *s = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(s);
|
||||||
|
QCOMPARE(s->name()->identifier()->chars(), "S");
|
||||||
|
QCOMPARE(s->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv = s->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::templateSpecialization_with_IntArgument()
|
||||||
|
{
|
||||||
|
const QByteArray src = "\n"
|
||||||
|
"struct S0{ int value = 0; };\n"
|
||||||
|
"struct S1{ int value = 1; };\n"
|
||||||
|
"struct S2{ int value = 2; };\n"
|
||||||
|
"template<int N> struct S { S0 s; };\n"
|
||||||
|
"template<> struct S<1> { S1 s; };\n"
|
||||||
|
"template<> struct S<2> { S2 s; };\n"
|
||||||
|
"int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" S<0> s0;\n"
|
||||||
|
" S<1> s1;\n"
|
||||||
|
" S<2> s2;\n"
|
||||||
|
" s0.s.value;\n"
|
||||||
|
" s1.s.value;\n"
|
||||||
|
" s2.s.value;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("templateSpecialization_with_IntArgument");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=3);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{
|
||||||
|
Class *s[3] = {
|
||||||
|
doc->globalSymbolAt(0)->asClass(),
|
||||||
|
doc->globalSymbolAt(1)->asClass(),
|
||||||
|
doc->globalSymbolAt(2)->asClass(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(s[0]);
|
||||||
|
QVERIFY(s[1]);
|
||||||
|
QVERIFY(s[2]);
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->name()->identifier()->chars(), "S0");
|
||||||
|
QCOMPARE(s[1]->name()->identifier()->chars(), "S1");
|
||||||
|
QCOMPARE(s[2]->name()->identifier()->chars(), "S2");
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->memberCount(), 1);
|
||||||
|
QCOMPARE(s[1]->memberCount(), 1);
|
||||||
|
QCOMPARE(s[2]->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv[3] = {
|
||||||
|
s[0]->memberAt(0)->asDeclaration(),
|
||||||
|
s[1]->memberAt(0)->asDeclaration(),
|
||||||
|
s[2]->memberAt(0)->asDeclaration(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(sv[0]);
|
||||||
|
QVERIFY(sv[1]);
|
||||||
|
QVERIFY(sv[2]);
|
||||||
|
|
||||||
|
QCOMPARE(sv[0]->name()->identifier()->chars(), "value");
|
||||||
|
QCOMPARE(sv[1]->name()->identifier()->chars(), "value");
|
||||||
|
QCOMPARE(sv[2]->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
|
||||||
|
find(sv[0]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 1);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 12);
|
||||||
|
QCOMPARE(find.usages()[1].col, 9);
|
||||||
|
|
||||||
|
find(sv[1]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 2);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 13);
|
||||||
|
QCOMPARE(find.usages()[1].col, 9);
|
||||||
|
|
||||||
|
find(sv[2]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 3);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 14);
|
||||||
|
QCOMPARE(find.usages()[1].col, 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::templateSpecialization_with_BoolArgument()
|
||||||
|
{
|
||||||
|
const QByteArray src = "\n"
|
||||||
|
"struct S0{ int value = 0; };\n"
|
||||||
|
"struct S1{ int value = 1; };\n"
|
||||||
|
"template<bool B> struct S { S0 s; };\n"
|
||||||
|
"template<> struct S<true> { S1 s; };\n"
|
||||||
|
"int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" S<false> s0;\n"
|
||||||
|
" S<true> s1;\n"
|
||||||
|
" s0.s.value;\n"
|
||||||
|
" s1.s.value;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("templateSpecialization_with_BoolArgument");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=3);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{
|
||||||
|
Class *s[2] = {
|
||||||
|
doc->globalSymbolAt(0)->asClass(),
|
||||||
|
doc->globalSymbolAt(1)->asClass(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(s[0]);
|
||||||
|
QVERIFY(s[1]);
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->name()->identifier()->chars(), "S0");
|
||||||
|
QCOMPARE(s[1]->name()->identifier()->chars(), "S1");
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->memberCount(), 1);
|
||||||
|
QCOMPARE(s[1]->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv[2] = {
|
||||||
|
s[0]->memberAt(0)->asDeclaration(),
|
||||||
|
s[1]->memberAt(0)->asDeclaration(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(sv[0]);
|
||||||
|
QVERIFY(sv[1]);
|
||||||
|
|
||||||
|
QCOMPARE(sv[0]->name()->identifier()->chars(), "value");
|
||||||
|
QCOMPARE(sv[1]->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
|
||||||
|
find(sv[0]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 1);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 9);
|
||||||
|
QCOMPARE(find.usages()[1].col, 9);
|
||||||
|
|
||||||
|
find(sv[1]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 2);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 10);
|
||||||
|
QCOMPARE(find.usages()[1].col, 9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::templatePartialSpecialization()
|
||||||
|
{
|
||||||
|
const QByteArray src = "\n"
|
||||||
|
"struct S0{ int value = 0; };\n"
|
||||||
|
"struct S1{ int value = 1; };\n"
|
||||||
|
"template<class T, class U> struct S { S0 ss; };\n"
|
||||||
|
"template<class U> struct S<float, U> { S1 ss; };\n"
|
||||||
|
"int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" S<int, int> s0;\n"
|
||||||
|
" S<float, int> s1;\n"
|
||||||
|
" s0.ss.value;\n"
|
||||||
|
" s1.ss.value;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("templatePartialSpecialization");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=3);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
{
|
||||||
|
Class *s[2] = {
|
||||||
|
doc->globalSymbolAt(0)->asClass(),
|
||||||
|
doc->globalSymbolAt(1)->asClass(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(s[0]);
|
||||||
|
QVERIFY(s[1]);
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->name()->identifier()->chars(), "S0");
|
||||||
|
QCOMPARE(s[1]->name()->identifier()->chars(), "S1");
|
||||||
|
|
||||||
|
QCOMPARE(s[0]->memberCount(), 1);
|
||||||
|
QCOMPARE(s[1]->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv[2] = {
|
||||||
|
s[0]->memberAt(0)->asDeclaration(),
|
||||||
|
s[1]->memberAt(0)->asDeclaration(),
|
||||||
|
};
|
||||||
|
|
||||||
|
QVERIFY(sv[0]);
|
||||||
|
QVERIFY(sv[1]);
|
||||||
|
|
||||||
|
QCOMPARE(sv[0]->name()->identifier()->chars(), "value");
|
||||||
|
QCOMPARE(sv[1]->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
|
||||||
|
find(sv[0]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 1);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 9);
|
||||||
|
QCOMPARE(find.usages()[1].col, 10);
|
||||||
|
|
||||||
|
find(sv[1]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
QCOMPARE(find.usages()[0].line, 2);
|
||||||
|
QCOMPARE(find.usages()[0].col, 15);
|
||||||
|
QCOMPARE(find.usages()[1].line, 10);
|
||||||
|
QCOMPARE(find.usages()[1].col, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::templatePartialSpecialization_2()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
R"(
|
||||||
|
struct S0{int value=0;};
|
||||||
|
struct S1{int value=1;};
|
||||||
|
struct S2{int value=2;};
|
||||||
|
template<class T1, class T2> struct S{T1 ss;};
|
||||||
|
template<class U> struct S<int, U>{ U ss; };
|
||||||
|
template<class V> struct S<V*, int>{ V *ss; };
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
S<S0, float> s0;
|
||||||
|
s0.ss.value;
|
||||||
|
S<int, S1> s1;
|
||||||
|
s1.ss.value;
|
||||||
|
S<S2*, int> s2;
|
||||||
|
s2.ss->value;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("templatePartialSpecialization_2");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=3);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
|
||||||
|
Class *s[3];
|
||||||
|
Declaration *sv[3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
s[i] = doc->globalSymbolAt(i)->asClass();
|
||||||
|
QVERIFY(s[i]);
|
||||||
|
QCOMPARE(s[i]->memberCount(), 1);
|
||||||
|
sv[i] = s[i]->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv[i]);
|
||||||
|
QCOMPARE(sv[i]->name()->identifier()->chars(), "value");
|
||||||
|
}
|
||||||
|
QCOMPARE(s[0]->name()->identifier()->chars(), "S0");
|
||||||
|
QCOMPARE(s[1]->name()->identifier()->chars(), "S1");
|
||||||
|
QCOMPARE(s[2]->name()->identifier()->chars(), "S2");
|
||||||
|
|
||||||
|
find(sv[0]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
find(sv[1]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
|
||||||
|
find(sv[2]);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_FindUsages::template_SFINAE_1()
|
||||||
|
{
|
||||||
|
const QByteArray src =
|
||||||
|
R"(
|
||||||
|
struct S{int value=1;};
|
||||||
|
template<class, class> struct is_same {};
|
||||||
|
template<class T> struct is_same<T, T> {using type = int;};
|
||||||
|
template<class T = S, typename is_same<T, S>::type = 0> T* foo(){return new T();}
|
||||||
|
int main(){
|
||||||
|
foo()->value;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
Document::Ptr doc = Document::create("template_SFINAE_1");
|
||||||
|
doc->setUtf8Source(src);
|
||||||
|
doc->parse();
|
||||||
|
doc->check();
|
||||||
|
|
||||||
|
QVERIFY(doc->diagnosticMessages().isEmpty());
|
||||||
|
QVERIFY(doc->globalSymbolCount()>=1);
|
||||||
|
|
||||||
|
Snapshot snapshot;
|
||||||
|
snapshot.insert(doc);
|
||||||
|
|
||||||
|
Class *s = doc->globalSymbolAt(0)->asClass();
|
||||||
|
QVERIFY(s);
|
||||||
|
QCOMPARE(s->name()->identifier()->chars(), "S");
|
||||||
|
QCOMPARE(s->memberCount(), 1);
|
||||||
|
|
||||||
|
Declaration *sv = s->memberAt(0)->asDeclaration();
|
||||||
|
QVERIFY(sv);
|
||||||
|
QCOMPARE(sv->name()->identifier()->chars(), "value");
|
||||||
|
|
||||||
|
FindUsages find(src, doc, snapshot);
|
||||||
|
find(sv);
|
||||||
|
QCOMPARE(find.usages().size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_FindUsages)
|
QTEST_APPLESS_MAIN(tst_FindUsages)
|
||||||
#include "tst_findusages.moc"
|
#include "tst_findusages.moc"
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ void tst_Semantic::template_instance_1()
|
|||||||
Declaration *decl = templ->memberAt(1)->asClass()->memberAt(0)->asDeclaration();
|
Declaration *decl = templ->memberAt(1)->asClass()->memberAt(0)->asDeclaration();
|
||||||
QVERIFY(decl);
|
QVERIFY(decl);
|
||||||
|
|
||||||
FullySpecifiedType templArgs[] = {control->integerType(IntegerType::Int)};
|
TemplateArgument templArgs[] = {FullySpecifiedType(control->integerType(IntegerType::Int))};
|
||||||
const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1);
|
const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1);
|
||||||
|
|
||||||
FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control);
|
FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control);
|
||||||
|
|||||||
Reference in New Issue
Block a user