diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -25,8 +25,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/None.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" @@ -1079,16 +1079,15 @@ ObjCPropertyQueryKind QueryKind) const; using PropertyMap = - llvm::DenseMap, - ObjCPropertyDecl *>; + llvm::MapVector, + ObjCPropertyDecl *>; using ProtocolPropertySet = llvm::SmallDenseSet; using PropertyDeclOrder = llvm::SmallVector; /// This routine collects list of properties to be implemented in the class. /// This includes, class's and its conforming protocols' properties. /// Note, the superclass's properties are not included in the list. - virtual void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const {} + virtual void collectPropertiesToImplement(PropertyMap &PM) const {} SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; } @@ -1780,8 +1779,7 @@ *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const; - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; + void collectPropertiesToImplement(PropertyMap &PM) const override; /// isSuperClassOf - Return true if this class is the specified class or is a /// super class of the specified interface class. @@ -2246,8 +2244,7 @@ ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); } const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); } - void collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const override; + void collectPropertiesToImplement(PropertyMap &PM) const override; void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, ProtocolPropertySet &PS, diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -16,6 +16,7 @@ #include "clang/AST/Decl.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" @@ -196,7 +197,7 @@ /// popped, these declarations are removed from the IdentifierTable's notion /// of current declaration. It is up to the current Action implementation to /// implement these semantics. - using DeclSetTy = llvm::SmallPtrSet; + using DeclSetTy = llvm::SmallSetVector; DeclSetTy DeclsInScope; /// The DeclContext with which this scope is associated. For @@ -321,9 +322,7 @@ DeclsInScope.insert(D); } - void RemoveDecl(Decl *D) { - DeclsInScope.erase(D); - } + void RemoveDecl(Decl *D) { DeclsInScope.remove(D); } void incrementMSManglingNumber() { if (Scope *MSLMP = getMSLastManglingParent()) { @@ -351,7 +350,9 @@ /// isDeclScope - Return true if this is the scope that the specified decl is /// declared in. - bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(D); } + bool isDeclScope(const Decl *D) const { + return DeclsInScope.contains(const_cast(D)); + } /// Get the entity corresponding to this scope. DeclContext *getEntity() const { diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -403,21 +403,18 @@ return nullptr; } -void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const { +void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const { for (auto *Prop : properties()) { PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; - PO.push_back(Prop); } for (const auto *Ext : known_extensions()) { const ObjCCategoryDecl *ClassExt = Ext; for (auto *Prop : ClassExt->properties()) { PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; - PO.push_back(Prop); } } for (const auto *PI : all_referenced_protocols()) - PI->collectPropertiesToImplement(PM, PO); + PI->collectPropertiesToImplement(PM); // Note, the properties declared only in class extensions are still copied // into the main @interface's property list, and therefore we don't // explicitly, have to search class extension properties. @@ -1998,19 +1995,17 @@ RD->Data = this->Data; } -void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM, - PropertyDeclOrder &PO) const { +void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const { if (const ObjCProtocolDecl *PDecl = getDefinition()) { for (auto *Prop : PDecl->properties()) { // Insert into PM if not there already. PM.insert(std::make_pair( std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()), Prop)); - PO.push_back(Prop); } // Scan through protocol's protocols. for (const auto *PI : PDecl->protocols()) - PI->collectPropertiesToImplement(PM, PO); + PI->collectPropertiesToImplement(PM); } } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1822,9 +1822,8 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, ObjCInterfaceDecl::PropertyMap &PropMap) { if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { - ObjCInterfaceDecl::PropertyDeclOrder PO; while (SDecl) { - SDecl->collectPropertiesToImplement(PropMap, PO); + SDecl->collectPropertiesToImplement(PropMap); SDecl = SDecl->getSuperClass(); } } @@ -1889,15 +1888,14 @@ ObjCInterfaceDecl *IDecl, SourceLocation AtEnd) { ObjCInterfaceDecl::PropertyMap PropMap; - ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder; - IDecl->collectPropertiesToImplement(PropMap, PropertyOrder); + IDecl->collectPropertiesToImplement(PropMap); if (PropMap.empty()) return; ObjCInterfaceDecl::PropertyMap SuperPropMap; CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); - for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { - ObjCPropertyDecl *Prop = PropertyOrder[i]; + for (const auto &PropEntry : PropMap) { + ObjCPropertyDecl *Prop = PropEntry.second; // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || Prop->isClassProperty() || @@ -2046,8 +2044,7 @@ // its primary class (and its super classes) if property is // declared in one of those containers. if ((IDecl = C->getClassInterface())) { - ObjCInterfaceDecl::PropertyDeclOrder PO; - IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); + IDecl->collectPropertiesToImplement(NoNeedToImplPropMap); } } if (IDecl) diff --git a/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp @@ -379,8 +379,7 @@ IvarToPropMapTy IvarToPopertyMap; ObjCInterfaceDecl::PropertyMap PropMap; - ObjCInterfaceDecl::PropertyDeclOrder PropOrder; - InterfaceD->collectPropertiesToImplement(PropMap, PropOrder); + InterfaceD->collectPropertiesToImplement(PropMap); for (ObjCInterfaceDecl::PropertyMap::iterator I = PropMap.begin(), E = PropMap.end(); I != E; ++I) { diff --git a/clang/test/Sema/deterministic-diagnostics-order.m b/clang/test/Sema/deterministic-diagnostics-order.m new file mode 100644 --- /dev/null +++ b/clang/test/Sema/deterministic-diagnostics-order.m @@ -0,0 +1,116 @@ +// RUN: %clang_cc1 %s -fsyntax-only -Wobjc-property-implementation -Watomic-property-with-user-defined-accessor -Wunused 2> %t.err +// RUN: FileCheck -input-file=%t.err %s + +@interface I +@end + +@interface I(cat) +@property id prop1; +@property id prop2; +@property id prop3; +@end + +@implementation I(cat) +@end + +// CHECK: warning: property 'prop1' requires method +// CHECK: warning: property 'prop2' requires method +// CHECK: warning: property 'prop3' requires method + +@interface I2 +@property int prop1; +@property int prop2; +@property int prop3; +@end + +@implementation I2 +@synthesize prop1, prop2, prop3; +-(int) prop1 { return 0; } +-(int) prop2 { return 0; } +-(int) prop3 { return 0; } +@end + +// CHECK: warning: writable atomic property 'prop1' +// CHECK: warning: writable atomic property 'prop2' +// CHECK: warning: writable atomic property 'prop3' + +void test_unused() { + // Add enough variables to exceed the small storage of Scope::DeclSetTy. + int v1; + int v2; + int v3; + int v4; + int v5; + int v6; + int v7; + int v8; + int v9; + int v10; + int v11; + int v12; + int v13; + int v14; + int v15; + int v16; + int v17; + int v18; + int v19; + int v20; + int v21; + int v22; + int v23; + int v24; + int v25; + int v26; + int v27; + int v28; + int v29; + int v30; + int v31; + int v32; + int v33; + int v34; + int v35; + int v36; + int v37; + int v38; +} + +// CHECK: warning: unused variable 'v1' +// CHECK: warning: unused variable 'v2' +// CHECK: warning: unused variable 'v3' +// CHECK: warning: unused variable 'v4' +// CHECK: warning: unused variable 'v5' +// CHECK: warning: unused variable 'v6' +// CHECK: warning: unused variable 'v7' +// CHECK: warning: unused variable 'v8' +// CHECK: warning: unused variable 'v9' +// CHECK: warning: unused variable 'v10' +// CHECK: warning: unused variable 'v11' +// CHECK: warning: unused variable 'v12' +// CHECK: warning: unused variable 'v13' +// CHECK: warning: unused variable 'v14' +// CHECK: warning: unused variable 'v15' +// CHECK: warning: unused variable 'v16' +// CHECK: warning: unused variable 'v17' +// CHECK: warning: unused variable 'v18' +// CHECK: warning: unused variable 'v19' +// CHECK: warning: unused variable 'v20' +// CHECK: warning: unused variable 'v21' +// CHECK: warning: unused variable 'v22' +// CHECK: warning: unused variable 'v23' +// CHECK: warning: unused variable 'v24' +// CHECK: warning: unused variable 'v25' +// CHECK: warning: unused variable 'v26' +// CHECK: warning: unused variable 'v27' +// CHECK: warning: unused variable 'v28' +// CHECK: warning: unused variable 'v29' +// CHECK: warning: unused variable 'v30' +// CHECK: warning: unused variable 'v31' +// CHECK: warning: unused variable 'v32' +// CHECK: warning: unused variable 'v33' +// CHECK: warning: unused variable 'v34' +// CHECK: warning: unused variable 'v35' +// CHECK: warning: unused variable 'v36' +// CHECK: warning: unused variable 'v37' +// CHECK: warning: unused variable 'v38'