From 8c993c13639df2a14836e93abf5d7b123c026363 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 14 Mar 2014 05:40:17 +0100 Subject: [PATCH] Partial fix for #5555. Remember function attributes: pure, const, constructor, destructor --- lib/symboldatabase.cpp | 9 ++++++++- lib/symboldatabase.h | 12 ++++++++++++ lib/token.cpp | 9 +++++++++ lib/token.h | 23 ++++++++++++++++++++++- lib/tokenize.cpp | 33 +++++++++++++++++++++++++++++++-- lib/tokenlist.cpp | 8 ++++++++ 6 files changed, 90 insertions(+), 4 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b0b37b07d..dc0003d24 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1249,8 +1249,15 @@ Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, co { Function* function = 0; for (std::list::iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) { - if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) + if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) { function = &*i; + // copy attributes from function prototype to function + const_cast(tok)->isAttributeConstructor(i->tokenDef->isAttributeConstructor()); + const_cast(tok)->isAttributeDestructor(i->tokenDef->isAttributeDestructor()); + const_cast(tok)->isAttributePure(i->tokenDef->isAttributePure()); + const_cast(tok)->isAttributeConst(i->tokenDef->isAttributeConst()); + break; + } } if (!function) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index a740c79e4..5056ed394 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -562,6 +562,18 @@ public: bool isDestructor() const { return type==eDestructor; } + bool isAttributeConstructor() const { + return tokenDef->isAttributeConstructor(); + } + bool isAttributeDestructor() const { + return tokenDef->isAttributeDestructor(); + } + bool isAttributePure() const { + return tokenDef->isAttributePure(); + } + bool isAttributeConst() const { + return tokenDef->isAttributeConst(); + } const Token *tokenDef; // function name token in class definition const Token *argDef; // function argument start '(' in class definition diff --git a/lib/token.cpp b/lib/token.cpp index 186bec00a..ce3e201d4 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -51,7 +51,10 @@ Token::Token(Token **t) : _isStandardType(false), _isExpandedMacro(false), _isAttributeConstructor(false), + _isAttributeDestructor(false), _isAttributeUnused(false), + _isAttributePure(false), + _isAttributeConst(false), _astOperand1(nullptr), _astOperand2(nullptr), _astParent(nullptr) @@ -199,7 +202,10 @@ void Token::deleteThis() _isStandardType = _next->_isStandardType; _isExpandedMacro = _next->_isExpandedMacro; _isAttributeConstructor = _next->_isAttributeConstructor; + _isAttributeDestructor = _next->_isAttributeDestructor; _isAttributeUnused = _next->_isAttributeUnused; + _isAttributePure = _next->_isAttributePure; + _isAttributeConst = _next->_isAttributeConst; _varId = _next->_varId; _fileIndex = _next->_fileIndex; _linenr = _next->_linenr; @@ -223,7 +229,10 @@ void Token::deleteThis() _isStandardType = _previous->_isStandardType; _isExpandedMacro = _previous->_isExpandedMacro; _isAttributeConstructor = _previous->_isAttributeConstructor; + _isAttributeDestructor = _previous->_isAttributeDestructor; _isAttributeUnused = _previous->_isAttributeUnused; + _isAttributePure = _previous->_isAttributePure; + _isAttributeConst = _previous->_isAttributeConst; _varId = _previous->_varId; _fileIndex = _previous->_fileIndex; _linenr = _previous->_linenr; diff --git a/lib/token.h b/lib/token.h index 9efe540c6..7f2efb7a9 100644 --- a/lib/token.h +++ b/lib/token.h @@ -281,12 +281,30 @@ public: void isAttributeConstructor(bool ac) { _isAttributeConstructor = ac; } + bool isAttributeDestructor() const { + return _isAttributeDestructor; + } + void isAttributeDestructor(bool value) { + _isAttributeDestructor = value; + } bool isAttributeUnused() const { return _isAttributeUnused; } void isAttributeUnused(bool unused) { _isAttributeUnused = unused; } + bool isAttributePure() const { + return _isAttributePure; + } + void isAttributePure(bool value) { + _isAttributePure = value; + } + bool isAttributeConst() const { + return _isAttributeConst; + } + void isAttributeConst(bool value) { + _isAttributeConst = value; + } static const Token *findsimplematch(const Token *tok, const char pattern[]); static const Token *findsimplematch(const Token *tok, const char pattern[], const Token *end); @@ -661,8 +679,11 @@ private: bool _isLong; bool _isStandardType; bool _isExpandedMacro; - bool _isAttributeConstructor; // __attribute__((constructor)) + bool _isAttributeConstructor; // __attribute__((constructor)) __attribute__((constructor(priority))) + bool _isAttributeDestructor; // __attribute__((destructor)) __attribute__((destructor(priority))) bool _isAttributeUnused; // __attribute__((unused)) + bool _isAttributePure; // __attribute__((pure)) + bool _isAttributeConst; // __attribute__((const)) /** Updates internal property cache like _isName or _isBoolean. Called after any _str() modification. */ diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index ceb66ca8a..d5d4f5bc7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -116,7 +116,10 @@ Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last, tok2->isLong(tok->isLong()); tok2->isExpandedMacro(tok->isExpandedMacro()); tok2->isAttributeConstructor(tok->isAttributeConstructor()); + tok2->isAttributeDestructor(tok->isAttributeDestructor()); tok2->isAttributeUnused(tok->isAttributeUnused()); + tok2->isAttributePure(tok->isAttributePure()); + tok2->isAttributeConst(tok->isAttributeConst()); tok2->varId(tok->varId()); // Check for links and fix them up @@ -9089,8 +9092,24 @@ void Tokenizer::simplifyAttribute() { for (Token *tok = list.front(); tok; tok = tok->next()) { while (Token::simpleMatch(tok, "__attribute__ (") && tok->next()->link() && tok->next()->link()->next()) { - if (Token::simpleMatch(tok->tokAt(2), "( constructor )")) { - tok->next()->link()->next()->isAttributeConstructor(true); + if (Token::simpleMatch(tok->tokAt(2), "( constructor")) { + // prototype for constructor is: void func(void); + if (tok->next()->link()->next()->str() == "void") // __attribute__((constructor)) void func() {} + tok->next()->link()->next()->next()->isAttributeConstructor(true); + else if (tok->next()->link()->next()->str() == ";") // void func() __attribute__((constructor)); + tok->previous()->link()->previous()->isAttributeConstructor(true); + else // void __attribute__((constructor)) func() {} + tok->next()->link()->next()->isAttributeConstructor(true); + } + + if (Token::simpleMatch(tok->tokAt(2), "( destructor")) { + // prototype for destructor is: void func(void); + if (tok->next()->link()->next()->str() == "void") // __attribute__((destructor)) void func() {} + tok->next()->link()->next()->next()->isAttributeDestructor(true); + else if (tok->next()->link()->next()->str() == ";") // void func() __attribute__((destructor)); + tok->previous()->link()->previous()->isAttributeDestructor(true); + else // void __attribute__((destructor)) func() {} + tok->next()->link()->next()->isAttributeDestructor(true); } if (Token::simpleMatch(tok->tokAt(2), "( unused )")) { @@ -9105,6 +9124,16 @@ void Tokenizer::simplifyAttribute() tok->next()->link()->next()->isAttributeUnused(true); } + // type func(...) __attribute__((pure)); + if (Token::simpleMatch(tok->tokAt(2), "( pure )")) { + tok->previous()->link()->previous()->isAttributePure(true); + } + + // type func(...) __attribute__((const)); + if (Token::simpleMatch(tok->tokAt(2), "( const )")) { + tok->previous()->link()->previous()->isAttributeConst(true); + } + Token::eraseTokens(tok, tok->next()->link()->next()); tok->deleteThis(); } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index eefb08dd3..bf3197b8a 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -142,7 +142,11 @@ void TokenList::addtoken(const Token * tok, const unsigned int lineno, const uns _back->isUnsigned(tok->isUnsigned()); _back->isSigned(tok->isSigned()); _back->isLong(tok->isLong()); + _back->isAttributeConstructor(tok->isAttributeConstructor()); + _back->isAttributeDestructor(tok->isAttributeDestructor()); _back->isAttributeUnused(tok->isAttributeUnused()); + _back->isAttributePure(tok->isAttributePure()); + _back->isAttributeConst(tok->isAttributeConst()); } //--------------------------------------------------------------------------- // InsertTokens - Copy and insert tokens @@ -172,7 +176,11 @@ void TokenList::insertTokens(Token *dest, const Token *src, unsigned int n) dest->isSigned(src->isSigned()); dest->isPointerCompare(src->isPointerCompare()); dest->isLong(src->isLong()); + dest->isAttributeConstructor(src->isAttributeConstructor()); + dest->isAttributeDestructor(src->isAttributeDestructor()); dest->isAttributeUnused(src->isAttributeUnused()); + dest->isAttributePure(src->isAttributePure()); + dest->isAttributeConst(src->isAttributeConst()); src = src->next(); --n; }