bool MocNg::ShouldRegisterMetaType(clang::QualType T) { if (T->isVoidType() || (T->isReferenceType() && !T.getNonReferenceType().isConstQualified())) return false; if (registered_meta_type.count(T->getCanonicalTypeUnqualified().getTypePtr())) return true; T = T.getNonReferenceType(); if (T->isPointerType()) { // registering pointer to forward declared type fails. const clang::CXXRecordDecl* Pointee = T->getPointeeCXXRecordDecl(); if (Pointee && !Pointee->hasDefinition()) return false; return true; } const clang::ClassTemplateSpecializationDecl* TD = llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(T->getAsCXXRecordDecl()); if (TD) { if (!TD->hasDefinition()) return false; for (uint I = 0; I < TD->getTemplateArgs().size(); ++I) { const auto &Arg = TD->getTemplateArgs().get(I); if (Arg.getKind() == clang::TemplateArgument::Type) { if (!ShouldRegisterMetaType(Arg.getAsType())) return false; } } } return true; }
static void StreamValue(llvm::raw_ostream& o, const void* V, clang::QualType Ty, cling::Interpreter& Interp) { clang::ASTContext& C = Interp.getCI()->getASTContext(); if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) { switch (BT->getKind()) { case clang::BuiltinType::Bool: if (*(const bool*)V) o << "true"; else o << "false"; break; case clang::BuiltinType::Char_U: // intentional fall through case clang::BuiltinType::UChar: // intentional fall through case clang::BuiltinType::Char_S: // intentional fall through case clang::BuiltinType::SChar: StreamChar(o, *(const char*)V); break; case clang::BuiltinType::Short: o << *(const short*)V; break; case clang::BuiltinType::UShort: o << *(const unsigned short*)V; break; case clang::BuiltinType::Int: o << *(const int*)V; break; case clang::BuiltinType::UInt: o << *(const unsigned int*)V; break; case clang::BuiltinType::Long: o << *(const long*)V; break; case clang::BuiltinType::ULong: o << *(const unsigned long*)V; break; case clang::BuiltinType::LongLong: o << *(const long long*)V; break; case clang::BuiltinType::ULongLong: o << *(const unsigned long long*)V; break; case clang::BuiltinType::Float: o << *(const float*)V; break; case clang::BuiltinType::Double: o << *(const double*)V; break; case clang::BuiltinType::LongDouble: { std::stringstream ssLD; ssLD << *(const long double*)V; o << ssLD.str() << 'L'; break; } default: StreamObj(o, V, Ty); } } else if (Ty.getAsString().compare("std::string") == 0) { StreamObj(o, V, Ty); o << " "; // force a space o <<"c_str: "; StreamCharPtr(o, ((const char*) (*(const std::string*)V).c_str())); } else if (Ty->isEnumeralType()) { clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl(); uint64_t value = *(const uint64_t*)V; bool IsFirst = true; llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty); for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(), E = ED->enumerator_end(); I != E; ++I) { if (I->getInitVal() == ValAsAPSInt) { if (!IsFirst) { o << " ? "; } o << "(" << I->getQualifiedNameAsString() << ")"; IsFirst = false; } } o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10); } else if (Ty->isReferenceType()) StreamRef(o, (const void**)&V, Ty, Interp); else if (Ty->isPointerType()) { clang::QualType PointeeTy = Ty->getPointeeType(); if (PointeeTy->isCharType()) StreamCharPtr(o, (const char*)V); else if (PointeeTy->isFunctionProtoType()) StreamFunction(o, V, PointeeTy, Interp); else StreamPtr(o, V); } else if (Ty->isArrayType()) StreamArr(o, V, Ty, Interp); else if (Ty->isFunctionType()) StreamFunction(o, V, Ty, Interp); else StreamObj(o, V, Ty); }