diff options
| author | Adrian Prantl <aprantl@apple.com> | 2013-02-26 20:01:46 +0000 |
|---|---|---|
| committer | Adrian Prantl <aprantl@apple.com> | 2013-02-26 20:01:46 +0000 |
| commit | 71510db7bcbdcd09f0cb10961e421568a1406791 (patch) | |
| tree | c1189ca62943d26f29661ec690e0b11bb64efd8a /clang/lib | |
| parent | 37c777ecc03707977ca67b31cd064b3c74f8862d (diff) | |
| download | bcm5719-llvm-71510db7bcbdcd09f0cb10961e421568a1406791.tar.gz bcm5719-llvm-71510db7bcbdcd09f0cb10961e421568a1406791.zip | |
Ensure that DIType is regenerated after we visited an implementation that adds ivars to an interface. Fixes rdar://13175234
llvm-svn: 176116
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 53 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 30 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 4 |
3 files changed, 65 insertions, 22 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index d539e0098ff..d1bf9a9e45a 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1093,38 +1093,51 @@ namespace { /// all_declared_ivar_begin - return first ivar declared in this class, /// its extensions and its implementation. Lazily build the list on first /// access. +/// +/// Caveat: The list returned by this method reflects the current +/// state of the parser. The cache will be updated for every ivar +/// added by an extension or the implementation when they are +/// encountered. +/// See also ObjCIvarDecl::Create(). ObjCIvarDecl *ObjCInterfaceDecl::all_declared_ivar_begin() { // FIXME: Should make sure no callers ever do this. if (!hasDefinition()) return 0; - if (data().IvarList) - return data().IvarList; - ObjCIvarDecl *curIvar = 0; - if (!ivar_empty()) { - ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); - data().IvarList = *I; ++I; - for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) - curIvar->setNextIvar(*I); - } + if (!data().IvarList) { + if (!ivar_empty()) { + ObjCInterfaceDecl::ivar_iterator I = ivar_begin(), E = ivar_end(); + data().IvarList = *I; ++I; + for (curIvar = data().IvarList; I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); + } - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = known_extensions_begin(), - ExtEnd = known_extensions_end(); - Ext != ExtEnd; ++Ext) { - if (!Ext->ivar_empty()) { - ObjCCategoryDecl::ivar_iterator I = Ext->ivar_begin(),E = Ext->ivar_end(); - if (!data().IvarList) { - data().IvarList = *I; ++I; - curIvar = data().IvarList; + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = known_extensions_begin(), + ExtEnd = known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (!Ext->ivar_empty()) { + ObjCCategoryDecl::ivar_iterator + I = Ext->ivar_begin(), + E = Ext->ivar_end(); + if (!data().IvarList) { + data().IvarList = *I; ++I; + curIvar = data().IvarList; + } + for ( ;I != E; curIvar = *I, ++I) + curIvar->setNextIvar(*I); } - for ( ;I != E; curIvar = *I, ++I) - curIvar->setNextIvar(*I); } + data().IvarListMissingImplementation = true; } + + // cached and complete! + if (!data().IvarListMissingImplementation) + return data().IvarList; if (ObjCImplementationDecl *ImplDecl = getImplementation()) { + data().IvarListMissingImplementation = false; if (!ImplDecl->ivar_empty()) { SmallVector<SynthesizeIvarChunk, 16> layout; for (ObjCImplementationDecl::ivar_iterator I = ImplDecl->ivar_begin(), diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 970ba50b71a..2d0d2b83778 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1343,7 +1343,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { LexicalBlockStack.push_back(FwdDeclNode); RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); - // Add this to the completed types cache since we're completing it. + // Add this to the completed-type cache while we're completing it recursively. CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; // Convert all the elements. @@ -1436,7 +1436,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // Otherwise, insert it into the CompletedTypeCache so that recursive uses // will find it and we're emitting the complete type. - CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl; + QualType QualTy = QualType(Ty, 0); + CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl; // Push the struct on region stack. llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl); @@ -1561,6 +1562,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); FwdDeclNode->replaceOperandWith(10, Elements); + + // If the implementation is not yet set, we do not want to mark it + // as complete. An implementation may declare additional + // private ivars that we would miss otherwise. + if (ID->getImplementation() == 0) + CompletedTypeCache.erase(QualTy.getAsOpaquePtr()); LexicalBlockStack.pop_back(); return llvm::DIType(FwdDeclNode); @@ -1824,6 +1831,10 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(), static_cast<llvm::Value*>(TC))); + // Do not cache the type if it may be incomplete. + if (maybeIncompleteInterface(Ty)) + return Res; + // And update the type cache. TypeCache[Ty.getAsOpaquePtr()] = Res; @@ -1833,6 +1844,21 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { return Res; } +/// clang::ParseAST handles each TopLevelDecl immediately after it was parsed. +/// A subsequent implementation may add more ivars to an interface, which is +/// why we cannot cache it yet. +bool CGDebugInfo::maybeIncompleteInterface(QualType Ty) { + switch (Ty->getTypeClass()) { + case Type::ObjCObjectPointer: + return maybeIncompleteInterface(cast<ObjCObjectPointerType>(Ty)->getPointeeType()); + case Type::ObjCInterface: + if (ObjCInterfaceDecl *Decl = cast<ObjCInterfaceType>(Ty)->getDecl()) + return (Decl->getImplementation() == 0); + default: + return false; + } +} + /// CreateTypeNode - Create a new debug type node. llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { // Handle qualifiers, which recursively handles what they refer to. diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index fbbee0b3d2b..81b5c713279 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -299,6 +299,10 @@ private: /// CreateTypeNode - Create type metadata for a source language type. llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F); + /// maybeIncompleteInterface - Determine if Ty may contain an + /// interface without an implementation + bool maybeIncompleteInterface(QualType Ty); + /// CreateLimitedTypeNode - Create type metadata for a source language /// type, but only partial types for records. llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F); |

