void ObjCMethodDecl::createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *OID) { QualType selfTy; if (isInstanceMethod()) { // There may be no interface context due to error in declaration // of the interface (which has been reported). Recover gracefully. if (OID) { selfTy = Context.getObjCInterfaceType(OID); selfTy = Context.getObjCObjectPointerType(selfTy); } else { selfTy = Context.getObjCIdType(); } } else // we have a factory method. selfTy = Context.getObjCClassType(); bool selfIsPseudoStrong = false; bool selfIsConsumed = false; if (Context.getLangOpts().ObjCAutoRefCount) { if (isInstanceMethod()) { selfIsConsumed = hasAttr<NSConsumesSelfAttr>(); // 'self' is always __strong. It's actually pseudo-strong except // in init methods (or methods labeled ns_consumes_self), though. Qualifiers qs; qs.setObjCLifetime(Qualifiers::OCL_Strong); selfTy = Context.getQualifiedType(selfTy, qs); // In addition, 'self' is const unless this is an init method. if (getMethodFamily() != OMF_init && !selfIsConsumed) { selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } else { assert(isClassMethod()); // 'self' is always const in class methods. selfTy = selfTy.withConst(); selfIsPseudoStrong = true; } } ImplicitParamDecl *self = ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("self"), selfTy); setSelfDecl(self); if (selfIsConsumed) self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context)); if (selfIsPseudoStrong) self->setARCPseudoStrong(true); setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("_cmd"), Context.getObjCSelType())); }
QualType CXXMethodDecl::getThisType(ASTContext &C) const { // C++ 9.3.2p1: The type of this in a member function of a class X is X*. // If the member function is declared const, the type of this is const X*, // if the member function is declared volatile, the type of this is // volatile X*, and if the member function is declared const volatile, // the type of this is const volatile X*. assert(isInstance() && "No 'this' for static methods!"); QualType ClassTy = C.getTypeDeclType(getParent()); ClassTy = C.getQualifiedType(ClassTy, Qualifiers::fromCVRMask(getTypeQualifiers())); return C.getPointerType(ClassTy); }
/// \brief Return the fully qualified type, including fully-qualified /// versions of any template parameters. QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx) { // In case of myType* we need to strip the pointer first, fully // qualify and attach the pointer once again. if (isa<PointerType>(QT.getTypePtr())) { // Get the qualifiers. Qualifiers Quals = QT.getQualifiers(); QT = getFullyQualifiedType(QT->getPointeeType(), Ctx); QT = Ctx.getPointerType(QT); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); return QT; } // In case of myType& we need to strip the reference first, fully // qualify and attach the reference once again. if (isa<ReferenceType>(QT.getTypePtr())) { // Get the qualifiers. bool IsLValueRefTy = isa<LValueReferenceType>(QT.getTypePtr()); Qualifiers Quals = QT.getQualifiers(); QT = getFullyQualifiedType(QT->getPointeeType(), Ctx); // Add the r- or l-value reference type back to the fully // qualified one. if (IsLValueRefTy) QT = Ctx.getLValueReferenceType(QT); else QT = Ctx.getRValueReferenceType(QT); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); return QT; } // Remove the part of the type related to the type being a template // parameter (we won't report it as part of the 'type name' and it // is actually make the code below to be more complex (to handle // those) while (isa<SubstTemplateTypeParmType>(QT.getTypePtr())) { // Get the qualifiers. Qualifiers Quals = QT.getQualifiers(); QT = dyn_cast<SubstTemplateTypeParmType>(QT.getTypePtr())->desugar(); // Add back the qualifiers. QT = Ctx.getQualifiedType(QT, Quals); } NestedNameSpecifier *Prefix = nullptr; Qualifiers PrefixQualifiers; ElaboratedTypeKeyword Keyword = ETK_None; if (const auto *ETypeInput = dyn_cast<ElaboratedType>(QT.getTypePtr())) { QT = ETypeInput->getNamedType(); Keyword = ETypeInput->getKeyword(); } // Create a nested name specifier if needed (i.e. if the decl context // is not the global scope. Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(), true /*FullyQualified*/); // move the qualifiers on the outer type (avoid 'std::const string'!) if (Prefix) { PrefixQualifiers = QT.getLocalQualifiers(); QT = QualType(QT.getTypePtr(), 0); } // In case of template specializations iterate over the arguments and // fully qualify them as well. if (isa<const TemplateSpecializationType>(QT.getTypePtr()) || isa<const RecordType>(QT.getTypePtr())) { // We are asked to fully qualify and we have a Record Type (which // may pont to a template specialization) or Template // Specialization Type. We need to fully qualify their arguments. Qualifiers Quals = QT.getLocalQualifiers(); const Type *TypePtr = getFullyQualifiedTemplateType(Ctx, QT.getTypePtr()); QT = Ctx.getQualifiedType(TypePtr, Quals); } if (Prefix || Keyword != ETK_None) { QT = Ctx.getElaboratedType(Keyword, Prefix, QT); QT = Ctx.getQualifiedType(QT, PrefixQualifiers); } return QT; }