@@ -45,7 +45,7 @@ ConfusableIdentifierCheck::~ConfusableIdentifierCheck() = default;
45
45
// We're skipping 1. and 3. for the sake of simplicity, but this can lead to
46
46
// false positive.
47
47
48
- std::string ConfusableIdentifierCheck:: skeleton (StringRef Name) {
48
+ static std::string skeleton (StringRef Name) {
49
49
using namespace llvm ;
50
50
std::string SName = Name.str ();
51
51
std::string Skeleton;
@@ -89,75 +89,107 @@ std::string ConfusableIdentifierCheck::skeleton(StringRef Name) {
89
89
return Skeleton;
90
90
}
91
91
92
- static bool mayShadowImpl (const NamedDecl *ND0 , const NamedDecl *ND1 ) {
93
- const DeclContext * DC0 = ND0-> getDeclContext ()-> getPrimaryContext () ;
94
- const DeclContext *DC1 = ND1-> getDeclContext ()-> getPrimaryContext ();
92
+ static bool mayShadowImpl (const DeclContext *DC0 , const DeclContext *DC1 ) {
93
+ return DC0 && DC0 == DC1 ;
94
+ }
95
95
96
- if (isa<TemplateTypeParmDecl>(ND0) || isa<TemplateTypeParmDecl>(ND0))
97
- return true ;
96
+ static bool mayShadowImpl (const NamedDecl *ND0, const NamedDecl *ND1) {
97
+ return isa<TemplateTypeParmDecl>(ND0) || isa<TemplateTypeParmDecl>(ND1);
98
+ }
98
99
99
- while (DC0->isTransparentContext ())
100
- DC0 = DC0->getParent ();
101
- while (DC1->isTransparentContext ())
102
- DC1 = DC1->getParent ();
100
+ static bool isMemberOf (const ConfusableIdentifierCheck::ContextInfo *DC0,
101
+ const ConfusableIdentifierCheck::ContextInfo *DC1) {
102
+ if (DC0->Bases .empty ())
103
+ return false ;
104
+ return llvm::is_contained (DC1->Bases , DC0->PrimaryContext );
105
+ }
103
106
104
- if (DC0->Equals (DC1))
107
+ static bool enclosesContext (const ConfusableIdentifierCheck::ContextInfo *DC0,
108
+ const ConfusableIdentifierCheck::ContextInfo *DC1) {
109
+ if (DC0->PrimaryContext == DC1->PrimaryContext )
105
110
return true ;
106
111
107
- return false ;
112
+ return llvm::is_contained (DC0->PrimaryContexts , DC1->PrimaryContext ) ||
113
+ llvm::is_contained (DC1->PrimaryContexts , DC0->PrimaryContext );
108
114
}
109
115
110
- static bool isMemberOf (const NamedDecl *ND, const CXXRecordDecl *RD) {
111
- const DeclContext *NDParent = ND->getDeclContext ();
112
- if (!NDParent || !isa<CXXRecordDecl>(NDParent))
113
- return false ;
114
- if (NDParent == RD)
116
+ static bool mayShadow (const NamedDecl *ND0,
117
+ const ConfusableIdentifierCheck::ContextInfo *DC0,
118
+ const NamedDecl *ND1,
119
+ const ConfusableIdentifierCheck::ContextInfo *DC1) {
120
+ if (!DC0->Bases .empty () && ND1->getAccess () != AS_private &&
121
+ isMemberOf (DC1, DC0))
115
122
return true ;
116
- return !RD->forallBases (
117
- [NDParent](const CXXRecordDecl *Base) { return NDParent != Base; });
123
+ if (!DC1->Bases .empty () && ND0->getAccess () != AS_private &&
124
+ isMemberOf (DC0, DC1))
125
+ return true ;
126
+
127
+ return enclosesContext (DC0, DC1) &&
128
+ (mayShadowImpl (ND0, ND1) || mayShadowImpl (DC0->NonTransparentContext ,
129
+ DC1->NonTransparentContext ));
118
130
}
119
131
120
- static bool mayShadow (const NamedDecl *ND0, const NamedDecl *ND1) {
132
+ const ConfusableIdentifierCheck::ContextInfo *
133
+ ConfusableIdentifierCheck::getContextInfo (const DeclContext *DC) {
134
+ const DeclContext *PrimaryContext = DC->getPrimaryContext ();
135
+ auto It = ContextInfos.find (PrimaryContext);
136
+ if (It != ContextInfos.end ())
137
+ return &It->second ;
138
+
139
+ ContextInfo &Info = ContextInfos[PrimaryContext];
140
+ Info.PrimaryContext = PrimaryContext;
141
+ Info.NonTransparentContext = PrimaryContext;
142
+
143
+ while (Info.NonTransparentContext ->isTransparentContext ()) {
144
+ Info.NonTransparentContext = Info.NonTransparentContext ->getParent ();
145
+ if (!Info.NonTransparentContext )
146
+ break ;
147
+ }
121
148
122
- const DeclContext *DC0 = ND0->getDeclContext ()->getPrimaryContext ();
123
- const DeclContext *DC1 = ND1->getDeclContext ()->getPrimaryContext ();
149
+ if (Info.NonTransparentContext )
150
+ Info.NonTransparentContext =
151
+ Info.NonTransparentContext ->getPrimaryContext ();
124
152
125
- if ( const CXXRecordDecl *RD0 = dyn_cast<CXXRecordDecl>(DC0) ) {
126
- RD0 = RD0-> getDefinition ();
127
- if (RD0 && ND1-> getAccess () != AS_private && isMemberOf (ND1, RD0))
128
- return true ;
153
+ while (DC ) {
154
+ if (!isa<LinkageSpecDecl>(DC) && !isa<ExportDecl>(DC))
155
+ Info. PrimaryContexts . push_back (DC-> getPrimaryContext ());
156
+ DC = DC-> getParent () ;
129
157
}
130
- if (const CXXRecordDecl *RD1 = dyn_cast<CXXRecordDecl>(DC1)) {
131
- RD1 = RD1->getDefinition ();
132
- if (RD1 && ND0->getAccess () != AS_private && isMemberOf (ND0, RD1))
133
- return true ;
158
+
159
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(PrimaryContext)) {
160
+ RD = RD->getDefinition ();
161
+ if (RD) {
162
+ Info.Bases .push_back (RD);
163
+ RD->forallBases ([&](const CXXRecordDecl *Base) {
164
+ Info.Bases .push_back (Base);
165
+ return false ;
166
+ });
167
+ }
134
168
}
135
169
136
- if (DC0->Encloses (DC1))
137
- return mayShadowImpl (ND0, ND1);
138
- if (DC1->Encloses (DC0))
139
- return mayShadowImpl (ND1, ND0);
140
- return false ;
170
+ return &Info;
141
171
}
142
172
143
173
void ConfusableIdentifierCheck::check (
144
174
const ast_matchers::MatchFinder::MatchResult &Result) {
145
175
if (const auto *ND = Result.Nodes .getNodeAs <NamedDecl>(" nameddecl" )) {
146
176
if (IdentifierInfo *NDII = ND->getIdentifier ()) {
177
+ const ContextInfo *Info = getContextInfo (ND->getDeclContext ());
147
178
StringRef NDName = NDII->getName ();
148
- llvm::SmallVector<const NamedDecl * > &Mapped = Mapper[skeleton (NDName)];
149
- for (const NamedDecl *OND : Mapped) {
150
- const IdentifierInfo *ONDII = OND ->getIdentifier ();
151
- if (mayShadow (ND, OND )) {
179
+ llvm::SmallVector<Entry > &Mapped = Mapper[skeleton (NDName)];
180
+ for (const Entry &E : Mapped) {
181
+ const IdentifierInfo *ONDII = E. Declaration ->getIdentifier ();
182
+ if (mayShadow (ND, Info, E. Declaration , E. Info )) {
152
183
StringRef ONDName = ONDII->getName ();
153
184
if (ONDName != NDName) {
154
- diag (ND->getLocation (), " %0 is confusable with %1" ) << ND << OND;
155
- diag (OND->getLocation (), " other declaration found here" ,
185
+ diag (ND->getLocation (), " %0 is confusable with %1" )
186
+ << ND << E.Declaration ;
187
+ diag (E.Declaration ->getLocation (), " other declaration found here" ,
156
188
DiagnosticIDs::Note);
157
189
}
158
190
}
159
191
}
160
- Mapped.push_back (ND );
192
+ Mapped.push_back ({ND, Info} );
161
193
}
162
194
}
163
195
}
0 commit comments