diff options
Diffstat (limited to 'src/libs/3rdparty/cplusplus/Bind.cpp')
-rw-r--r-- | src/libs/3rdparty/cplusplus/Bind.cpp | 269 |
1 files changed, 221 insertions, 48 deletions
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 486efffc3d..c85d401c49 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -35,6 +35,7 @@ #include <string> #include <memory> #include <sstream> +#include <utility> using namespace CPlusPlus; @@ -46,6 +47,7 @@ Bind::Bind(TranslationUnit *unit) _expression(nullptr), _name(nullptr), _declaratorId(nullptr), + _decompositionDeclarator(nullptr), _visibility(Symbol::Public), _objcVisibility(Symbol::Public), _methodKey(Function::NormalMethod), @@ -135,6 +137,8 @@ void Bind::setDeclSpecifiers(Symbol *symbol, const FullySpecifiedType &declSpeci if (Function *funTy = symbol->asFunction()) { if (declSpecifiers.isVirtual()) funTy->setVirtual(true); + if (declSpecifiers.isStatic()) + funTy->setStatic(true); } if (declSpecifiers.isDeprecated()) @@ -272,8 +276,25 @@ FullySpecifiedType Bind::postfixDeclarator(PostfixDeclaratorAST *ast, const Full return value; } -bool Bind::preVisit(AST *) +bool Bind::preVisit(AST *ast) { + if (_typeWasUnsignedOrSigned) { + if (SimpleSpecifierAST *simpleAst = ast->asSimpleSpecifier()) { + switch (tokenKind(simpleAst->specifier_token)) { + case T_CHAR: + case T_CHAR16_T: + case T_CHAR32_T: + case T_WCHAR_T: + case T_INT: + case T_SHORT: + case T_LONG: + _type.setType(&UndefinedType::instance); + break; + } + } + _typeWasUnsignedOrSigned = false; + } + ++_depth; if (_depth > kMaxDepth) return false; @@ -339,7 +360,9 @@ bool Bind::visit(DeclaratorAST *ast) return false; } -FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType &init, DeclaratorIdAST **declaratorId) +FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType &init, + DeclaratorIdAST **declaratorId, + DecompositionDeclaratorAST **decompDeclarator) { FullySpecifiedType type = init; @@ -347,6 +370,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType return type; std::swap(_declaratorId, declaratorId); + std::swap(_decompositionDeclarator, decompDeclarator); bool isAuto = false; const bool cxx11Enabled = translationUnit()->languageFeatures().cxx11Enabled; if (cxx11Enabled) @@ -369,7 +393,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType if (type.isAuto()) isAuto = true; } - if (!type->isFunctionType()) { + if (!type->asFunctionType()) { ExpressionTy initializer = this->expression(ast->initializer); if (cxx11Enabled && isAuto) { type = initializer; @@ -378,6 +402,7 @@ FullySpecifiedType Bind::declarator(DeclaratorAST *ast, const FullySpecifiedType } std::swap(_declaratorId, declaratorId); + std::swap(_decompositionDeclarator, decompDeclarator); return type; } @@ -890,6 +915,10 @@ OperatorNameId::Kind Bind::cppOperator(OperatorAST *ast) kind = OperatorNameId::ArrayAccessOp; break; + case T_LESS_EQUAL_GREATER: + kind = OperatorNameId::SpaceShipOp; + break; + default: kind = OperatorNameId::InvalidOp; } // switch @@ -904,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) @@ -918,6 +952,19 @@ void Bind::parameterDeclarationClause(ParameterDeclarationClauseAST *ast, int lp for (ParameterDeclarationListAST *it = ast->parameter_declaration_list; it; it = it->next) { this->declaration(it->value); + + // Check for '...' in last parameter declarator for variadic template + // (i.e. template<class ... T> void foo(T ... args);) + // those last dots are part of parameter declarator, not the parameter declaration clause + if (! it->next + && it->value->declarator != nullptr + && it->value->declarator->core_declarator != nullptr){ + DeclaratorIdAST* declId = it->value->declarator->core_declarator->asDeclaratorId(); + if (declId && declId->dot_dot_dot_token != 0){ + fun->setVariadic(true); + fun->setVariadicTemplate(true); + } + } } if (ast->dot_dot_dot_token) @@ -1238,12 +1285,39 @@ const StringLiteral *Bind::asStringLiteral(const AST *ast) const int firstToken = ast->firstToken(); const int lastToken = ast->lastToken(); std::string buffer; + + const auto token = tokenAt(ast->firstToken()); + + if (token.isCharLiteral()) { + if (token.kind() == T_WIDE_CHAR_LITERAL) + buffer += 'L'; + else if (token.kind() == T_UTF16_CHAR_LITERAL) + buffer += 'u'; + else if (token.kind() == T_UTF32_CHAR_LITERAL) + buffer += 'U'; + buffer += '\''; + } else if (token.isStringLiteral()) { + if (token.kind() == T_WIDE_STRING_LITERAL) + buffer += 'L'; + else if (token.kind() == T_UTF16_STRING_LITERAL) + buffer += 'u'; + else if (token.kind() == T_UTF32_STRING_LITERAL) + buffer += 'U'; + else if (token.kind() == T_UTF8_STRING_LITERAL) + buffer += "u8"; + buffer += '"'; + } for (int index = firstToken; index != lastToken; ++index) { const Token &tk = tokenAt(index); if (index != firstToken && (tk.whitespace() || tk.newline())) buffer += ' '; buffer += tk.spell(); } + if (token.isCharLiteral()) + buffer += '\''; + else if (token.isStringLiteral()) + buffer += '"'; + return control()->stringLiteral(buffer.c_str(), int(buffer.size())); } @@ -1454,6 +1528,8 @@ bool Bind::visit(IfStatementAST *ast) ast->symbol = block; Scope *previousScope = switchScope(block); + if (ast->initStmt) + this->statement(ast->initStmt); /*ExpressionTy condition =*/ this->expression(ast->condition); this->statement(ast->statement); this->statement(ast->else_statement); @@ -1879,6 +1955,7 @@ bool Bind::visit(LambdaExpressionAST *ast) { this->lambdaIntroducer(ast->lambda_introducer); if (Function *function = this->lambdaDeclarator(ast->lambda_declarator)) { + function->setSourceLocation(ast->lambda_introducer->firstToken(), translationUnit()); _scope->addMember(function); Scope *previousScope = switchScope(function); this->statement(ast->statement); @@ -1954,51 +2031,69 @@ bool Bind::visit(SimpleDeclarationAST *ast) for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) { DeclaratorIdAST *declaratorId = nullptr; - FullySpecifiedType declTy = this->declarator(it->value, type, &declaratorId); + DecompositionDeclaratorAST *decompDeclarator = nullptr; + FullySpecifiedType declTy = this->declarator(it->value, type, &declaratorId, + &decompDeclarator); - const Name *declName = nullptr; - int sourceLocation = location(it->value, ast->firstToken()); - if (declaratorId && declaratorId->name) - declName = declaratorId->name->name; + std::vector<std::pair<const Name *, int>> namesAndLocations; + if (declaratorId && declaratorId->name) { + namesAndLocations.push_back({declaratorId->name->name, + location(it->value, ast->firstToken())}); + } else if (decompDeclarator) { + for (auto it = decompDeclarator->identifiers->begin(); + it != decompDeclarator->identifiers->end(); ++it) { + if ((*it)->name) + namesAndLocations.push_back({(*it)->name, (*it)->firstToken()}); + } + } - Declaration *decl = control()->newDeclaration(sourceLocation, declName); - decl->setType(declTy); - setDeclSpecifiers(decl, type); + for (const auto &nameAndLoc : std::as_const(namesAndLocations)) { + const int sourceLocation = nameAndLoc.second; + Declaration *decl = control()->newDeclaration(sourceLocation, nameAndLoc.first); + if (const Type * const t = declTy.type(); t && declTy.isTypedef() && t->asClassType() + && t->asClassType()->name() && t->asClassType()->name()->asAnonymousNameId()) { + declTy.type()->asClassType()->setName(decl->name()); + } + decl->setType(declTy); + setDeclSpecifiers(decl, type); - if (Function *fun = decl->type()->asFunctionType()) { - fun->setEnclosingScope(_scope); - fun->setSourceLocation(sourceLocation, translationUnit()); + if (Function *fun = decl->type()->asFunctionType()) { + fun->setEnclosingScope(_scope); + fun->setSourceLocation(sourceLocation, translationUnit()); - setDeclSpecifiers(fun, type); - if (declaratorId && declaratorId->name) - fun->setName(declaratorId->name->name); // update the function name - } - else if (declTy.isAuto()) { - const ExpressionAST *initializer = it->value->initializer; - if (!initializer && declaratorId) - translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer"); - else if (initializer) - decl->setInitializer(asStringLiteral(initializer)); - } + setDeclSpecifiers(fun, type); + if (declaratorId && declaratorId->name) + fun->setName(declaratorId->name->name); // update the function name + } + else if (declTy.isAuto()) { + const ExpressionAST *initializer = it->value->initializer; + if (!initializer && declaratorId) { + translationUnit()->error(location(declaratorId->name, ast->firstToken()), + "auto-initialized variable must have an initializer"); + } else if (initializer) { + decl->setInitializer(asStringLiteral(initializer)); + } + } - if (_scope->isClass()) { - decl->setVisibility(_visibility); + if (_scope->asClass()) { + decl->setVisibility(_visibility); - if (Function *funTy = decl->type()->asFunctionType()) { - funTy->setMethodKey(methodKey); + if (Function *funTy = decl->type()->asFunctionType()) { + funTy->setMethodKey(methodKey); - bool pureVirtualInit = it->value->equal_token - && it->value->initializer - && it->value->initializer->asNumericLiteral(); - if (funTy->isVirtual() && pureVirtualInit) - funTy->setPureVirtual(true); + bool pureVirtualInit = it->value->equal_token + && it->value->initializer + && it->value->initializer->asNumericLiteral(); + if (funTy->isVirtual() && pureVirtualInit) + funTy->setPureVirtual(true); + } } - } - _scope->addMember(decl); + _scope->addMember(decl); - *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl); - symbolTail = &(*symbolTail)->next; + *symbolTail = new (translationUnit()->memoryPool()) List<Symbol *>(decl); + symbolTail = &(*symbolTail)->next; + } } return false; } @@ -2007,7 +2102,7 @@ bool Bind::visit(EmptyDeclarationAST *ast) { (void) ast; int semicolon_token = ast->semicolon_token; - if (_scope && (_scope->isClass() || _scope->isNamespace())) { + if (_scope && (_scope->asClass() || _scope->asNamespace())) { const Token &tk = tokenAt(semicolon_token); if (! tk.generated()) @@ -2184,7 +2279,7 @@ bool Bind::visit(AliasDeclarationAST *ast) decl->setType(ty); decl->setStorage(Symbol::Typedef); ast->symbol = decl; - if (_scope->isClass()) + if (_scope->asClass()) decl->setVisibility(_visibility); _scope->addMember(decl); @@ -2239,11 +2334,24 @@ bool Bind::visit(FunctionDefinitionAST *ast) Function *fun = type->asFunctionType(); ast->symbol = fun; + if (!fun && ast->declarator && ast->declarator->initializer) + if (ExpressionListParenAST *exprAst = ast->declarator->initializer->asExpressionListParen()) { + // this could be non-expanded function like macro, because + // for find usages we parse without expanding them + // So we create dummy function type here for findUsages to see function body + fun = control()->newFunction(0, nullptr); + fun->setStartOffset(tokenAt(exprAst->firstToken()).utf16charsBegin()); + fun->setEndOffset(tokenAt(exprAst->lastToken() - 1).utf16charsEnd()); + + type = fun; + ast->symbol = fun; + } + if (fun) { setDeclSpecifiers(fun, declSpecifiers); fun->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd()); - if (_scope->isClass()) { + if (_scope->asClass()) { fun->setVisibility(_visibility); fun->setMethodKey(methodKey); } @@ -2426,6 +2534,11 @@ bool Bind::visit(TemplateTypeParameterAST *ast) return false; } +bool Bind::visit(TypeConstraintAST *) +{ + return false; +} + bool Bind::visit(UsingAST *ast) { int sourceLocation = location(ast->name, ast->firstToken()); @@ -2767,10 +2880,27 @@ bool Bind::visit(DestructorNameAST *ast) bool Bind::visit(TemplateIdAST *ast) { // collect the template parameters - std::vector<FullySpecifiedType> templateArguments; + std::vector<TemplateArgument> templateArguments; for (ExpressionListAST *it = ast->template_argument_list; it; it = it->next) { ExpressionTy value = this->expression(it->value); - templateArguments.push_back(value); + if (value.isValid()) { + templateArguments.emplace_back(value); + } else { + // special case for numeric values + if (it->value->asNumericLiteral()) { + templateArguments + .emplace_back(value, + tokenAt(it->value->asNumericLiteral()->literal_token).number); + } else if (it->value->asBoolLiteral()) { + templateArguments + .emplace_back(value, tokenAt(it->value->asBoolLiteral()->literal_token).number); + } else { + // fall back to non-valid type in templateArguments + // for ast->template_argument_list and templateArguments sizes match + // TODO support other literals/expressions as default arguments + templateArguments.emplace_back(value); + } + } } const Identifier *id = identifier(ast->identifier_token); @@ -2883,13 +3013,17 @@ bool Bind::visit(SimpleSpecifierAST *ast) case T_SIGNED: if (_type.isSigned()) translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token)); + _type.setType(control()->integerType(IntegerType::Int)); _type.setSigned(true); + _typeWasUnsignedOrSigned = true; break; case T_UNSIGNED: if (_type.isUnsigned()) translationUnit()->error(ast->specifier_token, "duplicate `%s'", spell(ast->specifier_token)); + _type.setType(control()->integerType(IntegerType::Int)); _type.setUnsigned(true); + _typeWasUnsignedOrSigned = true; break; case T_CHAR: @@ -3014,6 +3148,22 @@ bool Bind::visit(GnuAttributeSpecifierAST *ast) return false; } +bool Bind::visit(MsvcDeclspecSpecifierAST *ast) +{ + for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) { + this->attribute(it->value); + } + return false; +} + +bool Bind::visit(StdAttributeSpecifierAST *ast) +{ + for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) { + this->attribute(it->value); + } + return false; +} + bool Bind::visit(TypeofSpecifierAST *ast) { ExpressionTy expression = this->expression(ast->expression); @@ -3058,7 +3208,7 @@ bool Bind::visit(ClassSpecifierAST *ast) klass->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd()); _scope->addMember(klass); - if (_scope->isClass()) + if (_scope->asClass()) klass->setVisibility(_visibility); // set the class key @@ -3121,7 +3271,7 @@ bool Bind::visit(EnumSpecifierAST *ast) ast->symbol = e; _scope->addMember(e); - if (_scope->isClass()) + if (_scope->asClass()) e->setVisibility(_visibility); Scope *previousScope = switchScope(e); @@ -3130,6 +3280,10 @@ bool Bind::visit(EnumSpecifierAST *ast) } (void) switchScope(previousScope); + if (ast->name) + _type.setType(control()->namedType(this->name(ast->name))); + else + _type.setType(ast->symbol); return false; } @@ -3156,7 +3310,7 @@ bool Bind::visit(PointerToMemberAST *ast) bool Bind::visit(PointerAST *ast) { - if (_type->isReferenceType()) + if (_type->asReferenceType()) translationUnit()->error(ast->firstToken(), "cannot declare pointer to a reference"); FullySpecifiedType type(control()->pointerType(_type)); @@ -3171,7 +3325,7 @@ bool Bind::visit(ReferenceAST *ast) { const bool rvalueRef = (tokenKind(ast->reference_token) == T_AMPER_AMPER); - if (_type->isReferenceType()) + if (_type->asReferenceType()) translationUnit()->error(ast->firstToken(), "cannot declare reference to a reference"); FullySpecifiedType type(control()->referenceType(_type, rvalueRef)); @@ -3226,6 +3380,15 @@ bool Bind::visit(DeclaratorIdAST *ast) return false; } +bool Bind::visit(DecompositionDeclaratorAST *ast) +{ + for (auto it = ast->identifiers->begin(); it != ast->identifiers->end(); ++it) + name(*it); + if (_decompositionDeclarator) + *_decompositionDeclarator = ast; + return false; +} + bool Bind::visit(NestedDeclaratorAST *ast) { _type = this->declarator(ast->declarator, _type, _declaratorId); @@ -3243,10 +3406,20 @@ bool Bind::visit(FunctionDeclaratorAST *ast) _type = this->trailingReturnType(ast->trailing_return_type, _type); fun->setReturnType(_type); + // "static", "virtual" etc. + FullySpecifiedType declSpecifiers; + for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) + declSpecifiers = this->specifier(it->value, declSpecifiers); + setDeclSpecifiers(fun, declSpecifiers); + // int lparen_token = ast->lparen_token; this->parameterDeclarationClause(ast->parameter_declaration_clause, ast->lparen_token, fun); // int rparen_token = ast->rparen_token; FullySpecifiedType type(fun); + type.setStatic(declSpecifiers.isStatic()); + type.setVirtual(declSpecifiers.isVirtual()); + type.setDeprecated(declSpecifiers.isDeprecated()); + type.setUnavailable(declSpecifiers.isUnavailable()); for (SpecifierListAST *it = ast->cv_qualifier_list; it; it = it->next) { type = this->specifier(it->value, type); } @@ -3295,7 +3468,7 @@ void Bind::ensureValidClassName(const Name **name, int sourceLocation) const QualifiedNameId *qName = (*name)->asQualifiedNameId(); const Name *uqName = qName ? qName->name() : *name; - if (!uqName->isNameId() && !uqName->isTemplateNameId()) { + if (!uqName->asNameId() && !uqName->asTemplateNameId()) { translationUnit()->error(sourceLocation, "expected a class-name"); *name = uqName->identifier(); |