modern objective-c translator. named aggregate types
defined inside the objc class belong to class's
decl. scope. This is to conform to objective-c
rules. // rdar://11351299
llvm-svn: 155855
diff --git a/clang/lib/Rewrite/RewriteModernObjC.cpp b/clang/lib/Rewrite/RewriteModernObjC.cpp
index 5cd6836..6d79263 100644
--- a/clang/lib/Rewrite/RewriteModernObjC.cpp
+++ b/clang/lib/Rewrite/RewriteModernObjC.cpp
@@ -109,7 +109,7 @@
llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
- llvm::SmallPtrSet<TagDecl*, 8> TagsDefinedInIvarDecls;
+ llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
/// DefinedNonLazyClasses - List of defined "non-lazy" classes.
SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
@@ -346,6 +346,10 @@
std::string &Result);
void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
+ bool IsTagDefinedInsideClass(ObjCInterfaceDecl *IDecl, TagDecl *Tag,
+ bool &IsNamedDefinition);
+ void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
+ std::string &Result);
bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
@@ -3494,18 +3498,31 @@
return false;
}
-static bool IsTagDefinedInsideClass(ASTContext *Context,
- ObjCInterfaceDecl *IDecl, TagDecl *Tag) {
+/// IsTagDefinedInsideClass - This routine checks that a named tagged type
+/// is defined inside an objective-c class. If so, it returns true.
+bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCInterfaceDecl *IDecl,
+ TagDecl *Tag,
+ bool &IsNamedDefinition) {
if (!IDecl)
return false;
SourceLocation TagLocation;
if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {
RD = RD->getDefinition();
- if (!RD)
+ if (!RD || !RD->getDeclName().getAsIdentifierInfo())
return false;
+ IsNamedDefinition = true;
TagLocation = RD->getLocation();
return Context->getSourceManager().isBeforeInTranslationUnit(
- IDecl->getLocation(), TagLocation);
+ IDecl->getLocation(), TagLocation);
+ }
+ if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {
+ if (!ED || !ED->getDeclName().getAsIdentifierInfo())
+ return false;
+ IsNamedDefinition = true;
+ TagLocation = ED->getLocation();
+ return Context->getSourceManager().isBeforeInTranslationUnit(
+ IDecl->getLocation(), TagLocation);
+
}
return false;
}
@@ -3529,12 +3546,11 @@
assert(false && "class not allowed as an ivar type");
Result += RD->getName();
- if (TagsDefinedInIvarDecls.count(RD)) {
- // This struct is already defined. Do not write its definition again.
+ if (GlobalDefinedTags.count(RD)) {
+ // struct/union is defined globally, use it.
Result += " ";
return true;
}
- TagsDefinedInIvarDecls.insert(RD);
Result += " {\n";
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i) {
@@ -3550,12 +3566,11 @@
if (ED->isCompleteDefinition()) {
Result += "\n\tenum ";
Result += ED->getName();
- if (TagsDefinedInIvarDecls.count(ED)) {
- // This enum is already defined. Do not write its definition again.
+ if (GlobalDefinedTags.count(ED)) {
+ // Enum is globall defined, use it.
Result += " ";
return true;
}
- TagsDefinedInIvarDecls.insert(ED);
Result += " {\n";
for (EnumDecl::enumerator_iterator EC = ED->enumerator_begin(),
@@ -3606,6 +3621,39 @@
Result += ";\n";
}
+/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined
+/// named aggregate types into the input buffer.
+void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
+ std::string &Result) {
+ QualType Type = fieldDecl->getType();
+ if (Type->isArrayType())
+ Type = Context->getBaseElementType(Type);
+ ObjCInterfaceDecl *IDecl =
+ dyn_cast<ObjCInterfaceDecl>(fieldDecl->getDeclContext());
+
+ TagDecl *TD = 0;
+ if (Type->isRecordType()) {
+ TD = Type->getAs<RecordType>()->getDecl();
+ }
+ else if (Type->isEnumeralType()) {
+ TD = Type->getAs<EnumType>()->getDecl();
+ }
+
+ if (TD) {
+ if (GlobalDefinedTags.count(TD))
+ return;
+
+ bool IsNamedDefinition = false;
+ if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
+ RewriteObjCFieldDeclType(Type, Result);
+ Result += ";";
+ }
+ if (IsNamedDefinition)
+ GlobalDefinedTags.insert(TD);
+ }
+
+}
+
/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
/// an objective-c class with ivars.
void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
@@ -3634,6 +3682,12 @@
return;
}
+ // Insert named struct/union definitions inside class to
+ // outer scope. This follows semantics of locally defined
+ // struct/unions in objective-c classes.
+ for (unsigned i = 0, e = IVars.size(); i < e; i++)
+ RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
+
Result += "\nstruct ";
Result += CDecl->getNameAsString();
Result += "_IMPL {\n";
@@ -3643,7 +3697,7 @@
Result += "_IMPL "; Result += RCDecl->getNameAsString();
Result += "_IVARS;\n";
}
- TagsDefinedInIvarDecls.clear();
+
for (unsigned i = 0, e = IVars.size(); i < e; i++)
RewriteObjCFieldDecl(IVars[i], Result);
@@ -7264,7 +7318,8 @@
if (IvarT->isRecordType()) {
RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl();
- if (IsTagDefinedInsideClass(Context, iFaceDecl->getDecl(), RD)) {
+ RD = RD->getDefinition();
+ if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
// decltype(((Foo_IMPL*)0)->bar) *
std::string RecName = iFaceDecl->getDecl()->getName();
RecName += "_IMPL";