Skip to content

Commit 371883f

Browse files
committed
[clang/Sema] Fix non-deterministic order for certain kind of diagnostics
In the context of caching clang invocations it is important to emit diagnostics in deterministic order; the same clang invocation should result in the same diagnostic output. rdar://100336989 Differential Revision: https://reviews.llvm.org/D135118
1 parent 9223315 commit 371883f

File tree

6 files changed

+138
-33
lines changed

6 files changed

+138
-33
lines changed

clang/include/clang/AST/DeclObjC.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
#include "clang/Basic/SourceLocation.h"
2626
#include "clang/Basic/Specifiers.h"
2727
#include "llvm/ADT/ArrayRef.h"
28-
#include "llvm/ADT/DenseMap.h"
2928
#include "llvm/ADT/DenseSet.h"
29+
#include "llvm/ADT/MapVector.h"
3030
#include "llvm/ADT/None.h"
3131
#include "llvm/ADT/PointerIntPair.h"
3232
#include "llvm/ADT/STLExtras.h"
@@ -1079,16 +1079,15 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
10791079
ObjCPropertyQueryKind QueryKind) const;
10801080

10811081
using PropertyMap =
1082-
llvm::DenseMap<std::pair<IdentifierInfo *, unsigned/*isClassProperty*/>,
1083-
ObjCPropertyDecl *>;
1082+
llvm::MapVector<std::pair<IdentifierInfo *, unsigned /*isClassProperty*/>,
1083+
ObjCPropertyDecl *>;
10841084
using ProtocolPropertySet = llvm::SmallDenseSet<const ObjCProtocolDecl *, 8>;
10851085
using PropertyDeclOrder = llvm::SmallVector<ObjCPropertyDecl *, 8>;
10861086

10871087
/// This routine collects list of properties to be implemented in the class.
10881088
/// This includes, class's and its conforming protocols' properties.
10891089
/// Note, the superclass's properties are not included in the list.
1090-
virtual void collectPropertiesToImplement(PropertyMap &PM,
1091-
PropertyDeclOrder &PO) const {}
1090+
virtual void collectPropertiesToImplement(PropertyMap &PM) const {}
10921091

10931092
SourceLocation getAtStartLoc() const { return ObjCContainerDeclBits.AtStart; }
10941093

@@ -1780,8 +1779,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
17801779
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
17811780
ObjCPropertyQueryKind QueryKind) const;
17821781

1783-
void collectPropertiesToImplement(PropertyMap &PM,
1784-
PropertyDeclOrder &PO) const override;
1782+
void collectPropertiesToImplement(PropertyMap &PM) const override;
17851783

17861784
/// isSuperClassOf - Return true if this class is the specified class or is a
17871785
/// super class of the specified interface class.
@@ -2246,8 +2244,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl,
22462244
ObjCProtocolDecl *getCanonicalDecl() override { return getFirstDecl(); }
22472245
const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); }
22482246

2249-
void collectPropertiesToImplement(PropertyMap &PM,
2250-
PropertyDeclOrder &PO) const override;
2247+
void collectPropertiesToImplement(PropertyMap &PM) const override;
22512248

22522249
void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property,
22532250
ProtocolPropertySet &PS,

