aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/3rdparty/cplusplus/Bind.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/3rdparty/cplusplus/Bind.cpp')
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp269
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();