aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-17 00:46:38 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-05-17 00:46:38 +0000
commit2636197098e02fd7c90f9496056b8ab886dcbff0 (patch)
treeb53191f9411fbe552f15d58329fee13ced60851b /lib/AST/ASTContext.cpp
parentbc6a191a1575fa3b7785fe5cbe01463d220553a7 (diff)
Reapply the commits that r131401 reverted and add a fix for PR9927.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131446 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp187
1 files changed, 164 insertions, 23 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 379c13a934..b0303797e4 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -31,6 +31,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "CXXABI.h"
+#include <map>
using namespace clang;
@@ -4152,7 +4153,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
bool ExpandStructures,
const FieldDecl *FD,
bool OutermostType,
- bool EncodingProperty) const {
+ bool EncodingProperty,
+ bool StructField) const {
if (T->getAs<BuiltinType>()) {
if (FD && FD->isBitField())
return EncodeBitField(this, S, T, FD);
@@ -4237,7 +4239,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
if (const ArrayType *AT =
// Ignore type qualifiers etc.
dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
- if (isa<IncompleteArrayType>(AT)) {
+ if (isa<IncompleteArrayType>(AT) && !StructField) {
// Incomplete arrays are encoded as a pointer to the array element.
S += '^';
@@ -4246,11 +4248,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
} else {
S += '[';
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
- S += llvm::utostr(CAT->getSize().getZExtValue());
- else {
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
+ if (getTypeSize(CAT->getElementType()) == 0)
+ S += '0';
+ else
+ S += llvm::utostr(CAT->getSize().getZExtValue());
+ } else {
//Variable length arrays are encoded as a regular array with 0 elements.
- assert(isa<VariableArrayType>(AT) && "Unknown array type!");
+ assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) &&
+ "Unknown array type!");
S += '0';
}
@@ -4288,24 +4294,30 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
}
if (ExpandStructures) {
S += '=';
- for (RecordDecl::field_iterator Field = RDecl->field_begin(),
- FieldEnd = RDecl->field_end();
- Field != FieldEnd; ++Field) {
- if (FD) {
- S += '"';
- S += Field->getNameAsString();
- S += '"';
- }
+ if (!RDecl->isUnion()) {
+ getObjCEncodingForStructureImpl(RDecl, S, FD);
+ } else {
+ for (RecordDecl::field_iterator Field = RDecl->field_begin(),
+ FieldEnd = RDecl->field_end();
+ Field != FieldEnd; ++Field) {
+ if (FD) {
+ S += '"';
+ S += Field->getNameAsString();
+ S += '"';
+ }
- // Special case bit-fields.
- if (Field->isBitField()) {
- getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
- (*Field));
- } else {
- QualType qt = Field->getType();
- getLegacyIntegralTypeEncoding(qt);
- getObjCEncodingForTypeImpl(qt, S, false, true,
- FD);
+ // Special case bit-fields.
+ if (Field->isBitField()) {
+ getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
+ (*Field));
+ } else {
+ QualType qt = Field->getType();
+ getLegacyIntegralTypeEncoding(qt);
+ getObjCEncodingForTypeImpl(qt, S, false, true,
+ FD, /*OutermostType*/false,
+ /*EncodingProperty*/false,
+ /*StructField*/true);
+ }
}
}
}
@@ -4426,6 +4438,135 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
assert(0 && "@encode for type not implemented!");
}
+void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
+ std::string &S,
+ const FieldDecl *FD,
+ bool includeVBases) const {
+ assert(RDecl && "Expected non-null RecordDecl");
+ assert(!RDecl->isUnion() && "Should not be called for unions");
+ if (!RDecl->getDefinition())
+ return;
+
+ CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl);
+ std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets;
+ const ASTRecordLayout &layout = getASTRecordLayout(RDecl);
+
+ if (CXXRec) {
+ for (CXXRecordDecl::base_class_iterator
+ BI = CXXRec->bases_begin(),
+ BE = CXXRec->bases_end(); BI != BE; ++BI) {
+ if (!BI->isVirtual()) {
+ CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
+ uint64_t offs = layout.getBaseClassOffsetInBits(base);
+ FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
+ std::make_pair(offs, base));
+ }
+ }
+ }
+
+ unsigned i = 0;
+ for (RecordDecl::field_iterator Field = RDecl->field_begin(),
+ FieldEnd = RDecl->field_end();
+ Field != FieldEnd; ++Field, ++i) {
+ uint64_t offs = layout.getFieldOffset(i);
+ FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
+ std::make_pair(offs, *Field));
+ }
+
+ if (CXXRec && includeVBases) {
+ for (CXXRecordDecl::base_class_iterator
+ BI = CXXRec->vbases_begin(),
+ BE = CXXRec->vbases_end(); BI != BE; ++BI) {
+ CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
+ uint64_t offs = layout.getVBaseClassOffsetInBits(base);
+ FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
+ std::make_pair(offs, base));
+ }
+ }
+
+ CharUnits size;
+ if (CXXRec) {
+ size = includeVBases ? layout.getSize() : layout.getNonVirtualSize();
+ } else {
+ size = layout.getSize();
+ }
+
+ uint64_t CurOffs = 0;
+ std::multimap<uint64_t, NamedDecl *>::iterator
+ CurLayObj = FieldOrBaseOffsets.begin();
+
+ if (CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) {
+ assert(CXXRec && CXXRec->isDynamicClass() &&
+ "Offset 0 was empty but no VTable ?");
+ if (FD) {
+ S += "\"_vptr$";
+ std::string recname = CXXRec->getNameAsString();
+ if (recname.empty()) recname = "?";
+ S += recname;
+ S += '"';
+ }
+ S += "^^?";
+ CurOffs += getTypeSize(VoidPtrTy);
+ }
+
+ if (!RDecl->hasFlexibleArrayMember()) {
+ // Mark the end of the structure.
+ uint64_t offs = toBits(size);
+ FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
+ std::make_pair(offs, (NamedDecl*)0));
+ }
+
+ for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) {
+ assert(CurOffs <= CurLayObj->first);
+
+ if (CurOffs < CurLayObj->first) {
+ uint64_t padding = CurLayObj->first - CurOffs;
+ // FIXME: There doesn't seem to be a way to indicate in the encoding that
+ // packing/alignment of members is different that normal, in which case
+ // the encoding will be out-of-sync with the real layout.
+ // If the runtime switches to just consider the size of types without
+ // taking into account alignment, we could make padding explicit in the
+ // encoding (e.g. using arrays of chars). The encoding strings would be
+ // longer then though.
+ CurOffs += padding;
+ }
+
+ NamedDecl *dcl = CurLayObj->second;
+ if (dcl == 0)
+ break; // reached end of structure.
+
+ if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) {
+ // We expand the bases without their virtual bases since those are going
+ // in the initial structure. Note that this differs from gcc which
+ // expands virtual bases each time one is encountered in the hierarchy,
+ // making the encoding type bigger than it really is.
+ getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
+ if (!base->isEmpty())
+ CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
+ } else {
+ FieldDecl *field = cast<FieldDecl>(dcl);
+ if (FD) {
+ S += '"';
+ S += field->getNameAsString();
+ S += '"';
+ }
+
+ if (field->isBitField()) {
+ EncodeBitField(this, S, field->getType(), field);
+ CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue();
+ } else {
+ QualType qt = field->getType();
+ getLegacyIntegralTypeEncoding(qt);
+ getObjCEncodingForTypeImpl(qt, S, false, true, FD,
+ /*OutermostType*/false,
+ /*EncodingProperty*/false,
+ /*StructField*/true);
+ CurOffs += getTypeSize(field->getType());
+ }
+ }
+ }
+}
+
void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
std::string& S) const {
if (QT & Decl::OBJC_TQ_In)