Skip to content

Commit 60ed104

Browse files
authored
[include-cleaner] Report refs for enum constants used through namespace aliases (llvm#106706)
1 parent 224112f commit 60ed104

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

clang-tools-extra/include-cleaner/lib/WalkAST.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/DeclTemplate.h"
1616
#include "clang/AST/Expr.h"
1717
#include "clang/AST/ExprCXX.h"
18+
#include "clang/AST/NestedNameSpecifier.h"
1819
#include "clang/AST/RecursiveASTVisitor.h"
1920
#include "clang/AST/TemplateBase.h"
2021
#include "clang/AST/TemplateName.h"
@@ -23,9 +24,11 @@
2324
#include "clang/Basic/IdentifierTable.h"
2425
#include "clang/Basic/SourceLocation.h"
2526
#include "clang/Basic/Specifiers.h"
27+
#include "llvm/ADT/STLExtras.h"
2628
#include "llvm/ADT/STLFunctionalExtras.h"
2729
#include "llvm/ADT/SmallVector.h"
2830
#include "llvm/Support/Casting.h"
31+
#include "llvm/Support/ErrorHandling.h"
2932

3033
namespace clang::include_cleaner {
3134
namespace {
@@ -125,6 +128,24 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
125128
return true;
126129
}
127130

131+
bool qualifierIsNamespaceOrNone(DeclRefExpr *DRE) {
132+
const auto *Qual = DRE->getQualifier();
133+
if (!Qual)
134+
return true;
135+
switch (Qual->getKind()) {
136+
case NestedNameSpecifier::Namespace:
137+
case NestedNameSpecifier::NamespaceAlias:
138+
case NestedNameSpecifier::Global:
139+
return true;
140+
case NestedNameSpecifier::TypeSpec:
141+
case NestedNameSpecifier::TypeSpecWithTemplate:
142+
case NestedNameSpecifier::Super:
143+
case NestedNameSpecifier::Identifier:
144+
return false;
145+
}
146+
llvm_unreachable("Unknown value for NestedNameSpecifierKind");
147+
}
148+
128149
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
129150
auto *FD = DRE->getFoundDecl();
130151
// Prefer the underlying decl if FoundDecl isn't a shadow decl, e.g:
@@ -146,10 +167,8 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
146167
//
147168
// If it's an enum constant, it must be due to prior decl. Report references
148169
// to it when qualifier isn't a type.
149-
if (llvm::isa<EnumConstantDecl>(FD)) {
150-
if (!DRE->getQualifier() || DRE->getQualifier()->getAsNamespace())
151-
report(DRE->getLocation(), FD);
152-
}
170+
if (llvm::isa<EnumConstantDecl>(FD) && qualifierIsNamespaceOrNone(DRE))
171+
report(DRE->getLocation(), FD);
153172
return true;
154173
}
155174

clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,9 @@ TEST(WalkAST, Enums) {
534534
testWalk(R"(namespace ns { enum E { A = 42 }; }
535535
struct S { using ns::E::A; };)",
536536
"int e = S::^A;");
537+
testWalk(R"(namespace ns { enum E { $explicit^A = 42 }; })",
538+
"namespace z = ns; int e = z::^A;");
539+
testWalk(R"(enum E { $explicit^A = 42 };)", "int e = ::^A;");
537540
}
538541

539542
TEST(WalkAST, InitializerList) {

0 commit comments

Comments
 (0)