diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index c8fd5d051..d897e88b1 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -276,6 +276,21 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() tok = tok->tokAt(2); } + // using type alias + else if (_tokenizer->isCPP() && Token::Match(tok, "using %name% =")) { + if (!findType(tok->next(), scope)) { + // fill typeList.. + typeList.push_back(Type(tok, nullptr, scope)); + Type* new_type = &typeList.back(); + scope->definedTypesMap[new_type->name()] = new_type; + } + + tok = tok->tokAt(3); + + while (tok && tok->str() != ";") + tok = tok->next(); + } + // unnamed struct and union else if (Token::Match(tok, "struct|union {") && Token::Match(tok->next()->link(), "} *|&| %name% ;|[")) { @@ -3517,7 +3532,14 @@ static const Token* skipPointers(const Token* tok) bool Scope::isVariableDeclaration(const Token* const tok, const Token*& vartok, const Token*& typetok) const { - if (check && check->_tokenizer->isCPP() && Token::Match(tok, "throw|new")) + const bool isCPP = check && check->_tokenizer->isCPP(); + + if (isCPP && Token::Match(tok, "throw|new")) + return false; + + const bool isCPP11 = isCPP && check->_settings->standards.cpp >= Standards::CPP11; + + if (isCPP11 && tok->str() == "using") return false; const Token* localTypeTok = skipScopeIdentifiers(tok); @@ -4986,7 +5008,10 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V valuetype->sign = ValueType::Sign::SIGNED; else if (type->isUnsigned()) valuetype->sign = ValueType::Sign::UNSIGNED; - if (type->str() == "const") + if (valuetype->type == ValueType::Type::UNKNOWN_TYPE && + type->type() && type->type()->isTypeAlias() && type->type()->typeStart) + parsedecl(type->type()->typeStart, valuetype, defaultSignedness, settings); + else if (type->str() == "const") valuetype->constness |= (1 << (valuetype->pointer - pointer0)); else if (const Library::Container *container = settings->library.detectContainer(type)) { valuetype->type = ValueType::Type::CONTAINER; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 80f7817a4..db724a2da 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -100,13 +100,24 @@ public: std::vector derivedFrom; std::list friendList; + const Token * typeStart; + const Token * typeEnd; + Type(const Token* classDef_ = nullptr, const Scope* classScope_ = nullptr, const Scope* enclosingScope_ = nullptr) : classDef(classDef_), classScope(classScope_), enclosingScope(enclosingScope_), - needInitialization(Unknown) { + needInitialization(Unknown), + typeStart(nullptr), + typeEnd(nullptr) { if (classDef_ && classDef_->str() == "enum") needInitialization = True; + else if (classDef_ && classDef_->str() == "using") { + typeStart = classDef->tokAt(3); + typeEnd = typeStart; + while (typeEnd->next() && typeEnd->next()->str() != ";") + typeEnd = typeEnd->next(); + } } const std::string& name() const; @@ -123,6 +134,10 @@ public: return classDef && classDef->str() == "enum"; } + bool isTypeAlias() const { + return classDef && classDef->str() == "using"; + } + bool isStructType() const { return classDef && classDef->str() == "struct"; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 7a8926b38..d50e75133 100755 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5538,6 +5538,8 @@ void Tokenizer::simplifyVarDecl(const bool only_k_r_fpar) void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar) { + const bool isCPP11 = _settings->standards.cpp >= Standards::CPP11; + // Split up variable declarations.. // "int a=4;" => "int a; a=4;" bool finishedwithkr = true; @@ -5586,6 +5588,8 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co continue; if (Token::Match(type0, "else|return|public:|protected:|private:")) continue; + if (isCPP11 && type0->str() == "using") + continue; bool isconst = false; bool isstatic = false; @@ -5828,6 +5832,8 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co void Tokenizer::simplifyPlatformTypes() { + const bool isCPP11 = _settings->standards.cpp >= Standards::CPP11; + enum { isLongLong, isLong, isInt } type; /** @todo This assumes a flat address space. Not true for segmented address space (FAR *). */ @@ -5846,11 +5852,15 @@ void Tokenizer::simplifyPlatformTypes() if (!Token::Match(tok, "std| ::| %type%")) continue; bool isUnsigned; - if (Token::Match(tok, "std| ::| size_t|uintptr_t|uintmax_t")) + if (Token::Match(tok, "std| ::| size_t|uintptr_t|uintmax_t")) { + if (isCPP11 && tok->strAt(-1) == "using" && tok->strAt(1) == "=") + continue; isUnsigned = true; - else if (Token::Match(tok, "std| ::| ssize_t|ptrdiff_t|intptr_t|intmax_t")) + } else if (Token::Match(tok, "std| ::| ssize_t|ptrdiff_t|intptr_t|intmax_t")) { + if (isCPP11 && tok->strAt(-1) == "using" && tok->strAt(1) == "=") + continue; isUnsigned = false; - else + } else continue; bool inStd = false; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 711e24d17..0ae9c8039 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -349,6 +349,8 @@ private: TEST_CASE(auto10); // #8020 TEST_CASE(unionWithConstructor); + + TEST_CASE(using1); } void array() { @@ -5313,6 +5315,50 @@ private: ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3); } + void using1() { + Standards::cppstd_t original_std = settings1.standards.cpp; + settings1.standards.cpp = Standards::CPP11; + GET_SYMBOL_DB("using INT = int;\n\n" + "using PINT = INT *;\n" + "using PCINT = const PINT;\n" + "INT i;\n" + "PINT pi;\n" + "PCINT pci;"); + settings1.standards.cpp = original_std; + const Token *tok = Token::findsimplematch(tokenizer.tokens(), "INT i ;"); + + ASSERT(db && tok && tok->next() && tok->next()->valueType()); + if (db && tok && tok->next() && tok->next()->valueType()) { + tok = tok->next(); + ASSERT_EQUALS(0, tok->valueType()->constness); + ASSERT_EQUALS(0, tok->valueType()->pointer); + ASSERT_EQUALS(ValueType::SIGNED, tok->valueType()->sign); + ASSERT_EQUALS(ValueType::INT, tok->valueType()->type); + } + + tok = Token::findsimplematch(tokenizer.tokens(), "PINT pi ;"); + + ASSERT(db && tok && tok->next() && tok->next()->valueType()); + if (db && tok && tok->next() && tok->next()->valueType()) { + tok = tok->next(); + ASSERT_EQUALS(0, tok->valueType()->constness); + ASSERT_EQUALS(1, tok->valueType()->pointer); + ASSERT_EQUALS(ValueType::SIGNED, tok->valueType()->sign); + ASSERT_EQUALS(ValueType::INT, tok->valueType()->type); + } + + tok = Token::findsimplematch(tokenizer.tokens(), "PCINT pci ;"); + + ASSERT(db && tok && tok->next() && tok->next()->valueType()); + if (db && tok && tok->next() && tok->next()->valueType()) { + tok = tok->next(); + ASSERT_EQUALS(1, tok->valueType()->constness); + ASSERT_EQUALS(1, tok->valueType()->pointer); + ASSERT_EQUALS(ValueType::SIGNED, tok->valueType()->sign); + ASSERT_EQUALS(ValueType::INT, tok->valueType()->type); + } + } + }; REGISTER_TEST(TestSymbolDatabase)