Skip to content

Commit

Permalink
[libclang] Add function to retrieve storage class in libclang.
Browse files Browse the repository at this point in the history
Patch by guibufolo!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219809 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
akyrtzi committed Oct 15, 2014
1 parent 822389d commit 763069a
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
61 changes: 61 additions & 0 deletions bindings/python/clang/cindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,17 @@ def extent(self):

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):
"""
Expand Down Expand Up @@ -1510,6 +1521,56 @@ def from_cursor_result(res, fn, args):
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):
Expand Down
25 changes: 24 additions & 1 deletion include/clang-c/Index.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -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.
Expand Down
35 changes: 35 additions & 0 deletions tools/libclang/CIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
1 change: 1 addition & 0 deletions tools/libclang/libclang.exports
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 763069a

Please sign in to comment.