From: Douglas Gregor Date: Mon, 21 Jan 2013 19:42:21 +0000 (+0000) Subject: Eliminate Sema::CompareProperties(), which was walking over a pile of X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b898209086c363ee43b854a4b90e773248fa1f9a;p=platform%2Fupstream%2Fllvm.git Eliminate Sema::CompareProperties(), which was walking over a pile of lexical declarations looking for properties when we could more efficiently check for property mismatches at property declaration time. Good for ~1% of -fsyntax-only time when most of the properties we're checking against come from an AST file. llvm-svn: 173079 --- diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1bcafc5..eb561e3 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6213,9 +6213,6 @@ public: ObjCPropertyDecl *SuperProperty, const IdentifierInfo *Name); - - void CompareProperties(Decl *CDecl, Decl *MergeProtocols); - void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, ObjCInterfaceDecl *ID); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 909ee22..0b09697 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2380,17 +2380,13 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } } } - if (ObjCInterfaceDecl *I = dyn_cast(ClassDecl)) { - // Compares properties declared in this class to those of its - // super class. - CompareProperties(I, I); + if (isa(ClassDecl)) { + // Nothing to do here. } else if (ObjCCategoryDecl *C = dyn_cast(ClassDecl)) { // Categories are used to extend the class by declaring new methods. // By the same token, they are also used to add new properties. No // need to compare the added property to those in the class. - // Compare protocol properties with those in category - CompareProperties(C, C); if (C->IsClassExtension()) { ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); DiagnoseClassExtensionDupMethods(C, CCPrimary); diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 98d70a5..eea265a 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -112,6 +112,33 @@ static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) { return 0; } +/// \brief Check this Objective-C property against a property declared in the +/// given protocol. +static void +CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, + ObjCProtocolDecl *Proto, + llvm::SmallPtrSet &Known) { + // Have we seen this protocol before? + if (!Known.insert(Proto)) + return; + + // Look for a property with the same name. + DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *ProtoProp = dyn_cast(R[I])) { + S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier()); + return; + } + } + + // Check this property against any protocols we inherit. + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PEnd = Proto->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(S, Prop, *P, Known); + } +} + Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, @@ -173,13 +200,49 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (getLangOpts().ObjCAutoRefCount) checkARCPropertyDecl(*this, Res); - // Compare this property against the property in our superclass. + llvm::SmallPtrSet KnownProtos; if (ObjCInterfaceDecl *IFace = dyn_cast(ClassDecl)) { + // For a class, compare the property against a property in our superclass. + bool FoundInSuper = false; if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) { DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); - for (unsigned I = 0, N = R.size(); I != N; ++I) - if (ObjCPropertyDecl *SuperProp = dyn_cast(R[I])) + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *SuperProp = dyn_cast(R[I])) { DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier()); + FoundInSuper = true; + break; + } + } + } + + if (FoundInSuper) { + // Also compare the property against a property in our protocols. + for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(), + PEnd = IFace->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } else { + // Slower path: look in all protocols we referenced. + for (ObjCInterfaceDecl::all_protocol_iterator + P = IFace->all_referenced_protocol_begin(), + PEnd = IFace->all_referenced_protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } + } else if (ObjCCategoryDecl *Cat = dyn_cast(ClassDecl)) { + for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(), + PEnd = Cat->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } else { + ObjCProtocolDecl *Proto = cast(ClassDecl); + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PEnd = Proto->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); } } @@ -1336,59 +1399,6 @@ Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl) { } } -/// CompareProperties - This routine compares properties -/// declared in 'ClassOrProtocol' objects (which can be a class or an -/// inherited protocol with the list of properties for class/category 'CDecl' -/// -void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { - Decl *ClassDecl = ClassOrProtocol; - ObjCInterfaceDecl *IDecl = dyn_cast_or_null(CDecl); - - if (!IDecl) { - // Category - ObjCCategoryDecl *CatDecl = static_cast(CDecl); - assert (CatDecl && "CompareProperties"); - if (ObjCCategoryDecl *MDecl = dyn_cast(ClassDecl)) { - for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), - E = MDecl->protocol_end(); P != E; ++P) - // Match properties of category with those of protocol (*P) - MatchOneProtocolPropertiesInClass(CatDecl, *P); - - // Go thru the list of protocols for this category and recursively match - // their properties with those in the category. - for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), - E = CatDecl->protocol_end(); P != E; ++P) - CompareProperties(CatDecl, *P); - } else { - ObjCProtocolDecl *MD = cast(ClassDecl); - for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), - E = MD->protocol_end(); P != E; ++P) - MatchOneProtocolPropertiesInClass(CatDecl, *P); - } - return; - } - - if (ObjCInterfaceDecl *MDecl = dyn_cast(ClassDecl)) { - for (ObjCInterfaceDecl::all_protocol_iterator - P = MDecl->all_referenced_protocol_begin(), - E = MDecl->all_referenced_protocol_end(); P != E; ++P) - // Match properties of class IDecl with those of protocol (*P). - MatchOneProtocolPropertiesInClass(IDecl, *P); - - // Go thru the list of protocols for this class and recursively match - // their properties with those declared in the class. - for (ObjCInterfaceDecl::all_protocol_iterator - P = IDecl->all_referenced_protocol_begin(), - E = IDecl->all_referenced_protocol_end(); P != E; ++P) - CompareProperties(IDecl, *P); - } else { - ObjCProtocolDecl *MD = cast(ClassDecl); - for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), - E = MD->protocol_end(); P != E; ++P) - MatchOneProtocolPropertiesInClass(IDecl, *P); - } -} - /// isPropertyReadonly - Return true if property is readonly, by searching /// for the property in the class and in its categories and implementations ///