Add support for simple c++ 11 type ailases like: using INT = int; (#1024)
* Add support for simple c++ 11 type ailases like: using INT = int; Only types supported by ValueType are supported. Complex types like function pointers are not supported. Template type aliases are not supported. * Fix crash when type in using type alias is simplified away. This fixes a crash when size_t is replaced with unsigned long in: using size_t = unsigned long; by the tokenizer. This does not fix the problem where Tokenizer::simplifyPlatformTypes() simplifies away size_t in other cases. This is only a problem when the new type is different from the platform type.
This commit is contained in:
parent
58034dee86
commit
cefb2131c7
|
@ -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;
|
||||
|
|
|
@ -100,13 +100,24 @@ public:
|
|||
std::vector<BaseInfo> derivedFrom;
|
||||
std::list<FriendInfo> 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";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue