/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ****************************************************************************/ #include "clangtype.h" #include "clangstring.h" #include "cursor.h" #include #include namespace ClangBackEnd { bool Type::isValid() const { return m_cxType.kind != CXType_Invalid; } bool Type::isConstant() const { return clang_isConstQualifiedType(m_cxType); } bool Type::isConstantReference() { return isLValueReference() && pointeeType().isConstant(); } bool Type::isPointer() const { return m_cxType.kind == CXType_Pointer; } bool Type::isPointerToConstant() const { return isPointer() && pointeeType().isConstant(); } bool Type::isConstantPointer() const { return isPointer() && isConstant(); } bool Type::isLValueReference() const { return m_cxType.kind == CXType_LValueReference; } bool Type::isReferencingConstant() const { return (isPointer() || isLValueReference()) && pointeeType().isConstant(); } bool Type::isOutputArgument() const { if (isLValueReference() && !pointeeType().isConstant()) return true; // We consider a pointer an output argument if it is non-const at any level. // This is consistent with how we categorize references in CppEditor. Type t = *this; while (t.isPointer()) { t = t.pointeeType(); if (!t.isConstant()) return true; } return false; } bool Type::isBuiltinType() const { return m_cxType.kind >= CXType_FirstBuiltin && m_cxType.kind <= CXType_LastBuiltin; } bool Type::isUnsigned() const { return m_cxType.kind == CXType_UChar || m_cxType.kind == CXType_UShort || m_cxType.kind == CXType_UInt || m_cxType.kind == CXType_ULong || m_cxType.kind == CXType_ULongLong || m_cxType.kind == CXType_UInt128; } Utf8String Type::utf8Spelling() const { return ClangString(clang_getTypeSpelling(m_cxType)); } ClangString Type::spelling() const { return ClangString(clang_getTypeSpelling(m_cxType)); } static const char *builtinTypeToText(CXTypeKind kind) { // CLANG-UPGRADE-CHECK: Check for added built-in types. switch (kind) { case CXType_Void: return "void"; case CXType_Bool: return "bool"; // See also ${CLANG_REPOSITORY}/lib/Sema/SemaChecking.cpp - IsSameCharType(). case CXType_Char_U: case CXType_UChar: return "unsigned char"; case CXType_Char_S: case CXType_SChar: return "signed char"; case CXType_Char16: return "char16_t"; case CXType_Char32: return "char32_t"; case CXType_WChar: return "wchar_t"; case CXType_UShort: return "unsigned short"; case CXType_UInt: return "unsigned int"; case CXType_ULong: return "unsigned long"; case CXType_ULongLong: return "unsigned long long"; case CXType_Short: return "short"; case CXType_Int: return "int"; case CXType_Long: return "long"; case CXType_LongLong: return "long long"; case CXType_Float: return "float"; case CXType_Double: return "double"; case CXType_LongDouble: return "long double"; case CXType_NullPtr: return "nullptr_t"; // https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html case CXType_Int128: return "__int128"; case CXType_UInt128: return "unsigned __int128"; // https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html case CXType_Float128: return "__float128"; case CXType_Float16: return "_Float16"; // https://www.khronos.org/registry/OpenCL/sdk/2.1/docs/man/xhtml/scalarDataTypes.html case CXType_Half: return "half"; default: return ""; } } Utf8String Type::builtinTypeToString() const { const char *text = builtinTypeToText(m_cxType.kind); return Utf8String::fromByteArray(QByteArray::fromRawData(text, int(strlen(text)))); } int Type::argumentCount() const { return clang_getNumArgTypes(m_cxType); } Type Type::alias() const { return clang_getTypedefDeclUnderlyingType(clang_getTypeDeclaration(m_cxType)); } Type Type::canonical() const { return clang_getCanonicalType(m_cxType); } Type Type::classType() const { return clang_Type_getClassType(m_cxType); } Type Type::pointeeType() const { return clang_getPointeeType(m_cxType); } Type Type::resultType() const { return clang_getResultType(m_cxType); } Type Type::argument(int index) const { return clang_getArgType(m_cxType, index); } Cursor Type::declaration() const { return clang_getTypeDeclaration(m_cxType); } long long Type::sizeOf(bool *isValid) const { const long long size = clang_Type_getSizeOf(m_cxType); *isValid = size != CXTypeLayoutError_Invalid && size != CXTypeLayoutError_Incomplete && size != CXTypeLayoutError_Dependent; return size; } CXTypeKind Type::kind() const { return m_cxType.kind; } Type::Type(CXType cxType) : m_cxType(cxType) { } bool operator==(Type first, Type second) { return clang_equalTypes(first.m_cxType, second.m_cxType); } bool operator!=(Type first, Type second) { return !operator==(first, second); } std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind) { ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind)); return os << typeKindSpelling.cString(); } std::ostream &operator<<(std::ostream &os, const Type &type) { ClangString typeKindSpelling(clang_getTypeKindSpelling(type.kind())); os << typeKindSpelling << ": \"" << type.spelling() << "\""; return os; } } // namespace ClangBackEnd