CPlusPlus: Handle C++20 concepts in parser

Change-Id: I8c6b8b1ba3f36b83cd1d667bec9830271147b1ac
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:
Christian Kandeler
2023-02-09 15:11:14 +01:00
parent 89a8631784
commit 61de69ea90
15 changed files with 547 additions and 1 deletions

View File

@@ -4634,3 +4634,33 @@ int NoExceptOperatorExpressionAST::lastToken() const
return noexcept_token + 1; return noexcept_token + 1;
return 1; return 1;
} }
int TypeConstraintAST::firstToken() const
{
if (nestedName)
return nestedName->firstToken();
return conceptName->firstToken();
}
int TypeConstraintAST::lastToken() const
{
if (greaterToken)
return greaterToken + 1;
return conceptName->lastToken();
}
int PlaceholderTypeSpecifierAST::firstToken() const
{
if (typeConstraint)
return typeConstraint->firstToken();
if (declTypetoken)
return declTypetoken;
return autoToken;
}
int PlaceholderTypeSpecifierAST::lastToken() const
{
if (rparenToken)
return rparenToken + 1;
return autoToken + 1;
}

View File

@@ -290,6 +290,7 @@ public:
virtual OperatorFunctionIdAST *asOperatorFunctionId() { return nullptr; } virtual OperatorFunctionIdAST *asOperatorFunctionId() { return nullptr; }
virtual ParameterDeclarationAST *asParameterDeclaration() { return nullptr; } virtual ParameterDeclarationAST *asParameterDeclaration() { return nullptr; }
virtual ParameterDeclarationClauseAST *asParameterDeclarationClause() { return nullptr; } virtual ParameterDeclarationClauseAST *asParameterDeclarationClause() { return nullptr; }
virtual PlaceholderTypeSpecifierAST *asPlaceholderTypeSpecifier() { return nullptr; }
virtual PointerAST *asPointer() { return nullptr; } virtual PointerAST *asPointer() { return nullptr; }
virtual PointerLiteralAST *asPointerLiteral() { return nullptr; } virtual PointerLiteralAST *asPointerLiteral() { return nullptr; }
virtual PointerToMemberAST *asPointerToMember() { return nullptr; } virtual PointerToMemberAST *asPointerToMember() { return nullptr; }
@@ -322,6 +323,7 @@ public:
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; }
virtual ConceptDeclarationAST *asConceptDeclaration() { return nullptr; }
virtual TemplateIdAST *asTemplateId() { return nullptr; } virtual TemplateIdAST *asTemplateId() { return nullptr; }
virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return nullptr; } virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return nullptr; }
virtual ThisExpressionAST *asThisExpression() { return nullptr; } virtual ThisExpressionAST *asThisExpression() { return nullptr; }
@@ -329,6 +331,7 @@ public:
virtual TrailingReturnTypeAST *asTrailingReturnType() { return nullptr; } virtual TrailingReturnTypeAST *asTrailingReturnType() { return nullptr; }
virtual TranslationUnitAST *asTranslationUnit() { return nullptr; } virtual TranslationUnitAST *asTranslationUnit() { return nullptr; }
virtual TryBlockStatementAST *asTryBlockStatement() { return nullptr; } virtual TryBlockStatementAST *asTryBlockStatement() { return nullptr; }
virtual TypeConstraintAST *asTypeConstraint() { return nullptr; }
virtual TypeConstructorCallAST *asTypeConstructorCall() { return nullptr; } virtual TypeConstructorCallAST *asTypeConstructorCall() { return nullptr; }
virtual TypeIdAST *asTypeId() { return nullptr; } virtual TypeIdAST *asTypeId() { return nullptr; }
virtual TypeidExpressionAST *asTypeidExpression() { return nullptr; } virtual TypeidExpressionAST *asTypeidExpression() { return nullptr; }
@@ -336,6 +339,7 @@ public:
virtual TypenameTypeParameterAST *asTypenameTypeParameter() { return nullptr; } virtual TypenameTypeParameterAST *asTypenameTypeParameter() { return nullptr; }
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 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; }
@@ -636,6 +640,49 @@ protected:
bool match0(AST *, ASTMatcher *) override; bool match0(AST *, ASTMatcher *) override;
}; };
class CPLUSPLUS_EXPORT TypeConstraintAST: public AST
{
public:
NestedNameSpecifierListAST *nestedName = nullptr;
NameAST *conceptName = nullptr;
int lessToken = 0;
ExpressionListAST *templateArgs = nullptr;
int greaterToken = 0;
TypeConstraintAST *asTypeConstraint() override { return this; }
int firstToken() const override;
int lastToken() const override;
TypeConstraintAST *clone(MemoryPool *pool) const override;
void accept0(ASTVisitor *visitor) override;
bool match0(AST *, ASTMatcher *) override;
};
class CPLUSPLUS_EXPORT PlaceholderTypeSpecifierAST: public SpecifierAST
{
public:
TypeConstraintAST *typeConstraint = nullptr;
int declTypetoken = 0;
int lparenToken = 0;
int decltypeToken = 0;
int autoToken = 0;
int rparenToken = 0;
public:
PlaceholderTypeSpecifierAST *asPlaceholderTypeSpecifier() override { return this; }
int firstToken() const override;
int lastToken() const override;
PlaceholderTypeSpecifierAST *clone(MemoryPool *pool) const override;
protected:
void accept0(ASTVisitor *visitor) override;
bool match0(AST *, ASTMatcher *) override;
};
class CPLUSPLUS_EXPORT DeclaratorAST: public AST class CPLUSPLUS_EXPORT DeclaratorAST: public AST
{ {
public: public:
@@ -2734,6 +2781,29 @@ protected:
bool match0(AST *, ASTMatcher *) override; bool match0(AST *, ASTMatcher *) override;
}; };
class CPLUSPLUS_EXPORT ConceptDeclarationAST: public DeclarationAST
{
public:
int concept_token = 0;
NameAST *name = nullptr;
SpecifierListAST *attributes = nullptr;
int equals_token = 0;
ExpressionAST *constraint = nullptr;
int semicolon_token = 0;
public:
ConceptDeclarationAST *asConceptDeclaration() override { return this; }
int firstToken() const override { return concept_token; }
int lastToken() const override { return semicolon_token + 1; }
ConceptDeclarationAST *clone(MemoryPool *pool) const override;
protected:
void accept0(ASTVisitor *visitor) override;
bool match0(AST *, ASTMatcher *) override;
};
class CPLUSPLUS_EXPORT ThrowExpressionAST: public ExpressionAST class CPLUSPLUS_EXPORT ThrowExpressionAST: public ExpressionAST
{ {
public: public:
@@ -2927,6 +2997,29 @@ protected:
bool match0(AST *, ASTMatcher *) override; bool match0(AST *, ASTMatcher *) override;
}; };
class CPLUSPLUS_EXPORT RequiresExpressionAST: public ExpressionAST
{
public:
int requires_token = 0;
int lparen_token = 0;
ParameterDeclarationClauseAST *parameters = nullptr;
int rparen_token = 0;
int lbrace_token = 0;
int rbrace_token = 0;
public:
RequiresExpressionAST *asRequiresExpression() override { return this; }
int firstToken() const override { return requires_token; }
int lastToken() const override { return rbrace_token + 1; }
RequiresExpressionAST *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:

View File

@@ -141,6 +141,32 @@ DecltypeSpecifierAST *DecltypeSpecifierAST::clone(MemoryPool *pool) const
return ast; return ast;
} }
TypeConstraintAST *TypeConstraintAST::clone(MemoryPool *pool) const
{
const auto ast = new (pool) TypeConstraintAST;
for (NestedNameSpecifierListAST *iter = nestedName, **ast_iter = &ast->nestedName; iter;
iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) NestedNameSpecifierListAST((iter->value) ? iter->value->clone(pool) : nullptr);
ast->lessToken = lessToken;
for (ExpressionListAST *iter = templateArgs, **ast_iter = &ast->templateArgs;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
*ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : nullptr);
ast->greaterToken = greaterToken;
return ast;
}
PlaceholderTypeSpecifierAST *PlaceholderTypeSpecifierAST::clone(MemoryPool *pool) const
{
const auto ast = new (pool) PlaceholderTypeSpecifierAST;
if (typeConstraint)
ast->typeConstraint = typeConstraint->clone(pool);
ast->lparenToken = lparenToken;
ast->declTypetoken = declTypetoken;
ast->autoToken = autoToken;
ast->rparenToken = rparenToken;
return ast;
}
DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const
{ {
DeclaratorAST *ast = new (pool) DeclaratorAST; DeclaratorAST *ast = new (pool) DeclaratorAST;
@@ -1284,6 +1310,34 @@ TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
return ast; return ast;
} }
ConceptDeclarationAST *ConceptDeclarationAST::clone(MemoryPool *pool) const
{
const auto ast = new (pool) ConceptDeclarationAST;
ast->concept_token = concept_token;
ast->name = name->clone(pool);
ast->equals_token = equals_token;
ast->semicolon_token = semicolon_token;
for (SpecifierListAST *iter = attributes, **ast_iter = &ast->attributes;
iter; iter = iter->next, ast_iter = &(*ast_iter)->next) {
*ast_iter = new (pool) SpecifierListAST((iter->value) ? iter->value->clone(pool) : nullptr);
}
ast->constraint = constraint->clone(pool);
return ast;
}
RequiresExpressionAST *RequiresExpressionAST::clone(MemoryPool *pool) const
{
const auto ast = new (pool) RequiresExpressionAST;
ast->requires_token = requires_token;
ast->lparen_token = lparen_token;
if (parameters)
ast->parameters = parameters->clone(pool);
ast->rparen_token = rparen_token;
ast->lbrace_token = lbrace_token;
ast->rbrace_token = rbrace_token;
return ast;
}
ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
{ {
ThrowExpressionAST *ast = new (pool) ThrowExpressionAST; ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;

View File

@@ -112,6 +112,21 @@ bool DecltypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
return false; return false;
} }
bool TypeConstraintAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (const auto _other = pattern->asTypeConstraint())
return matcher->match(this, _other);
return false;
}
bool PlaceholderTypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (const auto _other = pattern->asPlaceholderTypeSpecifier())
return matcher->match(this, _other);
return false;
}
bool DeclaratorAST::match0(AST *pattern, ASTMatcher *matcher) bool DeclaratorAST::match0(AST *pattern, ASTMatcher *matcher)
{ {
if (DeclaratorAST *_other = pattern->asDeclarator()) if (DeclaratorAST *_other = pattern->asDeclarator())
@@ -896,6 +911,21 @@ bool TemplateDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
return false; return false;
} }
bool ConceptDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (ConceptDeclarationAST *_other = pattern->asConceptDeclaration())
return matcher->match(this, _other);
return false;
}
bool RequiresExpressionAST::match0(AST *pattern, ASTMatcher *matcher)
{
if (const auto other = pattern->asRequiresExpression())
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())

