summaryrefslogtreecommitdiffstats
path: root/clang/tools
diff options
context:
space:
mode:
authorFrancois Pichet <pichet2000@gmail.com>2015-01-29 12:45:29 +0000
committerFrancois Pichet <pichet2000@gmail.com>2015-01-29 12:45:29 +0000
commitf3be1cc5a9d5d75665a3d3cff54d51a161608c59 (patch)
tree46912475ca949b759b5d1c72a19a102661f4b724 /clang/tools
parentfad390109502f97f25828a993fd3bc2500fa93f5 (diff)
downloadbcm5719-llvm-f3be1cc5a9d5d75665a3d3cff54d51a161608c59.tar.gz
bcm5719-llvm-f3be1cc5a9d5d75665a3d3cff54d51a161608c59.zip
libclang: Add three functions useful for dealing with anonymous fields:
clang_Cursor_getOffsetOfField clang_Cursor_isAnonymous clang_Type_visitFields Python: Add corresponding methods for dealing with anonymous fields. Patch by Loïc Jaquemet llvm-svn: 227432
Diffstat (limited to 'clang/tools')
-rw-r--r--clang/tools/c-index-test/c-index-test.c59
-rw-r--r--clang/tools/libclang/CXType.cpp76
-rw-r--r--clang/tools/libclang/libclang.exports3
3 files changed, 117 insertions, 21 deletions
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 56e4101399a..a49f758e8e9 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -1250,6 +1250,12 @@ static void PrintTypeAndTypeKind(CXType T, const char *Format) {
clang_disposeString(TypeKindSpelling);
}
+static enum CXVisitorResult FieldVisitor(CXCursor C,
+ CXClientData client_data) {
+ (*(int *) client_data)+=1;
+ return CXVisit_Continue;
+}
+
static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
CXClientData d) {
if (!clang_isInvalid(clang_getCursorKind(cursor))) {
@@ -1320,6 +1326,22 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");
}
}
+ /* Print the number of fields if they exist. */
+ {
+ int numFields = 0;
+ if (clang_Type_visitFields(T, FieldVisitor, &numFields)){
+ if (numFields != 0) {
+ printf(" [nbFields=%d]", numFields);
+ }
+ /* Print if it is an anonymous record. */
+ {
+ unsigned isAnon = clang_Cursor_isAnonymous(cursor);
+ if (isAnon != 0) {
+ printf(" [isAnon=%d]", isAnon);
+ }
+ }
+ }
+ }
printf("\n");
}
@@ -1353,28 +1375,29 @@ static enum CXChildVisitResult PrintTypeSize(CXCursor cursor, CXCursor p,
{
CXString FieldSpelling = clang_getCursorSpelling(cursor);
const char *FieldName = clang_getCString(FieldSpelling);
- /* recurse to get the root anonymous record parent */
- CXCursor Parent, Root;
+ /* recurse to get the first parent record that is not anonymous. */
+ CXCursor Parent, Record;
+ unsigned RecordIsAnonymous = 0;
if (clang_getCursorKind(cursor) == CXCursor_FieldDecl) {
- CXString RootParentSpelling;
- const char *RootParentName = 0;
- Parent = p;
+ Record = Parent = p;
do {
- if (RootParentName != 0)
- clang_disposeString(RootParentSpelling);
-
- Root = Parent;
- RootParentSpelling = clang_getCursorSpelling(Root);
- RootParentName = clang_getCString(RootParentSpelling);
- Parent = clang_getCursorSemanticParent(Root);
- } while (clang_getCursorType(Parent).kind == CXType_Record &&
- !strcmp(RootParentName, ""));
- clang_disposeString(RootParentSpelling);
- /* if RootParentName is "", record is anonymous. */
+ Record = Parent;
+ Parent = clang_getCursorSemanticParent(Record);
+ RecordIsAnonymous = clang_Cursor_isAnonymous(Record);
+ /* Recurse as long as the parent is a CXType_Record and the Record
+ is anonymous */
+ } while ( clang_getCursorType(Parent).kind == CXType_Record &&
+ RecordIsAnonymous > 0);
{
- long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Root),
+ long long Offset = clang_Type_getOffsetOf(clang_getCursorType(Record),
FieldName);
- printf(" [offsetof=%lld]", Offset);
+ long long Offset2 = clang_Cursor_getOffsetOfField(cursor);
+ if (Offset == Offset2){
+ printf(" [offsetof=%lld]", Offset);
+ } else {
+ /* Offsets will be different in anonymous records. */
+ printf(" [offsetof=%lld/%lld]", Offset, Offset2);
+ }
}
}
clang_disposeString(FieldSpelling);
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index 4d526fbd59f..7063077d5e0 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -775,13 +775,12 @@ static long long visitRecordForValidation(const RecordDecl *RD) {
return 0;
}
-long long clang_Type_getOffsetOf(CXType PT, const char *S) {
- // check that PT is not incomplete/dependent
- CXCursor PC = clang_getTypeDeclaration(PT);
+static long long validateFieldParentType(CXCursor PC, CXType PT){
if (clang_isInvalid(PC.kind))
return CXTypeLayoutError_Invalid;
const RecordDecl *RD =
dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ // validate parent declaration
if (!RD || RD->isInvalidDecl())
return CXTypeLayoutError_Invalid;
RD = RD->getDefinition();
@@ -789,6 +788,7 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) {
return CXTypeLayoutError_Incomplete;
if (RD->isInvalidDecl())
return CXTypeLayoutError_Invalid;
+ // validate parent type
QualType RT = GetQualType(PT);
if (RT->isIncompleteType())
return CXTypeLayoutError_Incomplete;
@@ -798,12 +798,25 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) {
long long Error = visitRecordForValidation(RD);
if (Error < 0)
return Error;
+ return 0;
+}
+
+long long clang_Type_getOffsetOf(CXType PT, const char *S) {
+ // check that PT is not incomplete/dependent
+ CXCursor PC = clang_getTypeDeclaration(PT);
+ long long Error = validateFieldParentType(PC,PT);
+ if (Error < 0)
+ return Error;
if (!S)
return CXTypeLayoutError_InvalidFieldName;
// lookup field
ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();
IdentifierInfo *II = &Ctx.Idents.get(S);
DeclarationName FieldName(II);
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ // verified in validateFieldParentType
+ RD = RD->getDefinition();
RecordDecl::lookup_const_result Res = RD->lookup(FieldName);
// If a field of the parent record is incomplete, lookup will fail.
// and we would return InvalidFieldName instead of Incomplete.
@@ -819,6 +832,25 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) {
return CXTypeLayoutError_InvalidFieldName;
}
+long long clang_Cursor_getOffsetOfField(CXCursor C) {
+ if (clang_isDeclaration(C.kind)) {
+ // we need to validate the parent type
+ CXCursor PC = clang_getCursorSemanticParent(C);
+ CXType PT = clang_getCursorType(PC);
+ long long Error = validateFieldParentType(PC,PT);
+ if (Error < 0)
+ return Error;
+ // proceed with the offset calculation
+ const Decl *D = cxcursor::getCursorDecl(C);
+ ASTContext &Ctx = cxcursor::getCursorContext(C);
+ if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D))
+ return Ctx.getFieldOffset(FD);
+ if (const IndirectFieldDecl *IFD = dyn_cast_or_null<IndirectFieldDecl>(D))
+ return Ctx.getFieldOffset(IFD);
+ }
+ return -1;
+}
+
enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {
QualType QT = GetQualType(T);
if (QT.isNull())
@@ -908,4 +940,42 @@ CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned i) {
return MakeCXType(A.getAsType(), GetTU(CT));
}
+unsigned clang_Type_visitFields(CXType PT,
+ CXFieldVisitor visitor,
+ CXClientData client_data){
+ CXCursor PC = clang_getTypeDeclaration(PT);
+ if (clang_isInvalid(PC.kind))
+ return false;
+ const RecordDecl *RD =
+ dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
+ if (!RD || RD->isInvalidDecl())
+ return false;
+ RD = RD->getDefinition();
+ if (!RD || RD->isInvalidDecl())
+ return false;
+
+ for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+ I != E; ++I){
+ const FieldDecl *FD = dyn_cast_or_null<FieldDecl>((*I));
+ // Callback to the client.
+ switch (visitor(cxcursor::MakeCXCursor(FD, GetTU(PT)), client_data)){
+ case CXVisit_Break:
+ return true;
+ case CXVisit_Continue:
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+unsigned clang_Cursor_isAnonymous(CXCursor C){
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+ const Decl *D = cxcursor::getCursorDecl(C);
+ if (const RecordDecl *FD = dyn_cast_or_null<RecordDecl>(D))
+ return FD->isAnonymousStructOrUnion();
+ return 0;
+}
+
} // end: extern "C"
diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index fa2c0e70bf3..f78f9981a98 100644
--- a/clang/tools/libclang/libclang.exports
+++ b/clang/tools/libclang/libclang.exports
@@ -21,9 +21,11 @@ clang_Cursor_getNumArguments
clang_Cursor_getObjCDeclQualifiers
clang_Cursor_getObjCPropertyAttributes
clang_Cursor_getObjCSelectorIndex
+clang_Cursor_getOffsetOfField
clang_Cursor_getSpellingNameRange
clang_Cursor_getTranslationUnit
clang_Cursor_getReceiverType
+clang_Cursor_isAnonymous
clang_Cursor_isBitField
clang_Cursor_isDynamicCall
clang_Cursor_isNull
@@ -77,6 +79,7 @@ clang_Type_getOffsetOf
clang_Type_getNumTemplateArguments
clang_Type_getTemplateArgumentAsType
clang_Type_getCXXRefQualifier
+clang_Type_visitFields
clang_VerbatimBlockLineComment_getText
clang_VerbatimLineComment_getText
clang_HTMLTagComment_getAsString
OpenPOWER on IntegriCloud