diff --git a/src/tools/clangbackend/source/tokeninfo.cpp b/src/tools/clangbackend/source/tokeninfo.cpp index f5a3622662c..5ac579570ea 100644 --- a/src/tools/clangbackend/source/tokeninfo.cpp +++ b/src/tools/clangbackend/source/tokeninfo.cpp @@ -226,6 +226,28 @@ bool TokenInfo::isArgumentInCurrentOutputArgumentLocations() const return isOutputArgument; } +// For reasons I don't fully understand, the cursors from clang_annotateTokens() are sometimes +// not the actual cursor for the respective token, but the one for a construct higher up +// in the syntax tree. This is often not what we want (e.g. QTCREATORBUG-21522, QTCREATORBUG-21534), +// so in such cases we re-retrieve the cursor for the token via clang_getCursor(). +Cursor TokenInfo::realCursor(const Cursor &cursor) const +{ + // Magic Qt stuff. + if (cursor.kind() == CXCursor_InvalidFile) + return cursor; + + const SourceLocation tokenLoc = m_token->location(); + const SourceLocation cursorLoc = cursor.sourceLocation(); + if (tokenLoc == cursorLoc) + return cursor; + + // Note: clang_getTokenLocation() does not work. + const CXFile cxFile = clang_getFile(m_token->tu(), tokenLoc.filePath().toByteArray()); + const CXSourceLocation cxLoc = clang_getLocation(m_token->tu(), cxFile, tokenLoc.line(), + tokenLoc.column()); + return clang_getCursor(m_token->tu(), cxLoc); +} + bool TokenInfo::isOutputArgument() const { if (m_currentOutputArgumentRanges->empty()) @@ -358,6 +380,14 @@ void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) if (cursor.isInvalidDeclaration()) return; + if (recursion == Recursion::FirstPass) { + const Cursor c = realCursor(cursor); + if (!clang_isInvalid(c.kind()) && c != cursor) { + identifierKind(c, Recursion::FirstPass); + return; + } + } + const CXCursorKind kind = cursor.kind(); switch (kind) { case CXCursor_Destructor: @@ -452,18 +482,8 @@ void TokenInfo::identifierKind(const Cursor &cursor, Recursion recursion) case CXCursor_InvalidFile: invalidFileKind(); break; - default: { - // QTCREATORBUG-21522 - // Note: clang_getTokenLocation() does not work. - const SourceLocation loc = m_token->location(); - const CXFile cxFile = clang_getFile(m_token->tu(), loc.filePath().toByteArray()); - const CXSourceLocation cxLoc = clang_getLocation(m_token->tu(), cxFile, loc.line(), - loc.column()); - const CXCursor realCursor = clang_getCursor(m_token->tu(), cxLoc); - if (realCursor != cursor) - identifierKind(realCursor, Recursion::FirstPass); + default: break; - } } } diff --git a/src/tools/clangbackend/source/tokeninfo.h b/src/tools/clangbackend/source/tokeninfo.h index 7e125ad5e62..bcb77bddeed 100644 --- a/src/tools/clangbackend/source/tokeninfo.h +++ b/src/tools/clangbackend/source/tokeninfo.h @@ -114,6 +114,7 @@ private: void collectOutputArguments(const Cursor &cursor); void filterOutPreviousOutputArguments(); bool isArgumentInCurrentOutputArgumentLocations() const; + Cursor realCursor(const Cursor &cursor) const; std::vector *m_currentOutputArgumentRanges = nullptr; uint m_line = 0; diff --git a/tests/unit/unittest/data/highlightingmarks.cpp b/tests/unit/unittest/data/highlightingmarks.cpp index a28210012b5..bc90444028e 100644 --- a/tests/unit/unittest/data/highlightingmarks.cpp +++ b/tests/unit/unittest/data/highlightingmarks.cpp @@ -745,3 +745,9 @@ void f4() ASSIGN(int i, thePointer); ASSIGN2(int i, thePointer); } + +const int MyConstant = 8; +void f5() +{ + int arr[MyConstant][8]; +} diff --git a/tests/unit/unittest/tokenprocessor-test.cpp b/tests/unit/unittest/tokenprocessor-test.cpp index a80d90eec43..b1956bbcfdd 100644 --- a/tests/unit/unittest/tokenprocessor-test.cpp +++ b/tests/unit/unittest/tokenprocessor-test.cpp @@ -1776,6 +1776,13 @@ TEST_F(TokenProcessor, IndirectMacro) ASSERT_THAT(infos[5], IsHighlightingMark(746u, 20u, 10u, HighlightingType::LocalVariable)); } +TEST_F(TokenProcessor, MultiDimArray) +{ + const auto infos = translationUnit.tokenInfosInRange(sourceRange(752, 28)); + + ASSERT_THAT(infos[3], IsHighlightingMark(752u, 13u, 10u, HighlightingType::GlobalVariable)); +} + Data *TokenProcessor::d; void TokenProcessor::SetUpTestCase()