This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG03101e141bf7: [include-cleaner] Attribute references to
explicit specializations (authored by kadircet).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D146732/new/
https://reviews.llvm.org/D146732
Files:
clang-tools-extra/include-cleaner/lib/WalkAST.cpp
clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
Index: clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
===================================================================
--- clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -114,6 +114,25 @@
// One explicit call from the TypeLoc in constructor spelling, another
// implicit reference through the constructor call.
testWalk("struct $explicit^$implicit^S { static int x; };", "auto y = ^S();");
+ testWalk("template<typename> struct $explicit^Foo {};", "^Foo<int> x;");
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ template<> struct $explicit^Foo<int> {};)cpp",
+ "^Foo<int> x;");
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ template<typename T> struct $explicit^Foo<T*> { void x(); };)cpp",
+ "^Foo<int *> x;");
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ template struct $explicit^Foo<int>;)cpp",
+ "^Foo<int> x;");
+ // FIXME: This is broken due to
+ // https://github.com/llvm/llvm-project/issues/42259.
+ testWalk(R"cpp(
+ template<typename T> struct $explicit^Foo { Foo(T); };
+ template<> struct Foo<int> { void get(); Foo(int); };)cpp",
+ "^Foo x(3);");
}
TEST(WalkAST, Alias) {
@@ -124,6 +143,25 @@
"int y = ^x;");
testWalk("using $explicit^foo = int;", "^foo x;");
testWalk("struct S {}; using $explicit^foo = S;", "^foo x;");
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ template<> struct Foo<int> {};
+ namespace ns { using ::$explicit^Foo; })cpp",
+ "ns::^Foo<int> x;");
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ namespace ns { using ::Foo; }
+ template<> struct ns::$explicit^Foo<int> {};)cpp",
+ "^Foo<int> x;");
+ // AST doesn't have enough information to figure out whether specialization
+ // happened through an exported type or not. So err towards attributing use to
+ // the using-decl, specializations on the exported type should be rare and
+ // they're not permitted on type-aliases.
+ testWalk(R"cpp(
+ template<typename> struct Foo {};
+ namespace ns { using ::$explicit^Foo; }
+ template<> struct ns::Foo<int> {};)cpp",
+ "ns::^Foo<int> x;");
}
TEST(WalkAST, Using) {
@@ -183,10 +221,6 @@
template <template <typename> typename> struct X {};
X<^S> x;)cpp");
testWalk("template<typename T> struct $explicit^S { S(T); };", "^S s(42);");
- // Should we mark the specialization instead?
- testWalk(
- "template<typename> struct $explicit^S {}; template <> struct S<int> {};",
- "^S<int> s;");
}
TEST(WalkAST, MemberExprs) {
Index: clang-tools-extra/include-cleaner/lib/WalkAST.cpp
===================================================================
--- clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -7,16 +7,19 @@
//===----------------------------------------------------------------------===//
#include "AnalysisInternal.h"
+#include "clang-include-cleaner/Types.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/Casting.h"
namespace clang::include_cleaner {
@@ -62,6 +65,24 @@
return resolveTemplateName(TST->getTemplateName());
return Base->getAsRecordDecl();
}
+ // Templated as TemplateSpecializationType and
+ // DeducedTemplateSpecializationType doesn't share a common base.
+ template <typename T>
+ // Picks the most specific specialization for a
+ // (Deduced)TemplateSpecializationType, while prioritizing using-decls.
+ NamedDecl *getMostRelevantTemplatePattern(const T *TST) {
+ // This is the underlying decl used by TemplateSpecializationType, can be
+ // null when type is dependent.
+ auto *RD = TST->getAsTagDecl();
+ auto *ND = resolveTemplateName(TST->getTemplateName());
+ // In case of exported template names always prefer the using-decl. This
+ // implies we'll point at the using-decl even when there's an explicit
+ // specializaiton using the exported name, but that's rare.
+ if (llvm::isa_and_present<UsingShadowDecl, TypeAliasTemplateDecl>(ND))
+ return ND;
+ // Fallback to primary template for dependent instantiations.
+ return RD ? RD : ND;
+ }
public:
ASTWalker(DeclCallback Callback) : Callback(Callback) {}
@@ -161,17 +182,15 @@
}
bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
- // FIXME: Handle explicit specializations.
report(TL.getTemplateNameLoc(),
- resolveTemplateName(TL.getTypePtr()->getTemplateName()));
+ getMostRelevantTemplatePattern(TL.getTypePtr()));
return true;
}
bool VisitDeducedTemplateSpecializationTypeLoc(
DeducedTemplateSpecializationTypeLoc TL) {
- // FIXME: Handle specializations.
report(TL.getTemplateNameLoc(),
- resolveTemplateName(TL.getTypePtr()->getTemplateName()));
+ getMostRelevantTemplatePattern(TL.getTypePtr()));
return true;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits