Index: bindings/python/clang/cindex.py =================================================================== --- bindings/python/clang/cindex.py +++ bindings/python/clang/cindex.py @@ -1247,6 +1247,17 @@ return self._extent @property + def storage_class(self): + """ + Retrieves the storage class (if any) of the entity pointed at by the + cursor. + """ + if not hasattr(self, '_storage_class'): + self._storage_class = conf.lib.clang_Cursor_getStorageClass(self) + + return StorageClass.from_id(self._storage_class) + + @property def access_specifier(self): """ Retrieves the access specifier (if any) of the entity pointed at by the @@ -1510,6 +1521,56 @@ res._tu = args[0]._tu return res +class StorageClass(object): + """ + Describes the storage class of a declaration + """ + + # The unique kind objects, index by id. + _kinds = [] + _name_map = None + + def __init__(self, value): + if value >= len(StorageClass._kinds): + StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1) + if StorageClass._kinds[value] is not None: + raise ValueError,'StorageClass already loaded' + self.value = value + StorageClass._kinds[value] = self + StorageClass._name_map = None + + def from_param(self): + return self.value + + @property + def name(self): + """Get the enumeration name of this storage class.""" + if self._name_map is None: + self._name_map = {} + for key,value in StorageClass.__dict__.items(): + if isinstance(value,StorageClass): + self._name_map[value] = key + return self._name_map[self] + + @staticmethod + def from_id(id): + if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]: + raise ValueError,'Unknown storage class %d' % id + return StorageClass._kinds[id] + + def __repr__(self): + return 'StorageClass.%s' % (self.name,) + +StorageClass.INVALID = StorageClass(0) +StorageClass.NONE = StorageClass(1) +StorageClass.EXTERN = StorageClass(2) +StorageClass.STATIC = StorageClass(3) +StorageClass.PRIVATEEXTERN = StorageClass(4) +StorageClass.OPENCLWORKGROUPLOCAL = StorageClass(5) +StorageClass.AUTO = StorageClass(6) +StorageClass.REGISTER = StorageClass(7) + + ### C++ access specifiers ### class AccessSpecifier(BaseEnumeration): Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3343,6 +3343,29 @@ CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor); /** + * \brief Represents the storage classes as declared in the source. CX_SC_Invalid + * was added for the clase that the passed cursor in not a declaration. + */ +enum CX_StorageClass { + CX_SC_Invalid, + CX_SC_None, + CX_SC_Extern, + CX_SC_Static, + CX_SC_PrivateExtern, + CX_SC_OpenCLWorkGroupLocal, + CX_SC_Auto, + CX_SC_Register +}; + +/** + * \brief Returns the storage class for a function or variable declaration. + * + * If the passed in Cursor is not a function or variable declaration, + * CX_SC_Invalid is returned else the storage class. + */ +CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor); + +/** * \brief Determine the number of overloaded declarations referenced by a * \c CXCursor_OverloadedDeclRef cursor. * Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -6417,6 +6417,41 @@ return D; } + +enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor C) { + StorageClass sc = SC_None; + const Decl *D = getCursorDecl(C); + if (D) { + if (const FunctionDecl *FD = dyn_cast(D)) { + sc = FD->getStorageClass(); + } else if (const VarDecl *VD = dyn_cast(D)) { + sc = VD->getStorageClass(); + } else { + return CX_SC_Invalid; + } + } else { + return CX_SC_Invalid; + } + switch (sc) { + case SC_None: + return CX_SC_None; + case SC_Extern: + return CX_SC_Extern; + case SC_Static: + return CX_SC_Static; + case SC_PrivateExtern: + return CX_SC_PrivateExtern; + case SC_OpenCLWorkGroupLocal: + return CX_SC_OpenCLWorkGroupLocal; + case SC_Auto: + return CX_SC_Auto; + case SC_Register: + return CX_SC_Register; + default: + return CX_SC_Invalid; + } +} + CXCursor clang_getCursorSemanticParent(CXCursor cursor) { if (clang_isDeclaration(cursor.kind)) { if (const Decl *D = getCursorDecl(cursor)) { Index: tools/libclang/libclang.exports =================================================================== --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -30,6 +30,7 @@ clang_Cursor_isObjCOptional clang_Cursor_isVariadic clang_Cursor_getModule +clang_Cursor_getStorageClass clang_File_isEqual clang_Module_getASTFile clang_Module_getParent