RSExportForEach *RSExportForEach::Create(RSContext *Context, const clang::FunctionDecl *FD) { slangAssert(Context && FD); llvm::StringRef Name = FD->getName(); RSExportForEach *FE; slangAssert(!Name.empty() && "Function must have a name"); FE = new RSExportForEach(Context, Name, FD); if (!FE->validateAndConstructParams(Context, FD)) { return NULL; } clang::ASTContext &Ctx = Context->getASTContext(); std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_foreach_param:"); Id.append(FE->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX); // Extract the usrData parameter (if we have one) if (FE->mUsrData) { const clang::ParmVarDecl *PVD = FE->mUsrData; clang::QualType QT = PVD->getType().getCanonicalType(); slangAssert(QT->isPointerType() && QT->getPointeeType().isConstQualified()); const clang::ASTContext &C = Context->getASTContext(); if (QT->getPointeeType().getCanonicalType().getUnqualifiedType() == C.VoidTy) { // In the case of using const void*, we can't reflect an appopriate // Java type, so we fall back to just reflecting the ain/aout parameters FE->mUsrData = NULL; } else { clang::RecordDecl *RD = clang::RecordDecl::Create(Ctx, clang::TTK_Struct, Ctx.getTranslationUnitDecl(), clang::SourceLocation(), clang::SourceLocation(), &Ctx.Idents.get(Id)); llvm::StringRef ParamName = PVD->getName(); clang::FieldDecl *FD = clang::FieldDecl::Create(Ctx, RD, clang::SourceLocation(), clang::SourceLocation(), PVD->getIdentifier(), QT->getPointeeType(), NULL, /* BitWidth = */ NULL, /* Mutable = */ false, /* HasInit = */ false); RD->addDecl(FD); RD->completeDefinition(); // Create an export type iff we have a valid usrData type clang::QualType T = Ctx.getTagDeclType(RD); slangAssert(!T.isNull()); RSExportType *ET = RSExportType::Create(Context, T.getTypePtr()); if (ET == NULL) { fprintf(stderr, "Failed to export the function %s. There's at least " "one parameter whose type is not supported by the " "reflection\n", FE->getName().c_str()); return NULL; } slangAssert((ET->getClass() == RSExportType::ExportClassRecord) && "Parameter packet must be a record"); FE->mParamPacketType = static_cast<RSExportRecordType *>(ET); } } if (FE->mIn) { const clang::Type *T = FE->mIn->getType().getCanonicalType().getTypePtr(); FE->mInType = RSExportType::Create(Context, T); } if (FE->mOut) { const clang::Type *T = FE->mOut->getType().getCanonicalType().getTypePtr(); FE->mOutType = RSExportType::Create(Context, T); } return FE; }