CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { CXTypeKind TK = CXType_Invalid; if (TU && !T.isNull()) { // Handle attributed types as the original type if (auto *ATT = T->getAs<AttributedType>()) { return MakeCXType(ATT->getModifiedType(), TU); } ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext(); if (Ctx.getLangOpts().ObjC1) { QualType UnqualT = T.getUnqualifiedType(); if (Ctx.isObjCIdType(UnqualT)) TK = CXType_ObjCId; else if (Ctx.isObjCClassType(UnqualT)) TK = CXType_ObjCClass; else if (Ctx.isObjCSelType(UnqualT)) TK = CXType_ObjCSel; } /* Handle decayed types as the original type */ if (const DecayedType *DT = T->getAs<DecayedType>()) { return MakeCXType(DT->getOriginalType(), TU); } } if (TK == CXType_Invalid) TK = GetTypeKind(T); CXType CT = { TK, { TK == CXType_Invalid ? nullptr : T.getAsOpaquePtr(), TU } }; return CT; }
/// WriteNodeReference - Write out a reference to the given node, /// using a unique identifier for each direct base and for the /// (only) virtual base. raw_ostream& InheritanceHierarchyWriter::WriteNodeReference(QualType Type, bool FromVirtual) { QualType CanonType = Context.getCanonicalType(Type); Out << "Class_" << CanonType.getAsOpaquePtr(); if (!FromVirtual) Out << "_" << DirectBaseCount[CanonType]; return Out; }
Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // C99 6.7.6: Type names have no identifier. This is already validated by // the parser. assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); QualType T = GetTypeForDeclarator(D, S); if (T.isNull()) return true; // Check that there are no default arguments (C++ only). if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); return T.getAsOpaquePtr(); }
TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type) { Integer.Kind = Integral; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); // If the value is large, we have to get additional memory from the ASTContext unsigned NumWords = Value.getNumWords(); if (NumWords > 1) { void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); Integer.pVal = static_cast<uint64_t *>(Mem); } else { Integer.VAL = Value.getZExtValue(); } Integer.Type = Type.getAsOpaquePtr(); }
DeclarationName DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, QualType Ty) { assert(Kind >= DeclarationName::CXXConstructorName && Kind <= DeclarationName::CXXConversionFunctionName && "Kind must be a C++ special name kind"); llvm::FoldingSet<CXXSpecialName> *SpecialNames = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); DeclarationNameExtra::ExtraKind EKind; switch (Kind) { case DeclarationName::CXXConstructorName: EKind = DeclarationNameExtra::CXXConstructor; assert(Ty.getCVRQualifiers() == 0 &&"Constructor type must be unqualified"); break; case DeclarationName::CXXDestructorName: EKind = DeclarationNameExtra::CXXDestructor; assert(Ty.getCVRQualifiers() == 0 && "Destructor type must be unqualified"); break; case DeclarationName::CXXConversionFunctionName: EKind = DeclarationNameExtra::CXXConversionFunction; break; default: return DeclarationName(); } // Unique selector, to guarantee there is one per name. llvm::FoldingSetNodeID ID; ID.AddInteger(EKind); ID.AddPointer(Ty.getAsOpaquePtr()); void *InsertPos = 0; if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos)) return DeclarationName(Name); CXXSpecialName *SpecialName = new CXXSpecialName; SpecialName->ExtraKindOrNumArgs = EKind; SpecialName->Type = Ty; SpecialName->FETokenInfo = 0; SpecialNames->InsertNode(SpecialName, InsertPos); return DeclarationName(SpecialName); }
CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { CXTypeKind TK = CXType_Invalid; if (TU && !T.isNull()) { ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext(); if (Ctx.getLangOpts().ObjC1) { QualType UnqualT = T.getUnqualifiedType(); if (Ctx.isObjCIdType(UnqualT)) TK = CXType_ObjCId; else if (Ctx.isObjCClassType(UnqualT)) TK = CXType_ObjCClass; else if (Ctx.isObjCSelType(UnqualT)) TK = CXType_ObjCSel; } } if (TK == CXType_Invalid) TK = GetTypeKind(T); CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; return CT; }
void StmtProfiler::VisitType(QualType T) { if (Canonical) T = Context.getCanonicalType(T); ID.AddPointer(T.getAsOpaquePtr()); }
Expr* ValueExtractionSynthesizer::SynthesizeSVRInit(Expr* E) { if (!m_gClingVD) FindAndCacheRuntimeDecls(); // Build a reference to gCling ExprResult gClingDRE = m_Sema->BuildDeclRefExpr(m_gClingVD, m_Context->VoidPtrTy, VK_RValue, SourceLocation()); // We have the wrapper as Sema's CurContext FunctionDecl* FD = cast<FunctionDecl>(m_Sema->CurContext); ExprWithCleanups* Cleanups = 0; // In case of ExprWithCleanups we need to extend its 'scope' to the call. if (E && isa<ExprWithCleanups>(E)) { Cleanups = cast<ExprWithCleanups>(E); E = Cleanups->getSubExpr(); } // Build a reference to Value* in the wrapper, should be // the only argument of the wrapper. SourceLocation locStart = (E) ? E->getLocStart() : FD->getLocStart(); SourceLocation locEnd = (E) ? E->getLocEnd() : FD->getLocEnd(); ExprResult wrapperSVRDRE = m_Sema->BuildDeclRefExpr(FD->getParamDecl(0), m_Context->VoidPtrTy, VK_RValue, locStart); QualType ETy = (E) ? E->getType() : m_Context->VoidTy; QualType desugaredTy = ETy.getDesugaredType(*m_Context); // The expr result is transported as reference, pointer, array, float etc // based on the desugared type. We should still expose the typedef'ed // (sugared) type to the cling::Value. if (desugaredTy->isRecordType() && E->getValueKind() == VK_LValue) { // returning a lvalue (not a temporary): the value should contain // a reference to the lvalue instead of copying it. desugaredTy = m_Context->getLValueReferenceType(desugaredTy); ETy = m_Context->getLValueReferenceType(ETy); } Expr* ETyVP = utils::Synthesize::CStyleCastPtrExpr(m_Sema, m_Context->VoidPtrTy, (uint64_t)ETy.getAsOpaquePtr()); Expr* ETransaction = utils::Synthesize::CStyleCastPtrExpr(m_Sema, m_Context->VoidPtrTy, (uint64_t)getTransaction()); llvm::SmallVector<Expr*, 6> CallArgs; CallArgs.push_back(gClingDRE.take()); CallArgs.push_back(wrapperSVRDRE.take()); CallArgs.push_back(ETyVP); CallArgs.push_back(ETransaction); ExprResult Call; SourceLocation noLoc; if (desugaredTy->isVoidType()) { // In cases where the cling::Value gets reused we need to reset the // previous settings to void. // We need to synthesize setValueNoAlloc(...), E, because we still need // to run E. // FIXME: Suboptimal: this discards the already created AST nodes. QualType vpQT = m_Context->VoidPtrTy; QualType vQT = m_Context->VoidTy; Expr* vpQTVP = utils::Synthesize::CStyleCastPtrExpr(m_Sema, vpQT, (uint64_t)vQT.getAsOpaquePtr()); CallArgs[2] = vpQTVP; Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc, locStart, CallArgs, locEnd); if (E) Call = m_Sema->CreateBuiltinBinOp(locStart, BO_Comma, Call.take(), E); } else if (desugaredTy->isRecordType() || desugaredTy->isConstantArrayType()){ // 2) object types : // check existance of copy constructor before call if (!availableCopyConstructor(desugaredTy, m_Sema)) return E; // call new (setValueWithAlloc(gCling, &SVR, ETy)) (E) Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedWithAlloc, locStart, CallArgs, locEnd); Expr* placement = Call.take(); if (const ConstantArrayType* constArray = dyn_cast<ConstantArrayType>(desugaredTy.getTypePtr())) { CallArgs.clear(); CallArgs.push_back(E); CallArgs.push_back(placement); uint64_t arrSize = m_Context->getConstantArrayElementCount(constArray); Expr* arrSizeExpr = utils::Synthesize::IntegerLiteralExpr(*m_Context, arrSize); CallArgs.push_back(arrSizeExpr); // 2.1) arrays: // call copyArray(T* src, void* placement, int size) Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedCopyArray, locStart, CallArgs, locEnd); } else { TypeSourceInfo* ETSI = m_Context->getTrivialTypeSourceInfo(ETy, noLoc); Call = m_Sema->BuildCXXNew(E->getSourceRange(), /*useGlobal ::*/true, /*placementLParen*/ noLoc, MultiExprArg(placement), /*placementRParen*/ noLoc, /*TypeIdParens*/ SourceRange(), /*allocType*/ ETSI->getType(), /*allocTypeInfo*/ETSI, /*arraySize*/0, /*directInitRange*/E->getSourceRange(), /*initializer*/E, /*mayContainAuto*/false ); } } else if (desugaredTy->isIntegralOrEnumerationType() || desugaredTy->isReferenceType() || desugaredTy->isPointerType() || desugaredTy->isFloatingType()) { if (desugaredTy->isIntegralOrEnumerationType()) { // 1) enum, integral, float, double, referece, pointer types : // call to cling::internal::setValueNoAlloc(...); // If the type is enum or integral we need to force-cast it into // uint64 in order to pick up the correct overload. if (desugaredTy->isIntegralOrEnumerationType()) { QualType UInt64Ty = m_Context->UnsignedLongLongTy; TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(UInt64Ty, noLoc); Expr* castedE = m_Sema->BuildCStyleCastExpr(noLoc, TSI, noLoc, E).take(); CallArgs.push_back(castedE); } } else if (desugaredTy->isReferenceType()) { // we need to get the address of the references Expr* AddrOfE = m_Sema->BuildUnaryOp(/*Scope*/0, noLoc, UO_AddrOf, E).take(); CallArgs.push_back(AddrOfE); } else if (desugaredTy->isPointerType()) { // function pointers need explicit void* cast. QualType VoidPtrTy = m_Context->VoidPtrTy; TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(VoidPtrTy, noLoc); Expr* castedE = m_Sema->BuildCStyleCastExpr(noLoc, TSI, noLoc, E).take(); CallArgs.push_back(castedE); } else if (desugaredTy->isFloatingType()) { // floats and double will fall naturally in the correct // case, because of the overload resolution. CallArgs.push_back(E); } Call = m_Sema->ActOnCallExpr(/*Scope*/0, m_UnresolvedNoAlloc, locStart, CallArgs, locEnd); } else assert(0 && "Unhandled code path?"); assert(!Call.isInvalid() && "Invalid Call"); // Extend the scope of the temporary cleaner if applicable. if (Cleanups) { Cleanups->setSubExpr(Call.take()); Cleanups->setValueKind(Call.take()->getValueKind()); Cleanups->setType(Call.take()->getType()); return Cleanups; } return Call.take(); }
CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::directAnnotationReason(QualType T) { if (const TagDecl *D = T->getAsTagDecl()) { if (hasCustomAnnotation(D, Spelling)) { AnnotationReason Reason = {T, RK_Direct, nullptr, ""}; return Reason; } std::string ImplAnnotReason = getImplicitReason(D); if (!ImplAnnotReason.empty()) { AnnotationReason Reason = {T, RK_Implicit, nullptr, ImplAnnotReason}; return Reason; } } // Check if we have a cached answer void *Key = T.getAsOpaquePtr(); ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr()); if (Cached != Cache.end()) { return Cached->second; } // Check if we have a type which we can recurse into if (const clang::ArrayType *Array = T->getAsArrayTypeUnsafe()) { if (hasEffectiveAnnotation(Array->getElementType())) { AnnotationReason Reason = {Array->getElementType(), RK_ArrayElement, nullptr, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into Base classes if (const CXXRecordDecl *Declaration = T->getAsCXXRecordDecl()) { if (Declaration->hasDefinition()) { Declaration = Declaration->getDefinition(); for (const CXXBaseSpecifier &Base : Declaration->bases()) { if (hasEffectiveAnnotation(Base.getType())) { AnnotationReason Reason = {Base.getType(), RK_BaseClass, nullptr, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into members for (const FieldDecl *Field : Declaration->fields()) { if (hasEffectiveAnnotation(Field->getType())) { AnnotationReason Reason = {Field->getType(), RK_Field, Field, ""}; Cache[Key] = Reason; return Reason; } } // Recurse into template arguments if the annotation // MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS is present if (hasCustomAnnotation( Declaration, "moz_inherit_type_annotations_from_template_args")) { const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Declaration); if (Spec) { const TemplateArgumentList &Args = Spec->getTemplateArgs(); AnnotationReason Reason = tmplArgAnnotationReason(Args.asArray()); if (Reason.Kind != RK_None) { Cache[Key] = Reason; return Reason; } } } } } AnnotationReason Reason = {QualType(), RK_None, nullptr, ""}; Cache[Key] = Reason; return Reason; }
CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { CXTypeKind TK = GetTypeKind(T); CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; return CT; }
void Profile(llvm::FoldingSetNodeID &ID) { ID.AddInteger(ExtraKindOrNumArgs); ID.AddPointer(Type.getAsOpaquePtr()); }
/// getOrCreateType - Get the type from the cache or create a new /// one if necessary. llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DICompileUnit Unit) { if (Ty.isNull()) return llvm::DIType(); // Check to see if the compile unit already has created this type. llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()]; if (!Slot.isNull()) return Slot; // Handle CVR qualifiers, which recursively handles what they refer to. if (Ty.getCVRQualifiers()) return Slot = CreateCVRType(Ty, Unit); // Work out details of type. switch (Ty->getTypeClass()) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" assert(false && "Dependent types cannot show up in debug information"); case Type::Complex: case Type::LValueReference: case Type::RValueReference: case Type::Vector: case Type::ExtVector: case Type::ExtQual: case Type::ObjCQualifiedInterface: case Type::ObjCQualifiedId: case Type::FixedWidthInt: case Type::BlockPointer: case Type::MemberPointer: case Type::TemplateSpecialization: case Type::QualifiedName: case Type::ObjCQualifiedClass: // Unsupported types return llvm::DIType(); case Type::ObjCInterface: Slot = CreateType(cast<ObjCInterfaceType>(Ty), Unit); break; case Type::Builtin: Slot = CreateType(cast<BuiltinType>(Ty), Unit); break; case Type::Pointer: Slot = CreateType(cast<PointerType>(Ty), Unit); break; case Type::Typedef: Slot = CreateType(cast<TypedefType>(Ty), Unit); break; case Type::Record: case Type::Enum: Slot = CreateType(cast<TagType>(Ty), Unit); break; case Type::FunctionProto: case Type::FunctionNoProto: return Slot = CreateType(cast<FunctionType>(Ty), Unit); case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: return Slot = CreateType(cast<ArrayType>(Ty), Unit); case Type::TypeOfExpr: return Slot = getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr() ->getType(), Unit); case Type::TypeOf: return Slot = getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(), Unit); } return Slot; }