View File

@@ -216,6 +216,25 @@ bool ASTMatcher::match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern
return true; return true;
} }
bool ASTMatcher::match(TypeConstraintAST *node, TypeConstraintAST *pattern)
{
if (!pattern->nestedName)
pattern->nestedName = node->nestedName;
else if (!AST::match(node->nestedName, pattern->nestedName, this))
return false;
if (!pattern->conceptName)
pattern->conceptName = node->conceptName;
else if (!AST::match(node->conceptName, pattern->conceptName, this))
return false;
pattern->lessToken = node->lessToken;
if (!pattern->templateArgs)
pattern->templateArgs = node->templateArgs;
else if (!AST::match(node->templateArgs, pattern->templateArgs, this))
return false;
pattern->greaterToken = node->greaterToken;
return true;
}
bool ASTMatcher::match(DeclaratorAST *node, DeclaratorAST *pattern) bool ASTMatcher::match(DeclaratorAST *node, DeclaratorAST *pattern)
{ {
(void) node; (void) node;
@@ -1749,6 +1768,19 @@ bool ASTMatcher::match(ParameterDeclarationClauseAST *node, ParameterDeclaration
return true; return true;
} }
bool ASTMatcher::match(PlaceholderTypeSpecifierAST *node, PlaceholderTypeSpecifierAST *pattern)
{
if (!pattern->typeConstraint)
pattern->typeConstraint = node->typeConstraint;
else if (!AST::match(node->typeConstraint, pattern->typeConstraint, this))
return false;
pattern->declTypetoken = node->declTypetoken;
pattern->lparenToken = node->lparenToken;
pattern->autoToken = node->autoToken;
pattern->rparenToken = node->rparenToken;
return true;
}
bool ASTMatcher::match(CallAST *node, CallAST *pattern) bool ASTMatcher::match(CallAST *node, CallAST *pattern)
{ {
(void) node; (void) node;
@@ -2181,6 +2213,40 @@ bool ASTMatcher::match(TemplateDeclarationAST *node, TemplateDeclarationAST *pat
return true; return true;
} }
bool ASTMatcher::match(ConceptDeclarationAST *node, ConceptDeclarationAST *pattern)
{
pattern->concept_token = node->concept_token;
pattern->equals_token = node->equals_token;
pattern->semicolon_token = node->semicolon_token;
if (!pattern->attributes)
pattern->attributes = node->attributes;
else if (!AST::match(node->attributes, pattern->attributes, this))
return false;
if (!pattern->constraint)
pattern->constraint = node->constraint;
else if (! AST::match(node->constraint, pattern->constraint, this))
return false;
return true;
}
bool ASTMatcher::match(RequiresExpressionAST *node, RequiresExpressionAST *pattern)
{
pattern->requires_token = node->requires_token;
pattern->lparen_token = node->lparen_token;
pattern->lbrace_token = node->lbrace_token;
pattern->rbrace_token = node->rbrace_token;
if (!pattern->parameters)
pattern->parameters = node->parameters;
else if (!AST::match(node->parameters, pattern->parameters, this))
return false;
return true;
}
bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern) bool ASTMatcher::match(ThrowExpressionAST *node, ThrowExpressionAST *pattern)
{ {
(void) node; (void) node;

View File

@@ -54,6 +54,7 @@ public:
virtual bool match(CompoundExpressionAST *node, CompoundExpressionAST *pattern); virtual bool match(CompoundExpressionAST *node, CompoundExpressionAST *pattern);
virtual bool match(CompoundLiteralAST *node, CompoundLiteralAST *pattern); virtual bool match(CompoundLiteralAST *node, CompoundLiteralAST *pattern);
virtual bool match(CompoundStatementAST *node, CompoundStatementAST *pattern); virtual bool match(CompoundStatementAST *node, CompoundStatementAST *pattern);
virtual bool match(ConceptDeclarationAST *node, ConceptDeclarationAST *pattern);
virtual bool match(ConditionAST *node, ConditionAST *pattern); virtual bool match(ConditionAST *node, ConditionAST *pattern);
virtual bool match(ConditionalExpressionAST *node, ConditionalExpressionAST *pattern); virtual bool match(ConditionalExpressionAST *node, ConditionalExpressionAST *pattern);
virtual bool match(ContinueStatementAST *node, ContinueStatementAST *pattern); virtual bool match(ContinueStatementAST *node, ContinueStatementAST *pattern);
@@ -139,6 +140,7 @@ public:
virtual bool match(OperatorFunctionIdAST *node, OperatorFunctionIdAST *pattern); virtual bool match(OperatorFunctionIdAST *node, OperatorFunctionIdAST *pattern);
virtual bool match(ParameterDeclarationAST *node, ParameterDeclarationAST *pattern); virtual bool match(ParameterDeclarationAST *node, ParameterDeclarationAST *pattern);
virtual bool match(ParameterDeclarationClauseAST *node, ParameterDeclarationClauseAST *pattern); virtual bool match(ParameterDeclarationClauseAST *node, ParameterDeclarationClauseAST *pattern);
virtual bool match(PlaceholderTypeSpecifierAST *node, PlaceholderTypeSpecifierAST *pattern);
virtual bool match(PointerAST *node, PointerAST *pattern); virtual bool match(PointerAST *node, PointerAST *pattern);
virtual bool match(PointerLiteralAST *node, PointerLiteralAST *pattern); virtual bool match(PointerLiteralAST *node, PointerLiteralAST *pattern);
virtual bool match(PointerToMemberAST *node, PointerToMemberAST *pattern); virtual bool match(PointerToMemberAST *node, PointerToMemberAST *pattern);
@@ -156,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(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);
virtual bool match(SimpleNameAST *node, SimpleNameAST *pattern); virtual bool match(SimpleNameAST *node, SimpleNameAST *pattern);
@@ -173,6 +176,7 @@ public:
virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern); virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern);
virtual bool match(TranslationUnitAST *node, TranslationUnitAST *pattern); virtual bool match(TranslationUnitAST *node, TranslationUnitAST *pattern);
virtual bool match(TryBlockStatementAST *node, TryBlockStatementAST *pattern); virtual bool match(TryBlockStatementAST *node, TryBlockStatementAST *pattern);
virtual bool match(TypeConstraintAST *node, TypeConstraintAST *pattern);
virtual bool match(TypeConstructorCallAST *node, TypeConstructorCallAST *pattern); virtual bool match(TypeConstructorCallAST *node, TypeConstructorCallAST *pattern);
virtual bool match(TypeIdAST *node, TypeIdAST *pattern); virtual bool match(TypeIdAST *node, TypeIdAST *pattern);
virtual bool match(TypeidExpressionAST *node, TypeidExpressionAST *pattern); virtual bool match(TypeidExpressionAST *node, TypeidExpressionAST *pattern);

View File

@@ -110,6 +110,23 @@ void DecltypeSpecifierAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this); visitor->endVisit(this);
} }
void TypeConstraintAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(nestedName, visitor);
accept(conceptName, visitor);
accept(templateArgs, visitor);
}
visitor->endVisit(this);
}
void PlaceholderTypeSpecifierAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this))
accept(typeConstraint, visitor);
visitor->endVisit(this);
}
void DeclaratorAST::accept0(ASTVisitor *visitor) void DeclaratorAST::accept0(ASTVisitor *visitor)
{ {
if (visitor->visit(this)) { if (visitor->visit(this)) {
@@ -946,6 +963,23 @@ void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
visitor->endVisit(this); visitor->endVisit(this);
} }
void ConceptDeclarationAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this)) {
accept(name, visitor);
accept(attributes, visitor);
accept(constraint, visitor);
}
visitor->endVisit(this);
}
void RequiresExpressionAST::accept0(ASTVisitor *visitor)
{
if (visitor->visit(this))
accept(parameters, visitor);
visitor->endVisit(this);
}
void ThrowExpressionAST::accept0(ASTVisitor *visitor) void ThrowExpressionAST::accept0(ASTVisitor *visitor)
{ {
if (visitor->visit(this)) { if (visitor->visit(this)) {

View File

@@ -96,6 +96,7 @@ public:
virtual bool visit(CompoundExpressionAST *) { return true; } virtual bool visit(CompoundExpressionAST *) { return true; }
virtual bool visit(CompoundLiteralAST *) { return true; } virtual bool visit(CompoundLiteralAST *) { return true; }
virtual bool visit(CompoundStatementAST *) { return true; } virtual bool visit(CompoundStatementAST *) { return true; }
virtual bool visit(ConceptDeclarationAST *) { return true; }
virtual bool visit(ConditionAST *) { return true; } virtual bool visit(ConditionAST *) { return true; }
virtual bool visit(ConditionalExpressionAST *) { return true; } virtual bool visit(ConditionalExpressionAST *) { return true; }
virtual bool visit(ContinueStatementAST *) { return true; } virtual bool visit(ContinueStatementAST *) { return true; }
@@ -181,6 +182,7 @@ public:
virtual bool visit(OperatorFunctionIdAST *) { return true; } virtual bool visit(OperatorFunctionIdAST *) { return true; }
virtual bool visit(ParameterDeclarationAST *) { return true; } virtual bool visit(ParameterDeclarationAST *) { return true; }
virtual bool visit(ParameterDeclarationClauseAST *) { return true; } virtual bool visit(ParameterDeclarationClauseAST *) { return true; }
virtual bool visit(PlaceholderTypeSpecifierAST *) { return true; }
virtual bool visit(PointerAST *) { return true; } virtual bool visit(PointerAST *) { return true; }
virtual bool visit(PointerLiteralAST *) { return true; } virtual bool visit(PointerLiteralAST *) { return true; }
virtual bool visit(PointerToMemberAST *) { return true; } virtual bool visit(PointerToMemberAST *) { return true; }
@@ -198,6 +200,7 @@ public:
virtual bool visit(QualifiedNameAST *) { return true; } virtual bool visit(QualifiedNameAST *) { return true; }
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(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; }
@@ -215,6 +218,7 @@ public:
virtual bool visit(TrailingReturnTypeAST *) { return true; } virtual bool visit(TrailingReturnTypeAST *) { return true; }
virtual bool visit(TranslationUnitAST *) { return true; } virtual bool visit(TranslationUnitAST *) { return true; }
virtual bool visit(TryBlockStatementAST *) { return true; } virtual bool visit(TryBlockStatementAST *) { return true; }
virtual bool visit(TypeConstraintAST *) { return true; }
virtual bool visit(TypeConstructorCallAST *) { return true; } virtual bool visit(TypeConstructorCallAST *) { return true; }
virtual bool visit(TypeIdAST *) { return true; } virtual bool visit(TypeIdAST *) { return true; }
virtual bool visit(TypeidExpressionAST *) { return true; } virtual bool visit(TypeidExpressionAST *) { return true; }
@@ -250,6 +254,7 @@ public:
virtual void endVisit(CompoundExpressionAST *) {} virtual void endVisit(CompoundExpressionAST *) {}
virtual void endVisit(CompoundLiteralAST *) {} virtual void endVisit(CompoundLiteralAST *) {}
virtual void endVisit(CompoundStatementAST *) {} virtual void endVisit(CompoundStatementAST *) {}
virtual void endVisit(ConceptDeclarationAST *) {}
virtual void endVisit(ConditionAST *) {} virtual void endVisit(ConditionAST *) {}
virtual void endVisit(ConditionalExpressionAST *) {} virtual void endVisit(ConditionalExpressionAST *) {}
virtual void endVisit(ContinueStatementAST *) {} virtual void endVisit(ContinueStatementAST *) {}
@@ -335,6 +340,7 @@ public:
virtual void endVisit(OperatorFunctionIdAST *) {} virtual void endVisit(OperatorFunctionIdAST *) {}
virtual void endVisit(ParameterDeclarationAST *) {} virtual void endVisit(ParameterDeclarationAST *) {}
virtual void endVisit(ParameterDeclarationClauseAST *) {} virtual void endVisit(ParameterDeclarationClauseAST *) {}
virtual void endVisit(PlaceholderTypeSpecifierAST *) {}
virtual void endVisit(PointerAST *) {} virtual void endVisit(PointerAST *) {}
virtual void endVisit(PointerLiteralAST *) {} virtual void endVisit(PointerLiteralAST *) {}
virtual void endVisit(PointerToMemberAST *) {} virtual void endVisit(PointerToMemberAST *) {}
@@ -352,6 +358,7 @@ public:
virtual void endVisit(QualifiedNameAST *) {} virtual void endVisit(QualifiedNameAST *) {}
virtual void endVisit(RangeBasedForStatementAST *) {} virtual void endVisit(RangeBasedForStatementAST *) {}
virtual void endVisit(ReferenceAST *) {} virtual void endVisit(ReferenceAST *) {}
virtual void endVisit(RequiresExpressionAST *) {}
virtual void endVisit(ReturnStatementAST *) {} virtual void endVisit(ReturnStatementAST *) {}
virtual void endVisit(SimpleDeclarationAST *) {} virtual void endVisit(SimpleDeclarationAST *) {}
virtual void endVisit(SimpleNameAST *) {} virtual void endVisit(SimpleNameAST *) {}
@@ -369,6 +376,7 @@ public:
virtual void endVisit(TrailingReturnTypeAST *) {} virtual void endVisit(TrailingReturnTypeAST *) {}
virtual void endVisit(TranslationUnitAST *) {} virtual void endVisit(TranslationUnitAST *) {}
virtual void endVisit(TryBlockStatementAST *) {} virtual void endVisit(TryBlockStatementAST *) {}
virtual void endVisit(TypeConstraintAST *) {}
virtual void endVisit(TypeConstructorCallAST *) {} virtual void endVisit(TypeConstructorCallAST *) {}
virtual void endVisit(TypeIdAST *) {} virtual void endVisit(TypeIdAST *) {}
virtual void endVisit(TypeidExpressionAST *) {} virtual void endVisit(TypeidExpressionAST *) {}

View File

@@ -146,6 +146,7 @@ class OperatorAST;
class OperatorFunctionIdAST; class OperatorFunctionIdAST;
class ParameterDeclarationAST; class ParameterDeclarationAST;
class ParameterDeclarationClauseAST; class ParameterDeclarationClauseAST;
class PlaceholderTypeSpecifierAST;
class PointerAST; class PointerAST;
class PointerLiteralAST; class PointerLiteralAST;
class PointerToMemberAST; class PointerToMemberAST;
@@ -166,6 +167,7 @@ class QtPropertyDeclarationItemAST;
class QualifiedNameAST; class QualifiedNameAST;
class RangeBasedForStatementAST; class RangeBasedForStatementAST;
class ReferenceAST; class ReferenceAST;
class RequiresExpressionAST;
class ReturnStatementAST; class ReturnStatementAST;
class SimpleDeclarationAST; class SimpleDeclarationAST;
class SimpleNameAST; class SimpleNameAST;
@@ -178,6 +180,7 @@ class StdAttributeSpecifierAST;
class StringLiteralAST; class StringLiteralAST;
class SwitchStatementAST; class SwitchStatementAST;
class TemplateDeclarationAST; class TemplateDeclarationAST;
class ConceptDeclarationAST;
class TemplateIdAST; class TemplateIdAST;
class TemplateTypeParameterAST; class TemplateTypeParameterAST;
class ThisExpressionAST; class ThisExpressionAST;
@@ -185,6 +188,7 @@ class ThrowExpressionAST;
class TrailingReturnTypeAST; class TrailingReturnTypeAST;
class TranslationUnitAST; class TranslationUnitAST;
class TryBlockStatementAST; class TryBlockStatementAST;
class TypeConstraintAST;
class TypeConstructorCallAST; class TypeConstructorCallAST;
class TypeIdAST; class TypeIdAST;
class TypeidExpressionAST; class TypeidExpressionAST;

View File

@@ -933,6 +933,11 @@ bool Bind::visit(ParameterDeclarationClauseAST *ast)
return false; return false;
} }
bool Bind::visit(RequiresExpressionAST *)
{
return false;
}
void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lparen_token, Function *fun) void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lparen_token, Function *fun)
{ {
if (! ast) if (! ast)

View File

@@ -128,6 +128,7 @@ protected:
bool visit(NewTypeIdAST *ast) override; bool visit(NewTypeIdAST *ast) override;
bool visit(OperatorAST *ast) override; bool visit(OperatorAST *ast) override;
bool visit(ParameterDeclarationClauseAST *ast) override; bool visit(ParameterDeclarationClauseAST *ast) override;
bool visit(RequiresExpressionAST *ast) override;
bool visit(TranslationUnitAST *ast) override; bool visit(TranslationUnitAST *ast) override;
bool visit(ObjCProtocolRefsAST *ast) override; bool visit(ObjCProtocolRefsAST *ast) override;
bool visit(ObjCMessageArgumentAST *ast) override; bool visit(ObjCMessageArgumentAST *ast) override;

View File

@@ -1255,6 +1255,8 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
ast->declaration = nullptr; ast->declaration = nullptr;
if (parseDeclaration(ast->declaration)) if (parseDeclaration(ast->declaration))
break; break;
if (parseConceptDeclaration(ast->declaration))
break;
error(start_declaration, "expected a declaration"); error(start_declaration, "expected a declaration");
rewind(start_declaration + 1); rewind(start_declaration + 1);
@@ -1265,6 +1267,173 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
return true; return true;
} }
bool Parser::parseConceptDeclaration(DeclarationAST *&node)
{
if (!_languageFeatures.cxx20Enabled)
return false;
if (LA() != T_CONCEPT)
return false;
const auto ast = new (_pool) ConceptDeclarationAST;
ast->concept_token = consumeToken();
if (!parseName(ast->name))
return false;
parseAttributeSpecifier(ast->attributes);
if (LA() != T_EQUAL)
return false;
ast->equals_token = consumeToken();
if (!parseLogicalOrExpression(ast->constraint))
return false;
if (LA() != T_SEMICOLON)
return false;
ast->semicolon_token = consumeToken();
node = ast;
return true;
}
bool Parser::parsePlaceholderTypeSpecifier(PlaceholderTypeSpecifierAST *&node)
{
if ((lookAtBuiltinTypeSpecifier() || _translationUnit->tokenAt(_tokenIndex).isKeyword())
&& (LA() != T_AUTO && LA() != T_DECLTYPE)) {
return false;
}
TypeConstraintAST *typeConstraint = nullptr;
const int savedCursor = cursor();
parseTypeConstraint(typeConstraint);
if (LA() != T_AUTO && (LA() != T_DECLTYPE || LA(1) != T_LPAREN || LA(2) != T_AUTO)) {
rewind(savedCursor);
return false;
}
const auto spec = new (_pool) PlaceholderTypeSpecifierAST;
spec->typeConstraint = typeConstraint;
if (LA() == T_DECLTYPE) {
spec->declTypetoken = consumeToken();
if (LA() != T_LPAREN)
return false;
spec->lparenToken = consumeToken();
if (LA() != T_AUTO)
return false;
spec->autoToken = consumeToken();
if (LA() != T_RPAREN)
return false;
spec->rparenToken = consumeToken();
} else {
spec->autoToken = consumeToken();
}
node = spec;
return true;
}
bool Parser::parseTypeConstraint(TypeConstraintAST *&node)
{
NestedNameSpecifierListAST *nestedName = nullptr;
parseNestedNameSpecifierOpt(nestedName, true);
NameAST *conceptName = nullptr;
if (!parseUnqualifiedName(conceptName, true))
return false;
const auto typeConstraint = new (_pool) TypeConstraintAST;
typeConstraint->nestedName = nestedName;
typeConstraint->conceptName = conceptName;
if (LA() != T_LESS)
return true;
typeConstraint->lessToken = consumeToken();
if (LA() != T_GREATER) {
if (!parseTemplateArgumentList(typeConstraint->templateArgs))
return false;
}
if (LA() != T_GREATER)
return false;
typeConstraint->greaterToken = consumeToken();
node = typeConstraint;
return true;
}
bool Parser::parseRequirement()
{
if (LA() == T_TYPENAME) { // type-requirement
consumeToken();
NameAST *name = nullptr;
if (!parseName(name, true))
return false;
if (LA() != T_SEMICOLON)
return false;
consumeToken();
return true;
}
if (LA() == T_LBRACE) { // compound-requirement
consumeToken();
ExpressionAST *expr = nullptr;
if (!parseExpression(expr))
return false;
if (LA() != T_RBRACE)
return false;
consumeToken();
if (LA() == T_NOEXCEPT)
consumeToken();
if (LA() == T_SEMICOLON) {
consumeToken();
return true;
}
TypeConstraintAST *typeConstraint = nullptr;
if (!parseTypeConstraint(typeConstraint))
return false;
if (LA() != T_SEMICOLON)
return false;
consumeToken();
return true;
}
if (LA() == T_REQUIRES) { // nested-requirement
consumeToken();
ExpressionAST *constraintExpr = nullptr;
if (!parseLogicalOrExpression(constraintExpr))
return false;
if (LA() != T_SEMICOLON)
return false;
consumeToken();
return true;
}
ExpressionAST *simpleExpr;
if (!parseExpression(simpleExpr)) // simple-requirement
return false;
if (LA() != T_SEMICOLON)
return false;
consumeToken();
return true;
}
bool Parser::parseRequiresExpression(ExpressionAST *&node)
{
if (!_languageFeatures.cxx20Enabled)
return false;
if (LA() != T_REQUIRES)
return false;
const auto ast = new (_pool) RequiresExpressionAST;
ast->requires_token = consumeToken();
if (LA() == T_LPAREN) {
ast->lparen_token = consumeToken();
if (!parseParameterDeclarationClause(ast->parameters))
return false;
if (LA() != T_RPAREN)
return false;
ast->rparen_token = consumeToken();
}
if (LA() != T_LBRACE)
return false;
ast->lbrace_token = consumeToken();
if (!parseRequirement())
return false;
while (LA() != T_RBRACE) {
if (!parseRequirement())
return false;
}
ast->rbrace_token = consumeToken();
node = ast;
return true;
}
bool Parser::parseOperator(OperatorAST *&node) // ### FIXME bool Parser::parseOperator(OperatorAST *&node) // ### FIXME
{ {
DEBUG_THIS_RULE(); DEBUG_THIS_RULE();
@@ -1500,6 +1669,14 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
NameAST *named_type_specifier = nullptr; NameAST *named_type_specifier = nullptr;
SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq; SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
for (;;) { for (;;) {
PlaceholderTypeSpecifierAST *placeholderSpec = nullptr;
// A simple auto is also technically a placeholder-type-specifier, but for historical
// reasons, it is handled further below.
if (LA() != T_AUTO && parsePlaceholderTypeSpecifier(placeholderSpec)) {
*decl_specifier_seq_ptr = new (_pool) SpecifierListAST(placeholderSpec);
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
continue;
}
if (! noStorageSpecifiers && ! onlySimpleTypeSpecifiers && lookAtStorageClassSpecifier()) { if (! noStorageSpecifiers && ! onlySimpleTypeSpecifiers && lookAtStorageClassSpecifier()) {
// storage-class-specifier // storage-class-specifier
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST; SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
@@ -1550,8 +1727,9 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
} }
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next; decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
has_type_specifier = true; has_type_specifier = true;
} else } else {
break; break;
}
} }
return decl_specifier_seq != nullptr; return decl_specifier_seq != nullptr;
@@ -1694,6 +1872,8 @@ bool Parser::hasAuto(SpecifierListAST *decl_specifier_list) const
if (_translationUnit->tokenKind(simpleSpec->specifier_token) == T_AUTO) if (_translationUnit->tokenKind(simpleSpec->specifier_token) == T_AUTO)
return true; return true;
} }
if (spec->asPlaceholderTypeSpecifier())
return true;
} }
return false; return false;
} }
@@ -4731,6 +4911,9 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node)
case T_AT_SELECTOR: case T_AT_SELECTOR:
return parseObjCExpression(node); return parseObjCExpression(node);
case T_REQUIRES:
return parseRequiresExpression(node);
default: { default: {
NameAST *name = nullptr; NameAST *name = nullptr;
if (parseNameId(name)) { if (parseNameId(name)) {

View File

@@ -143,6 +143,11 @@ public:
bool parseTemplateArgument(ExpressionAST *&node); bool parseTemplateArgument(ExpressionAST *&node);
bool parseTemplateArgumentList(ExpressionListAST *&node); bool parseTemplateArgumentList(ExpressionListAST *&node);
bool parseTemplateDeclaration(DeclarationAST *&node); bool parseTemplateDeclaration(DeclarationAST *&node);
bool parseConceptDeclaration(DeclarationAST *&node);
bool parsePlaceholderTypeSpecifier(PlaceholderTypeSpecifierAST *&node);
bool parseTypeConstraint(TypeConstraintAST *&node);
bool parseRequirement();
bool parseRequiresExpression(ExpressionAST *&node);
bool parseTemplateParameter(DeclarationAST *&node); bool parseTemplateParameter(DeclarationAST *&node);
bool parseTemplateParameterList(DeclarationListAST *&node); bool parseTemplateParameterList(DeclarationListAST *&node);
bool parseThrowExpression(ExpressionAST *&node); bool parseThrowExpression(ExpressionAST *&node);

View File

@@ -70,6 +70,10 @@ public:
// Get Document // Get Document
const Document::Ptr document = waitForFileInGlobalSnapshot(filePath); const Document::Ptr document = waitForFileInGlobalSnapshot(filePath);
QVERIFY(document); QVERIFY(document);
if (!document->diagnosticMessages().isEmpty()) {
for (const Document::DiagnosticMessage &m : document->diagnosticMessages())
qDebug().noquote() << m.text();
}
QVERIFY(document->diagnosticMessages().isEmpty()); QVERIFY(document->diagnosticMessages().isEmpty());
m_snapshot.insert(document); m_snapshot.insert(document);

View File

@@ -145,6 +145,8 @@ private Q_SLOTS:
void lambdaType_data(); void lambdaType_data();
void lambdaType(); void lambdaType();
void concepts();
}; };
@@ -293,5 +295,28 @@ void tst_cxx11::lambdaType()
QCOMPARE(oo.prettyType(function->type()), expectedType); QCOMPARE(oo.prettyType(function->type()), expectedType);
} }
void tst_cxx11::concepts()
{
LanguageFeatures features;
features.cxxEnabled = true;
features.cxx11Enabled = features.cxx14Enabled = features.cxx20Enabled = true;
const QString source = R"(
template<typename T> concept IsPointer = requires(T p) { *p; };
template<IsPointer T> void* func(T p) { return p; }
void *func2(IsPointer auto p)
{
return p;
}
)";
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"