forked from qt-creator/qt-creator
CPlusPlus: Support requires clause in parser
Change-Id: Ice6a7a287453516a1cfc296e2c9f16160b3ea130 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
2
src/libs/3rdparty/cplusplus/AST.cpp
vendored
2
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -911,6 +911,8 @@ int DeclaratorAST::lastToken() const
|
|||||||
return candidate;
|
return candidate;
|
||||||
if (equal_token)
|
if (equal_token)
|
||||||
return equal_token + 1;
|
return equal_token + 1;
|
||||||
|
if (requiresClause)
|
||||||
|
return requiresClause->lastToken();
|
||||||
if (post_attribute_list)
|
if (post_attribute_list)
|
||||||
if (int candidate = post_attribute_list->lastToken())
|
if (int candidate = post_attribute_list->lastToken())
|
||||||
return candidate;
|
return candidate;
|
||||||
|
22
src/libs/3rdparty/cplusplus/AST.h
vendored
22
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -340,6 +340,7 @@ public:
|
|||||||
virtual TypeofSpecifierAST *asTypeofSpecifier() { return nullptr; }
|
virtual TypeofSpecifierAST *asTypeofSpecifier() { return nullptr; }
|
||||||
virtual UnaryExpressionAST *asUnaryExpression() { return nullptr; }
|
virtual UnaryExpressionAST *asUnaryExpression() { return nullptr; }
|
||||||
virtual RequiresExpressionAST *asRequiresExpression() { return nullptr; }
|
virtual RequiresExpressionAST *asRequiresExpression() { return nullptr; }
|
||||||
|
virtual RequiresClauseAST *asRequiresClause() { return nullptr; }
|
||||||
virtual UsingAST *asUsing() { return nullptr; }
|
virtual UsingAST *asUsing() { return nullptr; }
|
||||||
virtual UsingDirectiveAST *asUsingDirective() { return nullptr; }
|
virtual UsingDirectiveAST *asUsingDirective() { return nullptr; }
|
||||||
virtual WhileStatementAST *asWhileStatement() { return nullptr; }
|
virtual WhileStatementAST *asWhileStatement() { return nullptr; }
|
||||||
@@ -693,6 +694,7 @@ public:
|
|||||||
SpecifierListAST *post_attribute_list = nullptr;
|
SpecifierListAST *post_attribute_list = nullptr;
|
||||||
int equal_token = 0;
|
int equal_token = 0;
|
||||||
ExpressionAST *initializer = nullptr;
|
ExpressionAST *initializer = nullptr;
|
||||||
|
RequiresClauseAST *requiresClause = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeclaratorAST *asDeclarator() override { return this; }
|
DeclaratorAST *asDeclarator() override { return this; }
|
||||||
@@ -2763,6 +2765,7 @@ public:
|
|||||||
int less_token = 0;
|
int less_token = 0;
|
||||||
DeclarationListAST *template_parameter_list = nullptr;
|
DeclarationListAST *template_parameter_list = nullptr;
|
||||||
int greater_token = 0;
|
int greater_token = 0;
|
||||||
|
RequiresClauseAST *requiresClause = nullptr;
|
||||||
DeclarationAST *declaration = nullptr;
|
DeclarationAST *declaration = nullptr;
|
||||||
|
|
||||||
public: // annotations
|
public: // annotations
|
||||||
@@ -3020,6 +3023,25 @@ protected:
|
|||||||
bool match0(AST *, ASTMatcher *) override;
|
bool match0(AST *, ASTMatcher *) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CPLUSPLUS_EXPORT RequiresClauseAST: public AST
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int requires_token = 0;
|
||||||
|
ExpressionAST *constraint = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RequiresClauseAST *asRequiresClause() override { return this; }
|
||||||
|
|
||||||
|
int firstToken() const override { return requires_token; }
|
||||||
|
int lastToken() const override { return constraint->lastToken(); }
|
||||||
|
|
||||||
|
RequiresClauseAST *clone(MemoryPool *pool) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void accept0(ASTVisitor *visitor) override;
|
||||||
|
bool match0(AST *, ASTMatcher *) override;
|
||||||
|
};
|
||||||
|
|
||||||
class CPLUSPLUS_EXPORT UsingAST: public DeclarationAST
|
class CPLUSPLUS_EXPORT UsingAST: public DeclarationAST
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
11
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
11
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -1305,6 +1305,8 @@ TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
|
|||||||
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
|
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
|
||||||
*ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : nullptr);
|
*ast_iter = new (pool) DeclarationListAST((iter->value) ? iter->value->clone(pool) : nullptr);
|
||||||
ast->greater_token = greater_token;
|
ast->greater_token = greater_token;
|
||||||
|
if (requiresClause)
|
||||||
|
ast->requiresClause = requiresClause->clone(pool);
|
||||||
if (declaration)
|
if (declaration)
|
||||||
ast->declaration = declaration->clone(pool);
|
ast->declaration = declaration->clone(pool);
|
||||||
return ast;
|
return ast;
|
||||||
@@ -1338,6 +1340,15 @@ RequiresExpressionAST *RequiresExpressionAST::clone(MemoryPool *pool) const
|
|||||||
return ast;
|
return ast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RequiresClauseAST *RequiresClauseAST::clone(MemoryPool *pool) const
|
||||||
|
{
|
||||||
|
const auto ast = new (pool) RequiresClauseAST;
|
||||||
|
ast->requires_token = requires_token;
|
||||||
|
if (constraint)
|
||||||
|
ast->constraint = constraint->clone(pool);
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
|
ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
|
||||||
{
|
{
|
||||||
ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
|
ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
|
||||||
|
7
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
7
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -926,6 +926,13 @@ bool RequiresExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RequiresClauseAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||||
|
{
|
||||||
|
if (const auto other = pattern->asRequiresClause())
|
||||||
|
return matcher->match(this, other);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
|
bool ThrowExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||||
{
|
{
|
||||||
if (ThrowExpressionAST *_other = pattern->asThrowExpression())
|
if (ThrowExpressionAST *_other = pattern->asThrowExpression())
|
||||||
|
15
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
15
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -2205,6 +2205,11 @@ bool ASTMatcher::match(TemplateDeclarationAST *node, TemplateDeclarationAST *pat
|
|||||||
|
|
||||||
pattern->greater_token = node->greater_token;
|
pattern->greater_token = node->greater_token;
|
||||||
|
|
||||||
|
if (! pattern->requiresClause)
|
||||||
|
pattern->requiresClause = node->requiresClause;
|
||||||
|
else if (! AST::match(node->requiresClause, pattern->requiresClause, this))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (! pattern->declaration)
|
if (! pattern->declaration)
|
||||||
pattern->declaration = node->declaration;
|
pattern->declaration = node->declaration;
|
||||||
else if (! AST::match(node->declaration, pattern->declaration, this))
|
else if (! AST::match(node->declaration, pattern->declaration, this))
|
||||||
@@ -2247,6 +2252,16 @@ bool ASTMatcher::match(RequiresExpressionAST *node, RequiresExpressionAST *patte
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ASTMatcher::match(RequiresClauseAST *node, RequiresClauseAST *pattern)
|
||||||
|
{
|
||||||
|
pattern->requires_token = node->requires_token;
|
||||||
|
if (!pattern->constraint)
|
||||||
|
pattern->constraint = node->constraint;
|
||||||
|
else if (!AST::match(node->constraint, pattern->constraint, this))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern)
|
bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern)
|
||||||
{
|
{
|
||||||
(void) node;
|
(void) node;
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
1
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -158,6 +158,7 @@ public:
|
|||||||
virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern);
|
virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern);
|
||||||
virtual bool match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern);
|
virtual bool match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *pattern);
|
||||||
virtual bool match(ReferenceAST *node, ReferenceAST *pattern);
|
virtual bool match(ReferenceAST *node, ReferenceAST *pattern);
|
||||||
|
virtual bool match(RequiresClauseAST *node, RequiresClauseAST *pattern);
|
||||||
virtual bool match(RequiresExpressionAST *node, RequiresExpressionAST *pattern);
|
virtual bool match(RequiresExpressionAST *node, RequiresExpressionAST *pattern);
|
||||||
virtual bool match(ReturnStatementAST *node, ReturnStatementAST *pattern);
|
virtual bool match(ReturnStatementAST *node, ReturnStatementAST *pattern);
|
||||||
virtual bool match(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern);
|
virtual bool match(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern);
|
||||||
|
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
8
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -958,6 +958,7 @@ void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
|
|||||||
{
|
{
|
||||||
if (visitor->visit(this)) {
|
if (visitor->visit(this)) {
|
||||||
accept(template_parameter_list, visitor);
|
accept(template_parameter_list, visitor);
|
||||||
|
accept(requiresClause, visitor);
|
||||||
accept(declaration, visitor);
|
accept(declaration, visitor);
|
||||||
}
|
}
|
||||||
visitor->endVisit(this);
|
visitor->endVisit(this);
|
||||||
@@ -980,6 +981,13 @@ void RequiresExpressionAST::accept0(ASTVisitor *visitor)
|
|||||||
visitor->endVisit(this);
|
visitor->endVisit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RequiresClauseAST::accept0(ASTVisitor *visitor)
|
||||||
|
{
|
||||||
|
if (visitor->visit(this))
|
||||||
|
accept(constraint, visitor);
|
||||||
|
visitor->endVisit(this);
|
||||||
|
}
|
||||||
|
|
||||||
void ThrowExpressionAST::accept0(ASTVisitor *visitor)
|
void ThrowExpressionAST::accept0(ASTVisitor *visitor)
|
||||||
{
|
{
|
||||||
if (visitor->visit(this)) {
|
if (visitor->visit(this)) {
|
||||||
|
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
2
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -201,6 +201,7 @@ public:
|
|||||||
virtual bool visit(RangeBasedForStatementAST *) { return true; }
|
virtual bool visit(RangeBasedForStatementAST *) { return true; }
|
||||||
virtual bool visit(ReferenceAST *) { return true; }
|
virtual bool visit(ReferenceAST *) { return true; }
|
||||||
virtual bool visit(RequiresExpressionAST *) { return true; }
|
virtual bool visit(RequiresExpressionAST *) { return true; }
|
||||||
|
virtual bool visit(RequiresClauseAST *) { return true; }
|
||||||
virtual bool visit(ReturnStatementAST *) { return true; }
|
virtual bool visit(ReturnStatementAST *) { return true; }
|
||||||
virtual bool visit(SimpleDeclarationAST *) { return true; }
|
virtual bool visit(SimpleDeclarationAST *) { return true; }
|
||||||
virtual bool visit(SimpleNameAST *) { return true; }
|
virtual bool visit(SimpleNameAST *) { return true; }
|
||||||
@@ -359,6 +360,7 @@ public:
|
|||||||
virtual void endVisit(RangeBasedForStatementAST *) {}
|
virtual void endVisit(RangeBasedForStatementAST *) {}
|
||||||
virtual void endVisit(ReferenceAST *) {}
|
virtual void endVisit(ReferenceAST *) {}
|
||||||
virtual void endVisit(RequiresExpressionAST *) {}
|
virtual void endVisit(RequiresExpressionAST *) {}
|
||||||
|
virtual void endVisit(RequiresClauseAST *) {}
|
||||||
virtual void endVisit(ReturnStatementAST *) {}
|
virtual void endVisit(ReturnStatementAST *) {}
|
||||||
virtual void endVisit(SimpleDeclarationAST *) {}
|
virtual void endVisit(SimpleDeclarationAST *) {}
|
||||||
virtual void endVisit(SimpleNameAST *) {}
|
virtual void endVisit(SimpleNameAST *) {}
|
||||||
|
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
1
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -167,6 +167,7 @@ class QtPropertyDeclarationItemAST;
|
|||||||
class QualifiedNameAST;
|
class QualifiedNameAST;
|
||||||
class RangeBasedForStatementAST;
|
class RangeBasedForStatementAST;
|
||||||
class ReferenceAST;
|
class ReferenceAST;
|
||||||
|
class RequiresClauseAST;
|
||||||
class RequiresExpressionAST;
|
class RequiresExpressionAST;
|
||||||
class ReturnStatementAST;
|
class ReturnStatementAST;
|
||||||
class SimpleDeclarationAST;
|
class SimpleDeclarationAST;
|
||||||
|
18
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
18
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -1247,6 +1247,8 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
|
|||||||
ast->less_token = consumeToken();
|
ast->less_token = consumeToken();
|
||||||
if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
|
if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
|
||||||
match(T_GREATER, &ast->greater_token);
|
match(T_GREATER, &ast->greater_token);
|
||||||
|
if (!parseRequiresClauseOpt(ast->requiresClause))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (LA()) {
|
while (LA()) {
|
||||||
@@ -1402,6 +1404,20 @@ bool Parser::parseRequirement()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::parseRequiresClauseOpt(RequiresClauseAST *&node)
|
||||||
|
{
|
||||||
|
if (!_languageFeatures.cxx20Enabled)
|
||||||
|
return true;
|
||||||
|
if (LA() != T_REQUIRES)
|
||||||
|
return true;
|
||||||
|
const auto ast = new (_pool) RequiresClauseAST;
|
||||||
|
ast->requires_token = consumeToken();
|
||||||
|
if (!parseLogicalOrExpression(ast->constraint))
|
||||||
|
return false;
|
||||||
|
node = ast;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Parser::parseRequiresExpression(ExpressionAST *&node)
|
bool Parser::parseRequiresExpression(ExpressionAST *&node)
|
||||||
{
|
{
|
||||||
if (!_languageFeatures.cxx20Enabled)
|
if (!_languageFeatures.cxx20Enabled)
|
||||||
@@ -2999,6 +3015,8 @@ bool Parser::parseInitDeclarator(DeclaratorAST *&node, SpecifierListAST *decl_sp
|
|||||||
} else if (node->core_declarator && node->core_declarator->asDecompositionDeclarator()) {
|
} else if (node->core_declarator && node->core_declarator->asDecompositionDeclarator()) {
|
||||||
error(cursor(), "structured binding needs initializer");
|
error(cursor(), "structured binding needs initializer");
|
||||||
return false;
|
return false;
|
||||||
|
} else if (!parseRequiresClauseOpt(node->requiresClause)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
1
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -147,6 +147,7 @@ public:
|
|||||||
bool parsePlaceholderTypeSpecifier(PlaceholderTypeSpecifierAST *&node);
|
bool parsePlaceholderTypeSpecifier(PlaceholderTypeSpecifierAST *&node);
|
||||||
bool parseTypeConstraint(TypeConstraintAST *&node);
|
bool parseTypeConstraint(TypeConstraintAST *&node);
|
||||||
bool parseRequirement();
|
bool parseRequirement();
|
||||||
|
bool parseRequiresClauseOpt(RequiresClauseAST *&node);
|
||||||
bool parseRequiresExpression(ExpressionAST *&node);
|
bool parseRequiresExpression(ExpressionAST *&node);
|
||||||
bool parseTemplateParameter(DeclarationAST *&node);
|
bool parseTemplateParameter(DeclarationAST *&node);
|
||||||
bool parseTemplateParameterList(DeclarationListAST *&node);
|
bool parseTemplateParameterList(DeclarationListAST *&node);
|
||||||
|
@@ -147,6 +147,7 @@ private Q_SLOTS:
|
|||||||
void lambdaType();
|
void lambdaType();
|
||||||
|
|
||||||
void concepts();
|
void concepts();
|
||||||
|
void requiresClause();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -318,5 +319,27 @@ void *func2(IsPointer auto p)
|
|||||||
QVERIFY(!hasErrors);
|
QVERIFY(!hasErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_cxx11::requiresClause()
|
||||||
|
{
|
||||||
|
LanguageFeatures features;
|
||||||
|
features.cxxEnabled = true;
|
||||||
|
features.cxx11Enabled = features.cxx14Enabled = features.cxx20Enabled = true;
|
||||||
|
|
||||||
|
const QString source = R"(
|
||||||
|
template<class T> constexpr bool is_meowable = true;
|
||||||
|
template<class T> constexpr bool is_purrable() { return true; }
|
||||||
|
template<class T> void f(T) requires is_meowable<T>;
|
||||||
|
template<class T> requires is_meowable<T> void g(T) ;
|
||||||
|
template<class T> void h(T) requires (is_purrable<T>());
|
||||||
|
)";
|
||||||
|
QByteArray errors;
|
||||||
|
Document::Ptr doc = Document::create(FilePath::fromPathPart(u"testFile"));
|
||||||
|
processDocument(doc, source.toUtf8(), features, &errors);
|
||||||
|
const bool hasErrors = !errors.isEmpty();
|
||||||
|
if (hasErrors)
|
||||||
|
qDebug() << errors;
|
||||||
|
QVERIFY(!hasErrors);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_cxx11)
|
QTEST_APPLESS_MAIN(tst_cxx11)
|
||||||
#include "tst_cxx11.moc"
|
#include "tst_cxx11.moc"
|
||||||
|
Reference in New Issue
Block a user