From a3a62e78f7378182138555936b45a885865c00ad Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar <nikolai.kosjar@qt.io>
Date: Thu, 1 Jun 2017 11:00:59 +0200
Subject: [PATCH] Clang: Fix highlighting of function in using declaration

Change-Id: I0f646ce22cdc95e5932650a3fb2fe34b8d4a89a3
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
Reviewed-by: David Schulz <david.schulz@qt.io>
---
 src/tools/clangbackend/ipcsource/cursor.cpp        | 10 ++++++++++
 src/tools/clangbackend/ipcsource/cursor.h          |  3 +++
 .../clangbackend/ipcsource/highlightingmark.cpp    | 14 +++++++++++++-
 .../clangbackend/ipcsource/highlightingmark.h      |  1 +
 tests/unit/unittest/data/highlightingmarks.cpp     |  3 +++
 tests/unit/unittest/highlightingmarks-test.cpp     |  7 +++++++
 6 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/ipcsource/cursor.cpp
index 56dfd9e610..1bc494ec71 100644
--- a/src/tools/clangbackend/ipcsource/cursor.cpp
+++ b/src/tools/clangbackend/ipcsource/cursor.cpp
@@ -296,6 +296,16 @@ Cursor Cursor::argument(int index) const
     return clang_Cursor_getArgument(cxCursor, index);
 }
 
+unsigned Cursor::overloadedDeclarationsCount() const
+{
+    return clang_getNumOverloadedDecls(cxCursor);
+}
+
+Cursor Cursor::overloadedDeclaration(unsigned index) const
+{
+    return clang_getOverloadedDecl(cxCursor, index);
+}
+
 namespace {
 
 bool isNotUnexposedLValueReference(const Cursor &argument, const Type &argumentType)
diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h
index 8f294c7e26..8b5e72df3d 100644
--- a/src/tools/clangbackend/ipcsource/cursor.h
+++ b/src/tools/clangbackend/ipcsource/cursor.h
@@ -93,6 +93,9 @@ public:
     Cursor functionBaseDeclaration() const;
     Cursor functionBase() const;
     Cursor argument(int index) const;
+    unsigned overloadedDeclarationsCount() const;
+    Cursor overloadedDeclaration(unsigned index) const;
+
     void collectOutputArgumentRangesTo(
             std::vector<CXSourceRange> &outputArgumentRanges) const;
     std::vector<CXSourceRange> outputArgumentRanges() const;
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.cpp b/src/tools/clangbackend/ipcsource/highlightingmark.cpp
index 7a4537e9d7..b448b45f11 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.cpp
+++ b/src/tools/clangbackend/ipcsource/highlightingmark.cpp
@@ -157,6 +157,18 @@ void HighlightingMark::referencedTypeKind(const Cursor &cursor)
     }
 }
 
+void HighlightingMark::overloadedDeclRefKind(const Cursor &cursor)
+{
+    types.mainHighlightingType = HighlightingType::Function;
+
+    // Workaround https://bugs.llvm.org//show_bug.cgi?id=33256 - SomeType in
+    // "using N::SomeType" is mistakenly considered as a CXCursor_OverloadedDeclRef.
+    if (cursor.overloadedDeclarationsCount() >= 1
+            && cursor.overloadedDeclaration(0).kind() != CXCursor_FunctionDecl) {
+        types.mainHighlightingType = HighlightingType::Type;
+    }
+}
+
 void HighlightingMark::variableKind(const Cursor &cursor)
 {
     if (cursor.isLocalVariable())
@@ -298,7 +310,6 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
         case CXCursor_TemplateTemplateParameter:
         case CXCursor_UnionDecl:
         case CXCursor_StructDecl:
-        case CXCursor_OverloadedDeclRef:
         case CXCursor_TemplateRef:
         case CXCursor_Namespace:
         case CXCursor_NamespaceRef:
@@ -317,6 +328,7 @@ void HighlightingMark::identifierKind(const Cursor &cursor, Recursion recursion)
         case CXCursor_ObjCProtocolRef:
         case CXCursor_ObjCClassRef:
         case CXCursor_ObjCSuperClassRef:         types.mainHighlightingType = HighlightingType::Type; break;
+        case CXCursor_OverloadedDeclRef:         overloadedDeclRefKind(cursor); break;
         case CXCursor_FunctionTemplate:          types.mainHighlightingType = HighlightingType::Function; break;
         case CXCursor_EnumConstantDecl:          types.mainHighlightingType = HighlightingType::Enumeration; break;
         case CXCursor_PreprocessingDirective:    types.mainHighlightingType = HighlightingType::Preprocessor; break;
diff --git a/src/tools/clangbackend/ipcsource/highlightingmark.h b/src/tools/clangbackend/ipcsource/highlightingmark.h
index b2c05f4d55..f678e0954c 100644
--- a/src/tools/clangbackend/ipcsource/highlightingmark.h
+++ b/src/tools/clangbackend/ipcsource/highlightingmark.h
@@ -63,6 +63,7 @@ public:
 private:
     void identifierKind(const Cursor &cursor, Recursion recursion);
     void referencedTypeKind(const Cursor &cursor);
+    void overloadedDeclRefKind(const Cursor &cursor);
     void variableKind(const Cursor &cursor);
     void fieldKind(const Cursor &cursor);
     bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp
index ce2312d144..2880a1fc70 100644
--- a/tests/unit/unittest/data/highlightingmarks.cpp
+++ b/tests/unit/unittest/data/highlightingmarks.cpp
@@ -551,3 +551,6 @@ struct NonConstReferenceMemberInitialization
 
 template<class T> class Coo;
 template<class T> class Coo<T*>;
+
+namespace N { void goo(); }
+using N::goo;
diff --git a/tests/unit/unittest/highlightingmarks-test.cpp b/tests/unit/unittest/highlightingmarks-test.cpp
index 3b67d037be..4cecb620fc 100644
--- a/tests/unit/unittest/highlightingmarks-test.cpp
+++ b/tests/unit/unittest/highlightingmarks-test.cpp
@@ -1112,6 +1112,13 @@ TEST_F(HighlightingMarks, ClassTemplateParticalSpecialization)
     ASSERT_THAT(infos[6], HasOnlyType(HighlightingType::Type));
 }
 
+TEST_F(HighlightingMarks, UsingFunction)
+{
+    const auto infos = translationUnit.highlightingMarksInRange(sourceRange(556, 27));
+
+    ASSERT_THAT(infos[3], HasOnlyType(HighlightingType::Function));
+}
+
 Data *HighlightingMarks::d;
 
 void HighlightingMarks::SetUpTestCase()
-- 
GitLab