From 4e0854f23c9b084c4fbfd02e304c28c292588f1a Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 15 Oct 2014 17:05:31 +0000 Subject: [PATCH] [libclang] Add function to retrieve storage class in libclang. Patch by guibufolo! llvm-svn: 219809 --- clang/bindings/python/clang/cindex.py | 61 +++++++++++++++++++++++++++ clang/include/clang-c/Index.h | 25 ++++++++++- clang/tools/libclang/CIndex.cpp | 35 +++++++++++++++ clang/tools/libclang/libclang.exports | 1 + 4 files changed, 121 insertions(+), 1 deletion(-) diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 8bcf9c3bda69..5792effea59b 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -1246,6 +1246,17 @@ class Cursor(Structure): 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): """ @@ -1510,6 +1521,56 @@ class Cursor(Structure): 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): diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 3e64718edbd3..389294904620 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 28 +#define CINDEX_VERSION_MINOR 29 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -3342,6 +3342,29 @@ enum CX_CXXAccessSpecifier { */ 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. diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 552f5a70a5ba..8b829c7d50c3 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6418,6 +6418,41 @@ static const Decl *maybeGetTemplateCursor(const Decl *D) { 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)) { diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports index d7701ad97517..fa2c0e70bf32 100644 --- a/clang/tools/libclang/libclang.exports +++ b/clang/tools/libclang/libclang.exports @@ -30,6 +30,7 @@ clang_Cursor_isNull clang_Cursor_isObjCOptional clang_Cursor_isVariadic clang_Cursor_getModule +clang_Cursor_getStorageClass clang_File_isEqual clang_Module_getASTFile clang_Module_getParent