Index: plugins/clang/duchain/builder.cpp =================================================================== --- plugins/clang/duchain/builder.cpp +++ plugins/clang/duchain/builder.cpp @@ -1204,7 +1204,7 @@ CXChildVisitResult Visitor::buildUse(CXCursor cursor) { m_uses[m_parentContext->context].push_back(cursor); - return cursor.kind == CXCursor_DeclRefExpr || cursor.kind == CXCursor_MemberRefExpr ? + return cursor.kind == CXCursor_DeclRefExpr || cursor.kind == CXCursor_MemberRefExpr || cursor.kind == CXCursor_ObjCMessageExpr ? CXChildVisit_Recurse : CXChildVisit_Continue; } @@ -1223,9 +1223,9 @@ template CXChildVisitResult Visitor::buildCompoundStatement(CXCursor cursor) { - if (CK == CXCursor_LambdaExpr || m_parentContext->context->type() == DUContext::Function) + if (CK == CXCursor_LambdaExpr || CK == CXCursor_BlockExpr || m_parentContext->context->type() == DUContext::Function) { - auto context = createContext(cursor); + auto context = createContext(cursor); CurrentContext newParent(context, m_parentContext->keepAliveContexts); PushValue pushCurrent(m_parentContext, &newParent); clang_visitChildren(cursor, &visitCursor, this); @@ -1562,13 +1562,16 @@ case CXCursor_DeclRefExpr: case CXCursor_MemberRefExpr: case CXCursor_ObjCClassRef: + case CXCursor_ObjCMessageExpr: return visitor->buildUse(cursor); case CXCursor_MacroExpansion: return visitor->buildMacroExpansion(cursor); case CXCursor_CompoundStmt: return visitor->buildCompoundStatement(cursor); case CXCursor_LambdaExpr: return visitor->buildCompoundStatement(cursor); + case CXCursor_BlockExpr: + return visitor->buildCompoundStatement(cursor); case CXCursor_CXXBaseSpecifier: return visitor->buildCXXBaseSpecifier(cursor); case CXCursor_ParmDecl: Index: plugins/clang/duchain/cursorkindtraits.h =================================================================== --- plugins/clang/duchain/cursorkindtraits.h +++ plugins/clang/duchain/cursorkindtraits.h @@ -55,6 +55,19 @@ || CK == CXCursor_ObjCCategoryImplDecl; } +// TODO: somehow this is (probably) the function to call in isKDevForwardDeclaration() but +// I cannot seem to understand how to achieve that without raising a ton of +// uncomprehensible errors in builder.cpp (I can't even remove the ObjC cursor +// kinds from the isClass function above?!) +// TODO: remove this comment. +constexpr bool isClassNoObjC(CXCursorKind CK) +{ + return isClassTemplate(CK) + || CK == CXCursor_StructDecl + || CK == CXCursor_ClassDecl + || CK == CXCursor_UnionDecl; +} + constexpr bool isFunction(CXCursorKind CK) { return CK == CXCursor_FunctionDecl Index: plugins/clang/duchain/documentfinderhelpers.cpp =================================================================== --- plugins/clang/duchain/documentfinderhelpers.cpp +++ plugins/clang/duchain/documentfinderhelpers.cpp @@ -183,7 +183,8 @@ QStringLiteral("text/x-csrc"), QStringLiteral("text/x-c++src"), QStringLiteral("text/vnd.nvidia.cuda.csrc"), - QStringLiteral("text/x-objcsrc") + QStringLiteral("text/x-objcsrc"), + QStringLiteral("text/x-objc++src") }; return mimeTypes; } Index: plugins/clang/duchain/parsesession.cpp =================================================================== --- plugins/clang/duchain/parsesession.cpp +++ plugins/clang/duchain/parsesession.cpp @@ -90,10 +90,6 @@ QVector argsForSession(const QString& path, ParseSessionData::Options options, const ParserSettings& parserSettings) { QMimeDatabase db; - if(db.mimeTypeForFile(path).name() == QStringLiteral("text/x-objcsrc")) { - return {QByteArrayLiteral("-xobjective-c++")}; - } - // TODO: No proper mime type detection possible yet // cf. https://bugs.freedesktop.org/show_bug.cgi?id=26913 if (path.endsWith(QLatin1String(".cl"), Qt::CaseInsensitive)) { @@ -109,19 +105,20 @@ return result; } + auto result = parserSettings.toClangAPI(); if (parserSettings.parserOptions.isEmpty()) { // The parserOptions can be empty for some unit tests that use ParseSession directly - auto defaultArguments = ClangSettingsManager::self()->parserSettings(path).toClangAPI(); - - defaultArguments.append(QByteArrayLiteral("-nostdinc")); - defaultArguments.append(QByteArrayLiteral("-nostdinc++")); - defaultArguments.append(QByteArrayLiteral("-xc++")); + result = ClangSettingsManager::self()->parserSettings(path).toClangAPI(); - sanitizeArguments(defaultArguments); - return defaultArguments; +// FIXME: remove commented lines if the new flow is ratified, else revert change. +// defaultArguments.append(QByteArrayLiteral("-nostdinc")); +// defaultArguments.append(QByteArrayLiteral("-nostdinc++")); +// defaultArguments.append(QByteArrayLiteral("-xc++")); +// +// sanitizeArguments(defaultArguments); +// return defaultArguments; } - auto result = parserSettings.toClangAPI(); result.append(QByteArrayLiteral("-nostdinc")); if (parserSettings.isCpp()) { result.append(QByteArrayLiteral("-nostdinc++")); @@ -134,7 +131,18 @@ return result; } - result.append(parserSettings.isCpp() ? QByteArrayLiteral("-xc++") : QByteArrayLiteral("-xc")); + // check the C family membership and set the appropriate mode + // overriding any inappropriate modes set earlier in the args list. + const auto mimeType = db.mimeTypeForFile(path).name(); + if (mimeType == QStringLiteral("text/x-objc++src")) { + result.append(QByteArrayLiteral("-xobjective-c++")); + } else if (mimeType == QStringLiteral("text/x-objcsrc")) { + result.append(QByteArrayLiteral(" -ObjC")); + } else if (parserSettings.isCpp()) { + result.append(QByteArrayLiteral("-xc++")); + } else { + result.append(QByteArrayLiteral("-xc")); + } sanitizeArguments(result); return result; Index: plugins/clang/kdevclang.xml =================================================================== --- plugins/clang/kdevclang.xml +++ plugins/clang/kdevclang.xml @@ -72,4 +72,18 @@ + + + + Objective-C++ source code + + + + + + + Index: plugins/clang/kdevclangsupport.json =================================================================== --- plugins/clang/kdevclangsupport.json +++ plugins/clang/kdevclangsupport.json @@ -61,18 +61,20 @@ "C++", "OpenCL C", "CUDA C", - "Objective-C" + "Objective-C", + "Objective-C++" ], "X-KDevelop-LoadMode": "AlwaysOn", "X-KDevelop-Mode": "NoGUI", "X-KDevelop-SupportedMimeTypes": [ "text/x-chdr", "text/x-c++hdr", "text/x-csrc", "text/x-c++src", + "text/x-objcsrc", + "text/x-objc++src", "text/x-opencl-src", "text/vnd.nvidia.cuda.csrc", - "text/vnd.nvidia.cuda.chdr", - "text/x-objcsrc" + "text/vnd.nvidia.cuda.chdr" ] } Index: plugins/clang/tests/files/objc.m =================================================================== --- /dev/null +++ plugins/clang/tests/files/objc.m @@ -0,0 +1,17 @@ + +/// "type" : { "toString" : "NSString" }, +/// "useCount" : 2 +@interface NSString +{ +} +@end + +/// "identifiedTypeDeclaration" : { "isDefinition" : false } +NSString* f; + +/// "type" : { "toString" : "NSString*" } +NSString *strn = @"NSString or CFString"; + +#ifndef __OBJC__ +NSString *strn2 = "C String"; // in ObjC this would raise the error "String literal must be prefixed by '@'" +#endif Index: plugins/clang/tests/files/objcpp.mm =================================================================== --- /dev/null +++ plugins/clang/tests/files/objcpp.mm @@ -0,0 +1,113 @@ +/** + * "identifier" : "main", + * "internalContext" : { "type" : "Function", "range" : "[(5, 0), (8, 1)]" }, + * "range" : "[(5, 4), (5, 8)]" + */ +int main() +{ + return 0; +} + +/** + * "identifier" : "bar", + * "internalContext" : { "type" : "Namespace", "range" : "[(15, 0), (93, 1)]" }, + * "kind" : "Namespace" + */ +namespace bar +{ + /** + * "identifier" : "foo", + * "internalContext" : { "null" : false, "range" : "[(21, 4), (21, 14)]" } + */ + void foo(); + + /** + * "identifier" : "foostruct", + * "internalContext" : { "type" : "Class", "range" : "[(27, 4), (92, 5)]" } + */ + struct foostruct + { + /** + * "identifier" : "foostruct", + * "internalContext" : { "type" : "Function", "range" : "[(33, 8), (35, 9)]" } + */ + foostruct() + { + } + + /** + * "identifier" : "~foostruct", "range" : "[(41, 8), (41, 18)]", + * "internalContext" : { "type" : "Function", "range" : "[(41, 8), (43, 9)]" } + */ + ~foostruct() + { + } + + /** + * "identifier" : "operator int", + * "internalContext" : { "type" : "Function", "range" : "[(49, 8), (52, 9)]" } + */ + operator int() + { + return 0; + } + + /** + * "identifier" : "templateFunction", + * "internalContext" : { "type" : "Function", "range" : "[(58, 8), (61, 9)]" } + */ + template + void templateFunction() + { + } + + /** + * "identifier" : "fooenum", + * "internalContext" : { "type" : "Enum", "range" : "[(67, 8), (69, 9)]" } + */ + enum fooenum + { + }; + + /** + * "identifier" : "foomethod", + * "internalContext" : { "type" : "Function", "range" : "[(75, 8), (75, 23)]" } + */ + int foomethod(); + + /** + * "identifier" : "deffoomethod", + * "internalContext" : { "type" : "Function", "range" : "[(81, 8), (83, 9)]" } + */ + void deffoomethod() + { + } + + /** + * "identifier" : "operator=", "range" : "[(89, 19), (89, 28)]", + * "internalContext" : { "type" : "Function", "range" : "[(89, 8), (91, 9)]" } + */ + foostruct& operator=(const foostruct& other) + { return *this; + } + }; +} + +/// "identifier" : "", "range" : "[(96, 0), (96, 0)]" +struct {} unnamedStructObject; + +/// "identifier" : "", "range" : "[(99, 0), (99, 0)]" +union {} unnamedUnionObject; + +/// "type" : { "toString" : "NSString" }, +/// "useCount" : 1 +@class NSString; + +/// "type" : { "toString" : "NSString*" } +NSString *strn = @"NSString or CFString"; + +/// "type" : { "toString" : "NSString*" } +auto b = @"Another string"; + + + Index: plugins/clang/tests/test_files.cpp =================================================================== --- plugins/clang/tests/test_files.cpp +++ plugins/clang/tests/test_files.cpp @@ -66,7 +66,7 @@ { QTest::addColumn("fileName"); const QString testDirPath = TEST_FILES_DIR; - const QStringList files = QDir(testDirPath).entryList({"*.h", "*.cpp", "*.c", "*.cl", "*.cu"}, QDir::Files); + const QStringList files = QDir(testDirPath).entryList({"*.h", "*.cpp", "*.c", "*.cl", "*.cu", "*.m", "*.mm"}, QDir::Files); for (const QString& file : files) { QTest::newRow(file.toUtf8().constData()) << QString(testDirPath + '/' + file); }