void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: GenObjCClass(D->getName()); break; case Decl::ObjCCategory: { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } // Specially handle class extensions, which are anonymous categories. // We want to mangle in the location to uniquely distinguish them. if (CD->IsClassExtension()) { Out << "objc(ext)" << ID->getName() << '@'; GenLoc(CD); } else GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCCategoryImpl: { ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCProtocol: GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); break; } }
bool trans::canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass) { if (!Ctx.getLangOpts().ObjCARCWeak) return false; QualType T = type; if (T.isNull()) return false; // iOS is always safe to use 'weak'. if (Ctx.getTargetInfo().getTriple().getOS() == llvm::Triple::IOS) AllowOnUnknownClass = true; while (const PointerType *ptr = T->getAs<PointerType>()) T = ptr->getPointeeType(); if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject")) return false; // id/NSObject is not safe for weak. if (!AllowOnUnknownClass && !Class->hasDefinition()) return false; // forward classes are not verifiable, therefore not safe. if (Class && Class->isArcWeakrefUnavailable()) return false; } return true; }
void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) { std::string I = OID->getName(); ObjCInterfaceDecl *SID = OID->getSuperClass(); if (SID) Out << "@implementation " << I << " : " << SID->getName(); else Out << "@implementation " << I; for (ObjCImplementationDecl::instmeth_iterator I = OID->instmeth_begin(), E = OID->instmeth_end(); I != E; ++I) { ObjCMethodDecl *OMD = *I; PrintObjCMethodDecl(OMD); if (OMD->getBody()) { Out << ' '; OMD->getBody()->printPretty(Out); Out << '\n'; } } for (ObjCImplementationDecl::classmeth_iterator I = OID->classmeth_begin(), E = OID->classmeth_end(); I != E; ++I) { ObjCMethodDecl *OMD = *I; PrintObjCMethodDecl(OMD); if (OMD->getBody()) { Out << ' '; OMD->getBody()->printPretty(Out); Out << '\n'; } } Out << "@end\n"; }
bool trans::canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass) { if (!Ctx.getLangOptions().ObjCRuntimeHasWeak) return false; QualType T = type; if (T.isNull()) return false; while (const PointerType *ptr = T->getAs<PointerType>()) T = ptr->getPointeeType(); if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); if (!AllowOnUnknownClass && (!Class || Class->getName() == "NSObject")) return false; // id/NSObject is not safe for weak. if (!AllowOnUnknownClass && Class->isForwardDecl()) return false; // forward classes are not verifiable, therefore not safe. if (Class->isArcWeakrefUnavailable()) return false; if (isClassInWeakBlacklist(Class)) return false; } return true; }
void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) { switch (D->getKind()) { default: assert(false && "Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: GenObjCClass(D->getName()); break; case Decl::ObjCCategory: { ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCCategoryImpl: { ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); ObjCInterfaceDecl *ID = CD->getClassInterface(); if (!ID) { // Handle invalid code where the @interface might not // have been specified. // FIXME: We should be able to generate this USR even if the // @interface isn't available. IgnoreResults = true; return; } GenObjCCategory(ID->getName(), CD->getName()); break; } case Decl::ObjCProtocol: GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); break; } }
void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) { std::string I = OID->getName(); ObjCInterfaceDecl *SID = OID->getSuperClass(); if (SID) Out << "@interface " << I << " : " << SID->getName(); else Out << "@interface " << I; // Protocols? const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols(); if (!Protocols.empty()) { for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getName(); } if (!Protocols.empty()) Out << ">"; Out << '\n'; if (OID->ivar_size() > 0) { Out << '{'; for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(), E = OID->ivar_end(); I != E; ++I) { Out << '\t' << (*I)->getType().getAsString() << ' ' << (*I)->getName() << ";\n"; } Out << "}\n"; } for (ObjCInterfaceDecl::classprop_iterator I = OID->classprop_begin(), E = OID->classprop_end(); I != E; ++I) PrintObjCPropertyDecl(*I); bool eol_needed = false; for (ObjCInterfaceDecl::classmeth_iterator I = OID->classmeth_begin(), E = OID->classmeth_end(); I != E; ++I) eol_needed = true, PrintObjCMethodDecl(*I); for (ObjCInterfaceDecl::instmeth_iterator I = OID->instmeth_begin(), E = OID->instmeth_end(); I != E; ++I) eol_needed = true, PrintObjCMethodDecl(*I); Out << (eol_needed ? "\n@end\n" : "@end\n"); // FIXME: implement the rest... }
StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) return StringRef(); // Check whether we've already cached the parent name. StringRef &CachedParentName = ParentNames[DC]; if (!CachedParentName.empty()) return CachedParentName; // If we already processed this DeclContext and assigned empty to it, the // data pointer will be non-null. if (CachedParentName.data() != 0) return StringRef(); // Find the interesting names. llvm::SmallVector<DeclContext *, 2> Contexts; while (DC && !DC->isFunctionOrMethod()) { if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { if (ND->getIdentifier()) Contexts.push_back(DC); } DC = DC->getParent(); } { llvm::SmallString<128> S; llvm::raw_svector_ostream OS(S); bool First = true; for (unsigned I = Contexts.size(); I != 0; --I) { if (First) First = false; else { OS << "::"; } DeclContext *CurDC = Contexts[I-1]; if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) CurDC = CatImpl->getCategoryDecl(); if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { ObjCInterfaceDecl *Interface = Cat->getClassInterface(); if (!Interface) { // Assign an empty StringRef but with non-null data to distinguish // between empty because we didn't process the DeclContext yet. CachedParentName = StringRef((const char *)~0U, 0); return StringRef(); } OS << Interface->getName() << '(' << Cat->getName() << ')'; } else { OS << cast<NamedDecl>(CurDC)->getName(); } } CachedParentName = AllocatorRef->CopyString(OS.str()); } return CachedParentName; }
void CodeCompletionBuilder::addParentContext(DeclContext *DC) { if (DC->isTranslationUnit()) { ParentKind = CXCursor_TranslationUnit; return; } if (DC->isFunctionOrMethod()) return; NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) return; ParentKind = getCursorKindForDecl(ND); // Check whether we've already cached the parent name. StringRef &CachedParentName = Allocator.getParentNames()[DC]; if (!CachedParentName.empty()) { ParentName = CachedParentName; return; } // Find the interesting names. llvm::SmallVector<DeclContext *, 2> Contexts; while (DC && !DC->isFunctionOrMethod()) { if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { if (ND->getIdentifier()) Contexts.push_back(DC); } DC = DC->getParent(); } { llvm::SmallString<128> S; llvm::raw_svector_ostream OS(S); bool First = true; for (unsigned I = Contexts.size(); I != 0; --I) { if (First) First = false; else { OS << "::"; } DeclContext *CurDC = Contexts[I-1]; if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) CurDC = CatImpl->getCategoryDecl(); if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { ObjCInterfaceDecl *Interface = Cat->getClassInterface(); if (!Interface) return; OS << Interface->getName() << '(' << Cat->getName() << ')'; } else { OS << cast<NamedDecl>(CurDC)->getName(); } } ParentName = Allocator.CopyString(OS.str()); CachedParentName = ParentName; } }