diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 5710d7fe28ea..cbce1a2d3fa5 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -1499,6 +1499,50 @@ TypeKind.VARIABLEARRAY = TypeKind(115) TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116) TypeKind.MEMBERPOINTER = TypeKind(117) +class RefQualifierKind(object): + """Describes a specific ref-qualifier of a type.""" + + # The unique kind objects, indexed by id. + _kinds = [] + _name_map = None + + def __init__(self, value): + if value >= len(RefQualifierKind._kinds): + num_kinds = value - len(RefQualifierKind._kinds) + 1 + RefQualifierKind._kinds += [None] * num_kinds + if RefQualifierKind._kinds[value] is not None: + raise ValueError, 'RefQualifierKind already loaded' + self.value = value + RefQualifierKind._kinds[value] = self + RefQualifierKind._name_map = None + + def from_param(self): + return self.value + + @property + def name(self): + """Get the enumeration name of this kind.""" + if self._name_map is None: + self._name_map = {} + for key, value in RefQualifierKind.__dict__.items(): + if isinstance(value, RefQualifierKind): + self._name_map[value] = key + return self._name_map[self] + + @staticmethod + def from_id(id): + if (id >= len(RefQualifierKind._kinds) or + RefQualifierKind._kinds[id] is None): + raise ValueError, 'Unknown type kind %d' % id + return RefQualifierKind._kinds[id] + + def __repr__(self): + return 'RefQualifierKind.%s' % (self.name,) + +RefQualifierKind.NONE = RefQualifierKind(0) +RefQualifierKind.LVALUE = RefQualifierKind(1) +RefQualifierKind.RVALUE = RefQualifierKind(2) + class Type(Structure): """ The type of an element in the abstract syntax tree. @@ -1697,6 +1741,13 @@ class Type(Structure): """ return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) + def get_ref_qualifier(self): + """ + Retrieve the ref-qualifier of the type. + """ + return RefQualifierKind.from_id( + conf.lib.clang_Type_getCXXRefQualifier(self)) + @property def spelling(self): """Retrieve the spelling of this Type.""" @@ -2716,11 +2767,6 @@ functionList = [ [Type], c_longlong), - ("clang_Type_getClassType", - [Type], - Type, - Type.from_result), - ("clang_getFieldDeclBitWidth", [Cursor], c_int), @@ -3164,6 +3210,11 @@ functionList = [ [Type], c_longlong), + ("clang_Type_getClassType", + [Type], + Type, + Type.from_result), + ("clang_Type_getOffsetOf", [Type, c_char_p], c_longlong), @@ -3171,6 +3222,10 @@ functionList = [ ("clang_Type_getSizeOf", [Type], c_longlong), + + ("clang_Type_getCXXRefQualifier", + [Type], + c_uint), ] class LibclangError(Exception): diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index ca0bc14eb272..c8cdcb785517 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -3002,6 +3002,23 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T); */ CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S); +enum CXRefQualifierKind { + /** \brief No ref-qualifier was provided. */ + CXRefQualifier_None = 0, + /** \brief An lvalue ref-qualifier was provided (\c &). */ + CXRefQualifier_LValue, + /** \brief An rvalue ref-qualifier was provided (\c &&). */ + CXRefQualifier_RValue +}; + +/** + * \brief Retrieve the ref-qualifier kind of a function or method. + * + * The ref-qualifier is returned for C++ functions or methods. For other types + * or non-C++ declarations, CXRefQualifier_None is returned. + */ +CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T); + /** * \brief Returns non-zero if the cursor specifies a Record member that is a * bitfield. diff --git a/clang/test/Index/print-type-cxx11.cpp b/clang/test/Index/print-type-cxx11.cpp new file mode 100644 index 000000000000..0ad547377462 --- /dev/null +++ b/clang/test/Index/print-type-cxx11.cpp @@ -0,0 +1,8 @@ +struct RefQualifierTest { + void f() & {}; + void f() && {}; +}; + +// RUN: c-index-test -test-print-type -std=c++11 %s | FileCheck %s +// CHECK: CXXMethod=f:2:8 (Definition) [type=void () &] [typekind=FunctionProto] lvalue-ref-qualifier [resulttype=void] [resulttypekind=Void] [isPOD=0] +// CHECK: CXXMethod=f:3:8 (Definition) [type=void () &&] [typekind=FunctionProto] rvalue-ref-qualifier [resulttype=void] [resulttypekind=Void] [isPOD=0] diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c index 2e8b58bff446..90a65282f4ca 100644 --- a/clang/tools/c-index-test/c-index-test.c +++ b/clang/tools/c-index-test/c-index-test.c @@ -1160,6 +1160,7 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); + enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); PrintCursor(cursor, NULL); PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); if (clang_isConstQualifiedType(T)) @@ -1168,6 +1169,10 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, printf(" volatile"); if (clang_isRestrictQualifiedType(T)) printf(" restrict"); + if (RQ == CXRefQualifier_LValue) + printf(" lvalue-ref-qualifier"); + if (RQ == CXRefQualifier_RValue) + printf(" rvalue-ref-qualifier"); /* Print the canonical type if it is different. */ { CXType CT = clang_getCanonicalType(T); diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 9233e975f6dd..1e2cb1898462 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -816,6 +816,24 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) { return CXTypeLayoutError_InvalidFieldName; } +enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) { + QualType QT = GetQualType(T); + if (QT.isNull()) + return CXRefQualifier_None; + const FunctionProtoType *FD = QT->getAs(); + if (!FD) + return CXRefQualifier_None; + switch (FD->getRefQualifier()) { + case RQ_None: + return CXRefQualifier_None; + case RQ_LValue: + return CXRefQualifier_LValue; + case RQ_RValue: + return CXRefQualifier_RValue; + } + return CXRefQualifier_None; +} + unsigned clang_Cursor_isBitField(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index 6f6e39228df6..9bf26c979d29 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -64,6 +64,7 @@ clang_Type_getAlignOf clang_Type_getClassType clang_Type_getSizeOf clang_Type_getOffsetOf +clang_Type_getCXXRefQualifier clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString