From eb74bfc15a39f3c8698492cb246d9a34e4ec8ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 1 Sep 2010 18:10:12 +0200 Subject: [PATCH] Fixed #2007 (False positive: member variable not initialized (Borland C++ property)) --- lib/tokenize.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++ lib/tokenize.h | 5 ++++ test/testclass.cpp | 25 -------------------- test/testtokenize.cpp | 13 +++++++++++ 4 files changed, 71 insertions(+), 25 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index eddc96765..e29fee76e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1972,6 +1972,9 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s // remove Microsoft MFC.. simplifyMicrosoftMFC(); + // remove Borland stuff.. + simplifyBorland(); + // typedef.. simplifyTypedef(); @@ -8304,5 +8307,55 @@ void Tokenizer::simplifyMicrosoftMFC() } +// Remove Borland code +void Tokenizer::simplifyBorland() +{ + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "( __closure * %var% )")) + { + tok->deleteNext(); + } + } + + // I think that these classes are always declared at the outer scope + // I save some time by ignoring inner classes. + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (tok->str() == "{") + tok = tok->link(); + + if (Token::Match(tok, "class %var% :|{")) + { + unsigned int indentlevel = 0; + for (Token *tok2 = tok; tok2; tok2 = tok2->next()) + { + if (tok2->str() == "{") + { + if (indentlevel == 0) + indentlevel = 1; + else + tok2 = tok2->link(); + } + else if (tok2->str() == "}") + { + break; + } + else if (tok2->str() == "__property" && + Token::Match(tok2->previous(), ";|{|}|protected:|public:|__published:")) + { + while (tok2 && !Token::Match(tok2, "{|;")) + tok2->deleteThis(); + if (Token::simpleMatch(tok2, "{")) + { + Token::eraseTokens(tok2, tok2->link()); + tok2->deleteThis(); + tok2->deleteThis(); + } + } + } + } + } +} diff --git a/lib/tokenize.h b/lib/tokenize.h index 15cf4127f..54f438a05 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -478,6 +478,11 @@ public: */ void simplifyMicrosoftMFC(); + /** + * Remove Borland code + */ + void simplifyBorland(); + /** * This will return a short name describing function parameters * e.g. parameters: (int a, char b) should get name "int,char,". diff --git a/test/testclass.cpp b/test/testclass.cpp index f6bb0c1b7..d850339c6 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -73,7 +73,6 @@ private: TEST_CASE(uninitVarHeader2); // Class is defined in header TEST_CASE(uninitVarHeader3); // Class is defined in header TEST_CASE(uninitVarPublished); // Borland C++: Variables in the published section are auto-initialized - TEST_CASE(uninitProperty); // Borland C++: No FP for properties TEST_CASE(uninitOperator); // No FP about uninitialized 'operator[]' TEST_CASE(uninitFunction1); // No FP when initialized in function TEST_CASE(uninitFunction2); // No FP when initialized in function @@ -1995,30 +1994,6 @@ private: " Fred() { }\n" "}\n"); ASSERT_EQUALS("", errout.str()); - - checkUninitVar("class Fred\n" - "{\n" - "__published:\n" - " int * i_;\n" - " __property int * i = {read=i_, write=i_};\n" - "public:\n" - " Fred() { i_ = 0; }\n" - "}\n"); - ASSERT_EQUALS("", errout.str()); - } - - // Borland C++: No FP for properties - void uninitProperty() - { - checkUninitVar("class Fred\n" - "{\n" - "private:\n" - " int * i_;\n" - "public:\n" - " Fred() { i_ = 0; }\n" - " __property int * i = {read=i_, write=i_};\n" - "}\n"); - ASSERT_EQUALS("", errout.str()); } void uninitOperator() diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 420cfb08b..04b3341aa 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -259,6 +259,8 @@ private: TEST_CASE(microsoftMFC); + TEST_CASE(borland); + TEST_CASE(sql); } @@ -4613,6 +4615,17 @@ private: ASSERT_EQUALS("class MyDialog : public CDialog { private: CString text ; } ;", tokenizeAndStringify(code4,false)); } + void borland() + { + // __closure + ASSERT_EQUALS("int * a ;", + tokenizeAndStringify("int (__closure *a)();", false)); + + // __property + ASSERT_EQUALS("class Fred { } ;", + tokenizeAndStringify("class Fred { __property int x = { } };", false)); + } + void sql() { // Oracle PRO*C extensions for inline SQL. Just replace the SQL with "asm()" to fix wrong error messages