diff options
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 28 | ||||
-rw-r--r-- | test/SemaObjC/duplicate-ivar-in-class-extension.m | 32 |
4 files changed, 64 insertions, 15 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4ea379328c..2190e3b5bf 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1440,6 +1440,8 @@ public: void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl, ObjCContainerDecl* IDecl); + void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID); + /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns /// true, or false, accordingly. bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0be3841ad5..27eb2510ec 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5659,21 +5659,8 @@ void Sema::ActOnFields(Scope* S, } // Must enforce the rule that ivars in the base classes may not be // duplicates. - if (ID->getSuperClass()) { - for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), - IVE = ID->ivar_end(); IVI != IVE; ++IVI) { - ObjCIvarDecl* Ivar = (*IVI); - - if (IdentifierInfo *II = Ivar->getIdentifier()) { - ObjCIvarDecl* prevIvar = - ID->getSuperClass()->lookupInstanceVariable(II); - if (prevIvar) { - Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; - Diag(prevIvar->getLocation(), diag::note_previous_declaration); - } - } - } - } + if (ID->getSuperClass()) + DiagnoseDuplicateIvars(ID, ID->getSuperClass()); } else if (ObjCImplementationDecl *IMPDecl = dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 925c0db4e4..939ccab35d 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1781,6 +1781,29 @@ void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, } } +/// DiagnoseDuplicateIvars - +/// Check for duplicate ivars in the entire class at the start of +/// @implementation. This becomes necesssary because class extension can +/// add ivars to a class in random order which will not be known until +/// class's @implementation is seen. +void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, + ObjCInterfaceDecl *SID) { + for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), + IVE = ID->ivar_end(); IVI != IVE; ++IVI) { + ObjCIvarDecl* Ivar = (*IVI); + if (Ivar->isInvalidDecl()) + continue; + if (IdentifierInfo *II = Ivar->getIdentifier()) { + ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II); + if (prevIvar) { + Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; + Diag(prevIvar->getLocation(), diag::note_previous_declaration); + Ivar->setInvalidDecl(); + } + } + } +} + // Note: For class/category implemenations, allMethods/allProperties is // always null. void Sema::ActOnAtEnd(SourceRange AtEnd, @@ -1892,6 +1915,11 @@ void Sema::ActOnAtEnd(SourceRange AtEnd, if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { ImplMethodsVsClassMethods(IC, IDecl); AtomicPropertySetterGetterRules(IC, IDecl); + if (LangOpts.ObjCNonFragileABI2) + while (IDecl->getSuperClass()) { + DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); + IDecl = IDecl->getSuperClass(); + } } } else if (ObjCCategoryImplDecl* CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { diff --git a/test/SemaObjC/duplicate-ivar-in-class-extension.m b/test/SemaObjC/duplicate-ivar-in-class-extension.m new file mode 100644 index 0000000000..b66736f330 --- /dev/null +++ b/test/SemaObjC/duplicate-ivar-in-class-extension.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s + +@interface Root @end + +@interface SuperClass : Root +{ + int iSuper; // expected-note {{previous declaration is here}} +} +@end + +@interface SubClass : SuperClass { + int ivar; // expected-error {{duplicate member 'ivar'}} + int another_ivar; // expected-error {{duplicate member 'another_ivar'}} + int iSuper; // expected-error {{duplicate member 'iSuper'}} +} +@end + +@interface SuperClass () { + int ivar; // expected-note {{previous declaration is here}} +} +@end + +@interface Root () { + int another_ivar; // expected-note {{previous declaration is here}} +} +@end + +@implementation SubClass +-(int) method { + return self->ivar; // would be ambiguous if the duplicate ivar were allowed +} +@end |