forked from qt-creator/qt-creator
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:
30
src/libs/3rdparty/cplusplus/AST.cpp
vendored
30
src/libs/3rdparty/cplusplus/AST.cpp
vendored
@@ -4634,3 +4634,33 @@ int NoExceptOperatorExpressionAST::lastToken() const
|
||||
return noexcept_token + 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;
|
||||
}
|
||||
|
||||
93
src/libs/3rdparty/cplusplus/AST.h
vendored
93
src/libs/3rdparty/cplusplus/AST.h
vendored
@@ -290,6 +290,7 @@ public:
|
||||
virtual OperatorFunctionIdAST *asOperatorFunctionId() { return nullptr; }
|
||||
virtual ParameterDeclarationAST *asParameterDeclaration() { return nullptr; }
|
||||
virtual ParameterDeclarationClauseAST *asParameterDeclarationClause() { return nullptr; }
|
||||
virtual PlaceholderTypeSpecifierAST *asPlaceholderTypeSpecifier() { return nullptr; }
|
||||
virtual PointerAST *asPointer() { return nullptr; }
|
||||
virtual PointerLiteralAST *asPointerLiteral() { return nullptr; }
|
||||
virtual PointerToMemberAST *asPointerToMember() { return nullptr; }
|
||||
@@ -322,6 +323,7 @@ public:
|
||||
virtual StringLiteralAST *asStringLiteral() { return nullptr; }
|
||||
virtual SwitchStatementAST *asSwitchStatement() { return nullptr; }
|
||||
virtual TemplateDeclarationAST *asTemplateDeclaration() { return nullptr; }
|
||||
virtual ConceptDeclarationAST *asConceptDeclaration() { return nullptr; }
|
||||
virtual TemplateIdAST *asTemplateId() { return nullptr; }
|
||||
virtual TemplateTypeParameterAST *asTemplateTypeParameter() { return nullptr; }
|
||||
virtual ThisExpressionAST *asThisExpression() { return nullptr; }
|
||||
@@ -329,6 +331,7 @@ public:
|
||||
virtual TrailingReturnTypeAST *asTrailingReturnType() { return nullptr; }
|
||||
virtual TranslationUnitAST *asTranslationUnit() { return nullptr; }
|
||||
virtual TryBlockStatementAST *asTryBlockStatement() { return nullptr; }
|
||||
virtual TypeConstraintAST *asTypeConstraint() { return nullptr; }
|
||||
virtual TypeConstructorCallAST *asTypeConstructorCall() { return nullptr; }
|
||||
virtual TypeIdAST *asTypeId() { return nullptr; }
|
||||
virtual TypeidExpressionAST *asTypeidExpression() { return nullptr; }
|
||||
@@ -336,6 +339,7 @@ public:
|
||||
virtual TypenameTypeParameterAST *asTypenameTypeParameter() { return nullptr; }
|
||||
virtual TypeofSpecifierAST *asTypeofSpecifier() { return nullptr; }
|
||||
virtual UnaryExpressionAST *asUnaryExpression() { return nullptr; }
|
||||
virtual RequiresExpressionAST *asRequiresExpression() { return nullptr; }
|
||||
virtual UsingAST *asUsing() { return nullptr; }
|
||||
virtual UsingDirectiveAST *asUsingDirective() { return nullptr; }
|
||||
virtual WhileStatementAST *asWhileStatement() { return nullptr; }
|
||||
@@ -636,6 +640,49 @@ protected:
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -2734,6 +2781,29 @@ protected:
|
||||
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
|
||||
{
|
||||
public:
|
||||
@@ -2927,6 +2997,29 @@ protected:
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
||||
54
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
54
src/libs/3rdparty/cplusplus/ASTClone.cpp
vendored
@@ -141,6 +141,32 @@ DecltypeSpecifierAST *DecltypeSpecifierAST::clone(MemoryPool *pool) const
|
||||
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 *ast = new (pool) DeclaratorAST;
|
||||
@@ -1284,6 +1310,34 @@ TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
|
||||
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 *ast = new (pool) ThrowExpressionAST;
|
||||
|
||||
30
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
30
src/libs/3rdparty/cplusplus/ASTMatch0.cpp
vendored
@@ -112,6 +112,21 @@ bool DecltypeSpecifierAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
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)
|
||||
{
|
||||
if (DeclaratorAST *_other = pattern->asDeclarator())
|
||||
@@ -896,6 +911,21 @@ bool TemplateDeclarationAST::match0(AST *pattern, ASTMatcher *matcher)
|
||||
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)
|
||||
{
|
||||
if (ThrowExpressionAST *_other = pattern->asThrowExpression())
|
||||
|
||||
66
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
66
src/libs/3rdparty/cplusplus/ASTMatcher.cpp
vendored
@@ -216,6 +216,25 @@ bool ASTMatcher::match(DecltypeSpecifierAST *node, DecltypeSpecifierAST *pattern
|
||||
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)
|
||||
{
|
||||
(void) node;
|
||||
@@ -1749,6 +1768,19 @@ bool ASTMatcher::match(ParameterDeclarationClauseAST *node, ParameterDeclaration
|
||||
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)
|
||||
{
|
||||
(void) node;
|
||||
@@ -2181,6 +2213,40 @@ bool ASTMatcher::match(TemplateDeclarationAST *node, TemplateDeclarationAST *pat
|
||||
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)
|
||||
{
|
||||
(void) node;
|
||||
|
||||
4
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
4
src/libs/3rdparty/cplusplus/ASTMatcher.h
vendored
@@ -54,6 +54,7 @@ public:
|
||||
virtual bool match(CompoundExpressionAST *node, CompoundExpressionAST *pattern);
|
||||
virtual bool match(CompoundLiteralAST *node, CompoundLiteralAST *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(ConditionalExpressionAST *node, ConditionalExpressionAST *pattern);
|
||||
virtual bool match(ContinueStatementAST *node, ContinueStatementAST *pattern);
|
||||
@@ -139,6 +140,7 @@ public:
|
||||
virtual bool match(OperatorFunctionIdAST *node, OperatorFunctionIdAST *pattern);
|
||||
virtual bool match(ParameterDeclarationAST *node, ParameterDeclarationAST *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(PointerLiteralAST *node, PointerLiteralAST *pattern);
|
||||
virtual bool match(PointerToMemberAST *node, PointerToMemberAST *pattern);
|
||||
@@ -156,6 +158,7 @@ public:
|
||||
virtual bool match(QualifiedNameAST *node, QualifiedNameAST *pattern);
|
||||
virtual bool match(RangeBasedForStatementAST *node, RangeBasedForStatementAST *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(SimpleDeclarationAST *node, SimpleDeclarationAST *pattern);
|
||||
virtual bool match(SimpleNameAST *node, SimpleNameAST *pattern);
|
||||
@@ -173,6 +176,7 @@ public:
|
||||
virtual bool match(TrailingReturnTypeAST *node, TrailingReturnTypeAST *pattern);
|
||||
virtual bool match(TranslationUnitAST *node, TranslationUnitAST *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(TypeIdAST *node, TypeIdAST *pattern);
|
||||
virtual bool match(TypeidExpressionAST *node, TypeidExpressionAST *pattern);
|
||||
|
||||
34
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
34
src/libs/3rdparty/cplusplus/ASTVisit.cpp
vendored
@@ -110,6 +110,23 @@ void DecltypeSpecifierAST::accept0(ASTVisitor *visitor)
|
||||
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)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
@@ -946,6 +963,23 @@ void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
|
||||
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)
|
||||
{
|
||||
if (visitor->visit(this)) {
|
||||
|
||||
8
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
8
src/libs/3rdparty/cplusplus/ASTVisitor.h
vendored
@@ -96,6 +96,7 @@ public:
|
||||
virtual bool visit(CompoundExpressionAST *) { return true; }
|
||||
virtual bool visit(CompoundLiteralAST *) { return true; }
|
||||
virtual bool visit(CompoundStatementAST *) { return true; }
|
||||
virtual bool visit(ConceptDeclarationAST *) { return true; }
|
||||
virtual bool visit(ConditionAST *) { return true; }
|
||||
virtual bool visit(ConditionalExpressionAST *) { return true; }
|
||||
virtual bool visit(ContinueStatementAST *) { return true; }
|
||||
@@ -181,6 +182,7 @@ public:
|
||||
virtual bool visit(OperatorFunctionIdAST *) { return true; }
|
||||
virtual bool visit(ParameterDeclarationAST *) { return true; }
|
||||
virtual bool visit(ParameterDeclarationClauseAST *) { return true; }
|
||||
virtual bool visit(PlaceholderTypeSpecifierAST *) { return true; }
|
||||
virtual bool visit(PointerAST *) { return true; }
|
||||
virtual bool visit(PointerLiteralAST *) { return true; }
|
||||
virtual bool visit(PointerToMemberAST *) { return true; }
|
||||
@@ -198,6 +200,7 @@ public:
|
||||
virtual bool visit(QualifiedNameAST *) { return true; }
|
||||
virtual bool visit(RangeBasedForStatementAST *) { return true; }
|
||||
virtual bool visit(ReferenceAST *) { return true; }
|
||||
virtual bool visit(RequiresExpressionAST *) { return true; }
|
||||
virtual bool visit(ReturnStatementAST *) { return true; }
|
||||
virtual bool visit(SimpleDeclarationAST *) { return true; }
|
||||
virtual bool visit(SimpleNameAST *) { return true; }
|
||||
@@ -215,6 +218,7 @@ public:
|
||||
virtual bool visit(TrailingReturnTypeAST *) { return true; }
|
||||
virtual bool visit(TranslationUnitAST *) { return true; }
|
||||
virtual bool visit(TryBlockStatementAST *) { return true; }
|
||||
virtual bool visit(TypeConstraintAST *) { return true; }
|
||||
virtual bool visit(TypeConstructorCallAST *) { return true; }
|
||||
virtual bool visit(TypeIdAST *) { return true; }
|
||||
virtual bool visit(TypeidExpressionAST *) { return true; }
|
||||
@@ -250,6 +254,7 @@ public:
|
||||
virtual void endVisit(CompoundExpressionAST *) {}
|
||||
virtual void endVisit(CompoundLiteralAST *) {}
|
||||
virtual void endVisit(CompoundStatementAST *) {}
|
||||
virtual void endVisit(ConceptDeclarationAST *) {}
|
||||
virtual void endVisit(ConditionAST *) {}
|
||||
virtual void endVisit(ConditionalExpressionAST *) {}
|
||||
virtual void endVisit(ContinueStatementAST *) {}
|
||||
@@ -335,6 +340,7 @@ public:
|
||||
virtual void endVisit(OperatorFunctionIdAST *) {}
|
||||
virtual void endVisit(ParameterDeclarationAST *) {}
|
||||
virtual void endVisit(ParameterDeclarationClauseAST *) {}
|
||||
virtual void endVisit(PlaceholderTypeSpecifierAST *) {}
|
||||
virtual void endVisit(PointerAST *) {}
|
||||
virtual void endVisit(PointerLiteralAST *) {}
|
||||
virtual void endVisit(PointerToMemberAST *) {}
|
||||
@@ -352,6 +358,7 @@ public:
|
||||
virtual void endVisit(QualifiedNameAST *) {}
|
||||
virtual void endVisit(RangeBasedForStatementAST *) {}
|
||||
virtual void endVisit(ReferenceAST *) {}
|
||||
virtual void endVisit(RequiresExpressionAST *) {}
|
||||
virtual void endVisit(ReturnStatementAST *) {}
|
||||
virtual void endVisit(SimpleDeclarationAST *) {}
|
||||
virtual void endVisit(SimpleNameAST *) {}
|
||||
@@ -369,6 +376,7 @@ public:
|
||||
virtual void endVisit(TrailingReturnTypeAST *) {}
|
||||
virtual void endVisit(TranslationUnitAST *) {}
|
||||
virtual void endVisit(TryBlockStatementAST *) {}
|
||||
virtual void endVisit(TypeConstraintAST *) {}
|
||||
virtual void endVisit(TypeConstructorCallAST *) {}
|
||||
virtual void endVisit(TypeIdAST *) {}
|
||||
virtual void endVisit(TypeidExpressionAST *) {}
|
||||
|
||||
4
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
4
src/libs/3rdparty/cplusplus/ASTfwd.h
vendored
@@ -146,6 +146,7 @@ class OperatorAST;
|
||||
class OperatorFunctionIdAST;
|
||||
class ParameterDeclarationAST;
|
||||
class ParameterDeclarationClauseAST;
|
||||
class PlaceholderTypeSpecifierAST;
|
||||
class PointerAST;
|
||||
class PointerLiteralAST;
|
||||
class PointerToMemberAST;
|
||||
@@ -166,6 +167,7 @@ class QtPropertyDeclarationItemAST;
|
||||
class QualifiedNameAST;
|
||||
class RangeBasedForStatementAST;
|
||||
class ReferenceAST;
|
||||
class RequiresExpressionAST;
|
||||
class ReturnStatementAST;
|
||||
class SimpleDeclarationAST;
|
||||
class SimpleNameAST;
|
||||
@@ -178,6 +180,7 @@ class StdAttributeSpecifierAST;
|
||||
class StringLiteralAST;
|
||||
class SwitchStatementAST;
|
||||
class TemplateDeclarationAST;
|
||||
class ConceptDeclarationAST;
|
||||
class TemplateIdAST;
|
||||
class TemplateTypeParameterAST;
|
||||
class ThisExpressionAST;
|
||||
@@ -185,6 +188,7 @@ class ThrowExpressionAST;
|
||||
class TrailingReturnTypeAST;
|
||||
class TranslationUnitAST;
|
||||
class TryBlockStatementAST;
|
||||
class TypeConstraintAST;
|
||||
class TypeConstructorCallAST;
|
||||
class TypeIdAST;
|
||||
class TypeidExpressionAST;
|
||||
|
||||
5
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
5
src/libs/3rdparty/cplusplus/Bind.cpp
vendored
@@ -933,6 +933,11 @@ bool Bind::visit(ParameterDeclarationClauseAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bind::visit(RequiresExpressionAST *)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lparen_token, Function *fun)
|
||||
{
|
||||
if (! ast)
|
||||
|
||||
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
1
src/libs/3rdparty/cplusplus/Bind.h
vendored
@@ -128,6 +128,7 @@ protected:
|
||||
bool visit(NewTypeIdAST *ast) override;
|
||||
bool visit(OperatorAST *ast) override;
|
||||
bool visit(ParameterDeclarationClauseAST *ast) override;
|
||||
bool visit(RequiresExpressionAST *ast) override;
|
||||
bool visit(TranslationUnitAST *ast) override;
|
||||
bool visit(ObjCProtocolRefsAST *ast) override;
|
||||
bool visit(ObjCMessageArgumentAST *ast) override;
|
||||
|
||||
185
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
185
src/libs/3rdparty/cplusplus/Parser.cpp
vendored
@@ -1255,6 +1255,8 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
|
||||
ast->declaration = nullptr;
|
||||
if (parseDeclaration(ast->declaration))
|
||||
break;
|
||||
if (parseConceptDeclaration(ast->declaration))
|
||||
break;
|
||||
|
||||
error(start_declaration, "expected a declaration");
|
||||
rewind(start_declaration + 1);
|
||||
@@ -1265,6 +1267,173 @@ bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
|
||||
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
|
||||
{
|
||||
DEBUG_THIS_RULE();
|
||||
@@ -1500,6 +1669,14 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
|
||||
NameAST *named_type_specifier = nullptr;
|
||||
SpecifierListAST **decl_specifier_seq_ptr = &decl_specifier_seq;
|
||||
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()) {
|
||||
// storage-class-specifier
|
||||
SimpleSpecifierAST *spec = new (_pool) SimpleSpecifierAST;
|
||||
@@ -1550,9 +1727,10 @@ bool Parser::parseDeclSpecifierSeq(SpecifierListAST *&decl_specifier_seq,
|
||||
}
|
||||
decl_specifier_seq_ptr = &(*decl_specifier_seq_ptr)->next;
|
||||
has_type_specifier = true;
|
||||
} else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
return true;
|
||||
}
|
||||
if (spec->asPlaceholderTypeSpecifier())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -4731,6 +4911,9 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node)
|
||||
case T_AT_SELECTOR:
|
||||
return parseObjCExpression(node);
|
||||
|
||||
case T_REQUIRES:
|
||||
return parseRequiresExpression(node);
|
||||
|
||||
default: {
|
||||
NameAST *name = nullptr;
|
||||
if (parseNameId(name)) {
|
||||
|
||||
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
5
src/libs/3rdparty/cplusplus/Parser.h
vendored
@@ -143,6 +143,11 @@ public:
|
||||
bool parseTemplateArgument(ExpressionAST *&node);
|
||||
bool parseTemplateArgumentList(ExpressionListAST *&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 parseTemplateParameterList(DeclarationListAST *&node);
|
||||
bool parseThrowExpression(ExpressionAST *&node);
|
||||
|
||||
@@ -70,6 +70,10 @@ public:
|
||||
// Get Document
|
||||
const Document::Ptr document = waitForFileInGlobalSnapshot(filePath);
|
||||
QVERIFY(document);
|
||||
if (!document->diagnosticMessages().isEmpty()) {
|
||||
for (const Document::DiagnosticMessage &m : document->diagnosticMessages())
|
||||
qDebug().noquote() << m.text();
|
||||
}
|
||||
QVERIFY(document->diagnosticMessages().isEmpty());
|
||||
|
||||
m_snapshot.insert(document);
|
||||
|
||||
@@ -145,6 +145,8 @@ private Q_SLOTS:
|
||||
|
||||
void lambdaType_data();
|
||||
void lambdaType();
|
||||
|
||||
void concepts();
|
||||
};
|
||||
|
||||
|
||||
@@ -293,5 +295,28 @@ void tst_cxx11::lambdaType()
|
||||
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)
|
||||
#include "tst_cxx11.moc"
|
||||
|
||||
Reference in New Issue
Block a user