clang/include/clang/Sema/Scope.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "clang/AST/Decl.h"
1717
#include "clang/Basic/Diagnostic.h"
1818
#include "llvm/ADT/PointerIntPair.h"
19+
#include "llvm/ADT/SetVector.h"
1920
#include "llvm/ADT/SmallPtrSet.h"
2021
#include "llvm/ADT/SmallVector.h"
2122
#include "llvm/ADT/iterator_range.h"
@@ -196,7 +197,7 @@ class Scope {
196197
/// popped, these declarations are removed from the IdentifierTable's notion
197198
/// of current declaration. It is up to the current Action implementation to
198199
/// implement these semantics.
199-
using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>;
200+
using DeclSetTy = llvm::SmallSetVector<Decl *, 32>;
200201
DeclSetTy DeclsInScope;
201202

202203
/// The DeclContext with which this scope is associated. For
@@ -321,9 +322,7 @@ class Scope {
321322
DeclsInScope.insert(D);
322323
}
323324

324-
void RemoveDecl(Decl *D) {
325-
DeclsInScope.erase(D);
326-
}
325+
void RemoveDecl(Decl *D) { DeclsInScope.remove(D); }
327326

328327
void incrementMSManglingNumber() {
329328
if (Scope *MSLMP = getMSLastManglingParent()) {
@@ -351,7 +350,9 @@ class Scope {
351350

352351
/// isDeclScope - Return true if this is the scope that the specified decl is
353352
/// declared in.
354-
bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(D); }
353+
bool isDeclScope(const Decl *D) const {
354+
return DeclsInScope.contains(const_cast<Decl *>(D));
355+
}
355356

356357
/// Get the entity corresponding to this scope.
357358
DeclContext *getEntity() const {

clang/lib/AST/DeclObjC.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -403,21 +403,18 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
403403
return nullptr;
404404
}
405405

406-
void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM,
407-
PropertyDeclOrder &PO) const {
406+
void ObjCInterfaceDecl::collectPropertiesToImplement(PropertyMap &PM) const {
408407
for (auto *Prop : properties()) {
409408
PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
410-
PO.push_back(Prop);
411409
}
412410
for (const auto *Ext : known_extensions()) {
413411
const ObjCCategoryDecl *ClassExt = Ext;
414412
for (auto *Prop : ClassExt->properties()) {
415413
PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
416-
PO.push_back(Prop);
417414
}
418415
}
419416
for (const auto *PI : all_referenced_protocols())
420-
PI->collectPropertiesToImplement(PM, PO);
417+
PI->collectPropertiesToImplement(PM);
421418
// Note, the properties declared only in class extensions are still copied
422419
// into the main @interface's property list, and therefore we don't
423420
// explicitly, have to search class extension properties.
@@ -1998,19 +1995,17 @@ void ObjCProtocolDecl::startDefinition() {
19981995
RD->Data = this->Data;
19991996
}
20001997

2001-
void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM,
2002-
PropertyDeclOrder &PO) const {
1998+
void ObjCProtocolDecl::collectPropertiesToImplement(PropertyMap &PM) const {
20031999
if (const ObjCProtocolDecl *PDecl = getDefinition()) {
20042000
for (auto *Prop : PDecl->properties()) {
20052001
// Insert into PM if not there already.
20062002
PM.insert(std::make_pair(
20072003
std::make_pair(Prop->getIdentifier(), Prop->isClassProperty()),
20082004
Prop));
2009-
PO.push_back(Prop);
20102005
}
20112006
// Scan through protocol's protocols.
20122007
for (const auto *PI : PDecl->protocols())
2013-
PI->collectPropertiesToImplement(PM, PO);
2008+
PI->collectPropertiesToImplement(PM);
20142009
}
20152010
}
20162011

clang/lib/Sema/SemaObjCProperty.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,9 +1822,8 @@ CollectImmediateProperties(ObjCContainerDecl *CDecl,
18221822
static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
18231823
ObjCInterfaceDecl::PropertyMap &PropMap) {
18241824
if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
1825-
ObjCInterfaceDecl::PropertyDeclOrder PO;
18261825
while (SDecl) {
1827-
SDecl->collectPropertiesToImplement(PropMap, PO);
1826+
SDecl->collectPropertiesToImplement(PropMap);
18281827
SDecl = SDecl->getSuperClass();
18291828
}
18301829
}
@@ -1889,15 +1888,14 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
18891888
ObjCInterfaceDecl *IDecl,
18901889
SourceLocation AtEnd) {
18911890
ObjCInterfaceDecl::PropertyMap PropMap;
1892-
ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder;
1893-
IDecl->collectPropertiesToImplement(PropMap, PropertyOrder);
1891+
IDecl->collectPropertiesToImplement(PropMap);
18941892
if (PropMap.empty())
18951893
return;
18961894
ObjCInterfaceDecl::PropertyMap SuperPropMap;
18971895
CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
18981896

1899-
for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
1900-
ObjCPropertyDecl *Prop = PropertyOrder[i];
1897+
for (const auto &PropEntry : PropMap) {
1898+
ObjCPropertyDecl *Prop = PropEntry.second;
19011899
// Is there a matching property synthesize/dynamic?
19021900
if (Prop->isInvalidDecl() ||
19031901
Prop->isClassProperty() ||
@@ -2046,8 +2044,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
20462044
// its primary class (and its super classes) if property is
20472045
// declared in one of those containers.
20482046
if ((IDecl = C->getClassInterface())) {
2049-
ObjCInterfaceDecl::PropertyDeclOrder PO;
2050-
IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
2047+
IDecl->collectPropertiesToImplement(NoNeedToImplPropMap);
20512048
}
20522049
}
20532050
if (IDecl)

clang/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,7 @@ visit(const ObjCImplementationDecl *ImplD) const {
379379
IvarToPropMapTy IvarToPopertyMap;
380380

381381
ObjCInterfaceDecl::PropertyMap PropMap;
382-
ObjCInterfaceDecl::PropertyDeclOrder PropOrder;
383-
InterfaceD->collectPropertiesToImplement(PropMap, PropOrder);
382+
InterfaceD->collectPropertiesToImplement(PropMap);
384383

385384
for (ObjCInterfaceDecl::PropertyMap::iterator
386385
I = PropMap.begin(), E = PropMap.end(); I != E; ++I) {
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// RUN: %clang_cc1 %s -fsyntax-only -Wobjc-property-implementation -Watomic-property-with-user-defined-accessor -Wunused 2> %t.err
2+
// RUN: FileCheck -input-file=%t.err %s
3+
4+
@interface I
5+
@end
6+
7+
@interface I(cat)
8+
@property id prop1;
9+
@property id prop2;
10+
@property id prop3;
11+
@end
12+
13+
@implementation I(cat)
14+
@end
15+
16+
// CHECK: warning: property 'prop1' requires method
17+
// CHECK: warning: property 'prop2' requires method
18+
// CHECK: warning: property 'prop3' requires method
19+
20+
@interface I2
21+
@property int prop1;
22+
@property int prop2;
23+
@property int prop3;
24+
@end
25+
26+
@implementation I2
27+
@synthesize prop1, prop2, prop3;
28+
-(int) prop1 { return 0; }
29+
-(int) prop2 { return 0; }
30+
-(int) prop3 { return 0; }
31+
@end
32+
33+
// CHECK: warning: writable atomic property 'prop1'
34+
// CHECK: warning: writable atomic property 'prop2'
35+
// CHECK: warning: writable atomic property 'prop3'
36+
37+
void test_unused() {
38+
// Add enough variables to exceed the small storage of Scope::DeclSetTy.
39+
int v1;
40+
int v2;
41+
int v3;
42+
int v4;
43+
int v5;
44+
int v6;
45+
int v7;
46+
int v8;
47+
int v9;
48+
int v10;
49+
int v11;
50+
int v12;
51+
int v13;
52+
int v14;
53+
int v15;
54+
int v16;
55+
int v17;
56+
int v18;
57+
int v19;
58+
int v20;
59+
int v21;
60+
int v22;
61+
int v23;
62+
int v24;
63+
int v25;
64+
int v26;
65+
int v27;
66+
int v28;
67+
int v29;
68+
int v30;
69+
int v31;
70+
int v32;
71+
int v33;
72+
int v34;
73+
int v35;
74+
int v36;
75+
int v37;
76+
int v38;
77+
}
78+
79+
// CHECK: warning: unused variable 'v1'
80+
// CHECK: warning: unused variable 'v2'
81+
// CHECK: warning: unused variable 'v3'
82+
// CHECK: warning: unused variable 'v4'
83+
// CHECK: warning: unused variable 'v5'
84+
// CHECK: warning: unused variable 'v6'
85+
// CHECK: warning: unused variable 'v7'
86+
// CHECK: warning: unused variable 'v8'
87+
// CHECK: warning: unused variable 'v9'
88+
// CHECK: warning: unused variable 'v10'
89+
// CHECK: warning: unused variable 'v11'
90+
// CHECK: warning: unused variable 'v12'
91+
// CHECK: warning: unused variable 'v13'
92+
// CHECK: warning: unused variable 'v14'
93+
// CHECK: warning: unused variable 'v15'
94+
// CHECK: warning: unused variable 'v16'
95+
// CHECK: warning: unused variable 'v17'
96+
// CHECK: warning: unused variable 'v18'
97+
// CHECK: warning: unused variable 'v19'
98+
// CHECK: warning: unused variable 'v20'
99+
// CHECK: warning: unused variable 'v21'
100+
// CHECK: warning: unused variable 'v22'
101+
// CHECK: warning: unused variable 'v23'
102+
// CHECK: warning: unused variable 'v24'
103+
// CHECK: warning: unused variable 'v25'
104+
// CHECK: warning: unused variable 'v26'
105+
// CHECK: warning: unused variable 'v27'
106+
// CHECK: warning: unused variable 'v28'
107+
// CHECK: warning: unused variable 'v29'
108+
// CHECK: warning: unused variable 'v30'
109+
// CHECK: warning: unused variable 'v31'
110+
// CHECK: warning: unused variable 'v32'
111+
// CHECK: warning: unused variable 'v33'
112+
// CHECK: warning: unused variable 'v34'
113+
// CHECK: warning: unused variable 'v35'
114+
// CHECK: warning: unused variable 'v36'
115+
// CHECK: warning: unused variable 'v37'
116+
// CHECK: warning: unused variable 'v38'

0 commit comments

Comments
 (0)