Skip to content

Commit a334eb1

Browse files
committed
[RecursiveASTVisitor] Skip implicit instantiations.
In DEF_TRAVERSE_TMPL_SPEC_DECL, we attempted to skip implicit instantiations by detecting that D->getTemplateArgsAsWritten() returns nullptr, but as this test shows, it is possible for that to return a non-null pointer even for implicit instantiations. Explicitly check for this case instead. Fixes #110502
1 parent 650c41a commit a334eb1

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,22 @@ namespace std {
1414
static constexpr bool value = true;
1515
};
1616

17+
template <typename T, typename U>
18+
static constexpr bool is_same_v = is_same<T, U>::value; // NOLINT
19+
1720
template<bool, typename T = void>
1821
struct enable_if {
1922
using type = T;
2023
};
2124

25+
template <bool B, typename T = void>
26+
using enable_if_t = typename enable_if<B, T>::type; // NOLINT
27+
28+
template <typename T>
29+
struct remove_reference {
30+
using type = T;
31+
};
32+
2233
inline namespace __std_lib_version1 {
2334
template<typename T>
2435
struct add_const {
@@ -117,3 +128,13 @@ namespace my_std = std;
117128
using Alias = my_std::add_const<bool>::type;
118129
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use c++14 style type templates
119130
// CHECK-FIXES: using Alias = my_std::add_const_t<bool>;
131+
132+
template <typename T>
133+
struct ImplicitlyInstantiatedConstructor {
134+
template <typename U, typename = std::enable_if_t<std::is_same_v<U, T>>>
135+
ImplicitlyInstantiatedConstructor(U) {}
136+
};
137+
138+
const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference<int>::type(123));
139+
// CHECK-MESSAGES: :[[@LINE-1]]:68: warning: use c++14 style type templates
140+
// CHECK-FIXES: const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference_t<int>(123));

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,22 +2069,24 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
20692069

20702070
#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
20712071
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
2072+
auto TSK = D->getTemplateSpecializationKind(); \
20722073
/* For implicit instantiations ("set<int> x;"), we don't want to \
20732074
recurse at all, since the instatiated template isn't written in \
20742075
the source code anywhere. (Note the instatiated *type* -- \
20752076
set<int> -- is written, and will still get a callback of \
20762077
TemplateSpecializationType). For explicit instantiations \
20772078
("template set<int>;"), we do need a callback, since this \
2078-
is the only callback that's made for this instantiation. \
2079-
We use getTemplateArgsAsWritten() to distinguish. */ \
2080-
if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \
2081-
/* The args that remains unspecialized. */ \
2082-
TRY_TO(TraverseTemplateArgumentLocsHelper( \
2083-
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
2079+
is the only callback that's made for this instantiation. */ \
2080+
if (TSK != TSK_Undeclared && TSK != TSK_ImplicitInstantiation) { \
2081+
if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \
2082+
/* The args that remains unspecialized. */ \
2083+
TRY_TO(TraverseTemplateArgumentLocsHelper( \
2084+
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
2085+
} \
20842086
} \
20852087
\
20862088
if (getDerived().shouldVisitTemplateInstantiations() || \
2087-
D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \
2089+
TSK == TSK_ExplicitSpecialization) { \
20882090
/* Traverse base definition for explicit specializations */ \
20892091
TRY_TO(Traverse##DECLKIND##Helper(D)); \
20902092
} else { \

0 commit comments

Comments
 (0)