mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
[include-cleaner] Report refs for enum constants used through namespace aliases (#106706)
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/NestedNameSpecifier.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/TemplateBase.h"
|
||||
#include "clang/AST/TemplateName.h"
|
||||
@@ -23,9 +24,11 @@
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/STLFunctionalExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace clang::include_cleaner {
|
||||
namespace {
|
||||
@@ -125,6 +128,24 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool qualifierIsNamespaceOrNone(DeclRefExpr *DRE) {
|
||||
const auto *Qual = DRE->getQualifier();
|
||||
if (!Qual)
|
||||
return true;
|
||||
switch (Qual->getKind()) {
|
||||
case NestedNameSpecifier::Namespace:
|
||||
case NestedNameSpecifier::NamespaceAlias:
|
||||
case NestedNameSpecifier::Global:
|
||||
return true;
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate:
|
||||
case NestedNameSpecifier::Super:
|
||||
case NestedNameSpecifier::Identifier:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Unknown value for NestedNameSpecifierKind");
|
||||
}
|
||||
|
||||
bool VisitDeclRefExpr(DeclRefExpr *DRE) {
|
||||
auto *FD = DRE->getFoundDecl();
|
||||
// Prefer the underlying decl if FoundDecl isn't a shadow decl, e.g:
|
||||
@@ -146,10 +167,8 @@ public:
|
||||
//
|
||||
// If it's an enum constant, it must be due to prior decl. Report references
|
||||
// to it when qualifier isn't a type.
|
||||
if (llvm::isa<EnumConstantDecl>(FD)) {
|
||||
if (!DRE->getQualifier() || DRE->getQualifier()->getAsNamespace())
|
||||
report(DRE->getLocation(), FD);
|
||||
}
|
||||
if (llvm::isa<EnumConstantDecl>(FD) && qualifierIsNamespaceOrNone(DRE))
|
||||
report(DRE->getLocation(), FD);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -534,6 +534,9 @@ TEST(WalkAST, Enums) {
|
||||
testWalk(R"(namespace ns { enum E { A = 42 }; }
|
||||
struct S { using ns::E::A; };)",
|
||||
"int e = S::^A;");
|
||||
testWalk(R"(namespace ns { enum E { $explicit^A = 42 }; })",
|
||||
"namespace z = ns; int e = z::^A;");
|
||||
testWalk(R"(enum E { $explicit^A = 42 };)", "int e = ::^A;");
|
||||
}
|
||||
|
||||
TEST(WalkAST, InitializerList) {
|
||||
|
||||
Reference in New Issue
Block a user