]> granicus.if.org Git - clang/commitdiff
[libclang] Add function to retrieve storage class in libclang.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 15 Oct 2014 17:05:31 +0000 (17:05 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 15 Oct 2014 17:05:31 +0000 (17:05 +0000)
Patch by guibufolo!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219809 91177308-0d34-0410-b5e6-96231b3b80d8

bindings/python/clang/cindex.py
include/clang-c/Index.h
tools/libclang/CIndex.cpp
tools/libclang/libclang.exports

index 8bcf9c3bda69c673b923d3979d0d2482e51a0173..5792effea59be61ad12a1e48ba811a6d5b36efeb 100644 (file)
@@ -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):
index 3e64718edbd3d7560ad5219f4e7a9faf87d15bec..3892949046204cb195acf7dda7729398d3931056 100644 (file)
@@ -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.
index 552f5a70a5baef7bc52ecd16933e590e054726f4..8b829c7d50c3799871d6e3a95a60824c3dba3829 100644 (file)
@@ -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<FunctionDecl>(D)) {
+      sc = FD->getStorageClass();
+    } else if (const VarDecl *VD = dyn_cast<VarDecl>(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 d7701ad97517b8c8ab769699369f851c4843c6a8..fa2c0e70bf32135cf4f07cd02e549f11feb3849c 100644 (file)
@@ -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