bool ATSCollectionVisitor::VisitMemberExpr(MemberExpr *ME) { ValueDecl *OrigDecl = ME->getMemberDecl(); FieldDecl *FD = dyn_cast<FieldDecl>(OrigDecl); if (!FD) { // in C++, getMemberDecl returns a CXXMethodDecl. if (TransformationManager::isCXXLangOpt()) return true; TransAssert(0 && "Bad FD!\n"); } const Type *T = FD->getType().getTypePtr(); if (!T->isScalarType()) return true; RecordDecl *RD = FD->getParent(); TransAssert(RD && "NULL RecordDecl!"); if (!RD->isStruct() && !RD->isUnion()) return true; ConsumerInstance->addOneExpr(ME); return true; }
/// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, llvm::DICompileUnit Unit) { RecordDecl *Decl = Ty->getDecl(); unsigned Tag; if (Decl->isStruct()) Tag = llvm::dwarf::DW_TAG_structure_type; else if (Decl->isUnion()) Tag = llvm::dwarf::DW_TAG_union_type; else { assert(Decl->isClass() && "Unknown RecordType!"); Tag = llvm::dwarf::DW_TAG_class_type; } SourceManager &SM = M->getContext().getSourceManager(); // Get overall information about the record type for the debug info. std::string Name = Decl->getNameAsString(); llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation()); unsigned Line = SM.getInstantiationLineNumber(Decl->getLocation()); // Records and classes and unions can all be recursive. To handle them, we // first generate a debug descriptor for the struct as a forward declaration. // Then (if it is a definition) we go through and get debug info for all of // its members. Finally, we create a descriptor for the complete type (which // may refer to the forward decl if the struct is recursive) and replace all // uses of the forward declaration with the final definition. llvm::DIType FwdDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0, llvm::DIType(), llvm::DIArray()); // If this is just a forward declaration, return it. if (!Decl->getDefinition(M->getContext())) return FwdDecl; // Otherwise, insert it into the TypeCache so that recursive uses will find // it. TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Convert all the elements. llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl); unsigned FieldNo = 0; for (RecordDecl::field_iterator I = Decl->field_begin(M->getContext()), E = Decl->field_end(M->getContext()); I != E; ++I, ++FieldNo) { FieldDecl *Field = *I; llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); std::string FieldName = Field->getNameAsString(); // Get the location for the field. SourceLocation FieldDefLoc = Field->getLocation(); llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc); unsigned FieldLine = SM.getInstantiationLineNumber(FieldDefLoc); QualType FType = Field->getType(); uint64_t FieldSize = 0; unsigned FieldAlign = 0; if (!FType->isIncompleteArrayType()) { // Bit size, align and offset of the type. FieldSize = M->getContext().getTypeSize(FType); Expr *BitWidth = Field->getBitWidth(); if (BitWidth) FieldSize = BitWidth->getIntegerConstantExprValue(M->getContext()).getZExtValue(); FieldAlign = M->getContext().getTypeAlign(FType); } uint64_t FieldOffset = RL.getFieldOffset(FieldNo); // Create a DW_TAG_member node to remember the offset of this field in the // struct. FIXME: This is an absolutely insane way to capture this // information. When we gut debug info, this should be fixed. FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, FieldName, FieldDefUnit, FieldLine, FieldSize, FieldAlign, FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); } llvm::DIArray Elements = DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size()); // Bit size, align and offset of the type. uint64_t Size = M->getContext().getTypeSize(Ty); uint64_t Align = M->getContext().getTypeAlign(Ty); llvm::DIType RealDecl = DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size, Align, 0, 0, llvm::DIType(), Elements); // Now that we have a real decl for the struct, replace anything using the // old decl with the new one. This will recursively update the debug info. FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV()); FwdDecl.getGV()->eraseFromParent(); return RealDecl; }