summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libs/cplusplus/LookupContext.cpp30
-rw-r--r--src/plugins/cpptools/cppchecksymbols.cpp14
-rw-r--r--src/plugins/cpptools/cppchecksymbols.h2
-rw-r--r--tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp110
4 files changed, 150 insertions, 6 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 12ee4933c3..0834067144 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -335,8 +335,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
if (name->identifier() != 0 && scope->isBlock()) {
bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
- if (! candidates.isEmpty())
- break; // it's a local.
+ if (! candidates.isEmpty()) {
+ // it's a local.
+ //for qualified it can be outside of the local scope
+ if (name->isQualifiedNameId())
+ continue;
+ else
+ break;
+ }
for (unsigned i = 0; i < scope->memberCount(); ++i) {
if (UsingNamespaceDirective *u = scope->memberAt(i)->asUsingNamespaceDirective()) {
@@ -352,8 +358,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
} else if (Function *fun = scope->asFunction()) {
bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0);
- if (! candidates.isEmpty())
- break; // it's an argument or a template parameter.
+ if (! candidates.isEmpty()) {
+ // it's an argument or a template parameter.
+ //for qualified it can be outside of the local scope
+ if (name->isQualifiedNameId())
+ continue;
+ else
+ break;
+ }
if (fun->name() && fun->name()->isQualifiedNameId()) {
if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
@@ -379,8 +391,14 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
} else if (Template *templ = scope->asTemplate()) {
bindings()->lookupInScope(name, templ, &candidates, /*templateId = */ 0, /*binding=*/ 0);
- if (! candidates.isEmpty())
- return candidates; // it's a template parameter.
+ if (! candidates.isEmpty()) {
+ // it's a template parameter.
+ //for qualified it can be outside of the local scope
+ if (name->isQualifiedNameId())
+ continue;
+ else
+ break;
+ }
} else if (scope->asNamespace()
|| scope->asClass()
diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp
index fbf2766606..6ac5843c11 100644
--- a/src/plugins/cpptools/cppchecksymbols.cpp
+++ b/src/plugins/cpptools/cppchecksymbols.cpp
@@ -1240,6 +1240,7 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
{
unsigned startToken = ast->firstToken();
bool isDestructor = false;
+ bool isConstructor = false;
if (DestructorNameAST *dtor = ast->asDestructorName()) {
isDestructor = true;
if (dtor->unqualified_name)
@@ -1264,6 +1265,8 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
if (isDestructor != c->name()->isDestructorNameId())
continue;
+ isConstructor = isConstructorDeclaration(c);
+
Function *funTy = c->type()->asFunctionType();
if (! funTy) {
//Try to find a template function
@@ -1296,7 +1299,9 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
}
if (matchType != Match_None) {
+ // decide how constructor and destructor should be highlighted
if (highlightCtorDtorAsType
+ && (isConstructor || isDestructor)
&& maybeType(ast->name)
&& kind == SemanticInfo::FunctionUse) {
return false;
@@ -1399,3 +1404,12 @@ void CheckSymbols::flush()
_usages.clear();
_usages.reserve(cap);
}
+
+bool CheckSymbols::isConstructorDeclaration(Symbol *declaration)
+{
+ Class *clazz = declaration->enclosingClass();
+ if (clazz && clazz->name())
+ return declaration->name()->isEqualTo(clazz->name());
+
+ return false;
+}
diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h
index 2b69e00081..51c032bb9c 100644
--- a/src/plugins/cpptools/cppchecksymbols.h
+++ b/src/plugins/cpptools/cppchecksymbols.h
@@ -165,6 +165,8 @@ protected:
void flush();
private:
+ bool isConstructorDeclaration(Symbol *declaration);
+
Document::Ptr _doc;
LookupContext _context;
TypeOfExpression typeOfExpression;
diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
index 432fd2dad4..cbc66e2628 100644
--- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
+++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
@@ -176,6 +176,10 @@ private slots:
void test_checksymbols_StaticUse();
void test_checksymbols_VariableHasTheSameNameAsEnumUse();
void test_checksymbols_NestedClassOfEnclosingTemplateUse();
+ void test_checksymbols_8902_staticFunctionHighlightingAsMember_localVariable();
+ void test_checksymbols_8902_staticFunctionHighlightingAsMember_functionArgument();
+ void test_checksymbols_8902_staticFunctionHighlightingAsMember_templateParameter();
+ void test_checksymbols_8902_staticFunctionHighlightingAsMember_struct();
void test_checksymbols_QTCREATORBUG8890_danglingPointer();
void test_checksymbols_QTCREATORBUG8974_danglingPointer();
@@ -446,6 +450,112 @@ void tst_CheckSymbols::test_checksymbols_NestedClassOfEnclosingTemplateUse()
TestData::check(source, expectedUses);
}
+void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_localVariable()
+{
+ const QByteArray source =
+ "struct Foo\n"
+ "{\n"
+ " static int foo();\n"
+ "};\n"
+ "\n"
+ "void bar()\n"
+ "{\n"
+ " int foo = Foo::foo();\n"
+ "}\n"
+ ;
+
+ const QList<Use> expectedUses = QList<Use>()
+ << Use(1, 8, 3, SemanticInfo::TypeUse)
+ << Use(3, 16, 3, SemanticInfo::FunctionUse)
+ << Use(6, 6, 3, SemanticInfo::FunctionUse)
+ << Use(8, 9, 3, SemanticInfo::LocalUse)
+ << Use(8, 15, 3, SemanticInfo::TypeUse)
+ << Use(8, 20, 3, SemanticInfo::FunctionUse)
+ ;
+
+ TestData::check(source, expectedUses);
+}
+
+void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_functionArgument()
+{
+ const QByteArray source =
+ "struct Foo\n"
+ "{\n"
+ " static int foo();\n"
+ "};\n"
+ "\n"
+ "void bar(int foo)\n"
+ "{\n"
+ " Foo::foo();\n"
+ "}\n"
+ ;
+
+ const QList<Use> expectedUses = QList<Use>()
+ << Use(1, 8, 3, SemanticInfo::TypeUse)
+ << Use(3, 16, 3, SemanticInfo::FunctionUse)
+ << Use(6, 6, 3, SemanticInfo::FunctionUse)
+ << Use(6, 14, 3, SemanticInfo::LocalUse)
+ << Use(8, 5, 3, SemanticInfo::TypeUse)
+ << Use(8, 10, 3, SemanticInfo::FunctionUse)
+ ;
+
+ TestData::check(source, expectedUses);
+}
+
+void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_templateParameter()
+{
+ const QByteArray source =
+ "struct Foo\n"
+ "{\n"
+ " static int foo();\n"
+ "};\n"
+ "\n"
+ "template <class foo>\n"
+ "void bar()\n"
+ "{\n"
+ " Foo::foo();\n"
+ "}\n"
+ ;
+
+ const QList<Use> expectedUses = QList<Use>()
+ << Use(1, 8, 3, SemanticInfo::TypeUse)
+ << Use(3, 16, 3, SemanticInfo::FunctionUse)
+ << Use(6, 17, 3, SemanticInfo::TypeUse)
+ << Use(7, 6, 3, SemanticInfo::FunctionUse)
+ << Use(9, 5, 3, SemanticInfo::TypeUse)
+ << Use(9, 10, 3, SemanticInfo::FunctionUse)
+ ;
+
+ TestData::check(source, expectedUses);
+}
+
+void tst_CheckSymbols::test_checksymbols_8902_staticFunctionHighlightingAsMember_struct()
+{
+ const QByteArray source =
+ "struct Foo\n"
+ "{\n"
+ " static int foo();\n"
+ "};\n"
+ "\n"
+ "struct foo {};\n"
+ "void bar()\n"
+ "{\n"
+ " Foo::foo();\n"
+ "}\n"
+ ;
+
+ const QList<Use> expectedUses = QList<Use>()
+ << Use(1, 8, 3, SemanticInfo::TypeUse)
+ << Use(3, 16, 3, SemanticInfo::FunctionUse)
+ << Use(6, 8, 3, SemanticInfo::TypeUse)
+ << Use(7, 6, 3, SemanticInfo::FunctionUse)
+ << Use(9, 5, 3, SemanticInfo::TypeUse)
+ << Use(9, 10, 3, SemanticInfo::FunctionUse)
+ ;
+
+ TestData::check(source, expectedUses);
+}
+
void tst_CheckSymbols::test_checksymbols_QTCREATORBUG8890_danglingPointer()
{
const QByteArray source =