diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 9109c09c9..a84f81301 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -162,11 +162,11 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() if (tok->str() == "class") access[new_scope] = Private; - else if (tok->str() == "struct") + else if (tok->str() == "struct" || tok->str() == "union") access[new_scope] = Public; // fill typeList... - if (new_scope->isClassOrStruct() || new_scope->type == Scope::eUnion || new_scope->type == Scope::eEnum) { + if (new_scope->isClassOrStructOrUnion() || new_scope->type == Scope::eEnum) { Type* new_type = findType(tok->next(), scope); if (!new_type) { typeList.push_back(Type(new_scope->classDef, new_scope, scope)); @@ -358,8 +358,8 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() continue; } - // check if in class or structure - else if (scope->type == Scope::eClass || scope->type == Scope::eStruct) { + // check if in class or structure or union + else if (scope->isClassOrStructOrUnion()) { const Token *funcStart = nullptr; const Token *argStart = nullptr; const Token *declEnd = nullptr; @@ -1522,7 +1522,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const // regular function? else if (Token::Match(tok, "%name% (") && !isReservedName(tok->str()) && tok->previous() && (Token::Match(tok->previous(), "%name%|>|&|*|::|~") || // Either a return type or scope qualifier in front of tok - outerScope->isClassOrStruct())) { // or a ctor/dtor + outerScope->isClassOrStructOrUnion())) { // or a ctor/dtor const Token* tok1 = tok->previous(); const Token* tok2 = tok->next()->link()->next(); diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index e3c0df74f..b822ad63c 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -927,6 +927,10 @@ public: return (type == eClass || type == eStruct); } + bool isClassOrStructOrUnion() const { + return (type == eClass || type == eStruct || type == eUnion); + } + bool isExecutable() const { return type != eClass && type != eStruct && type != eUnion && type != eGlobal && type != eNamespace && type != eEnum; } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1af75d5c5..8b675530a 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -347,6 +347,8 @@ private: TEST_CASE(auto8); TEST_CASE(auto9); // #8044 (segmentation fault) TEST_CASE(auto10); // #8020 + + TEST_CASE(unionWithConstructor); } void array() { @@ -5252,6 +5254,23 @@ private: } } + void unionWithConstructor() { + GET_SYMBOL_DB("union Fred {\n" + " Fred(int x) : i(x) { }\n" + " Fred(float x) : f(x) { }\n" + " int i;\n" + " int f;\n" + "};"); + + ASSERT_EQUALS("", errout.str()); + + const Token *f = Token::findsimplematch(tokenizer.tokens(), "Fred ( int"); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 2); + + f = Token::findsimplematch(tokenizer.tokens(), "Fred ( float"); + ASSERT_EQUALS(true, db && f && f->function() && f->function()->tokenDef->linenr() == 3); + } + }; REGISTER_TEST(TestSymbolDatabase)