Skip to content

Commit

Permalink
[RecursiveASTVisitor] Skip implicit instantiations.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
hvdijk committed Oct 2, 2024
1 parent bc91f3c commit 5e06336
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,22 @@ namespace std {
static constexpr bool value = true;
};

template <typename T, typename U>
static constexpr bool is_same_v = is_same<T, U>::value; // NOLINT

template<bool, typename T = void>
struct enable_if {
using type = T;
};

template <bool B, typename T = void>
using enable_if_t = typename enable_if<B, T>::type; // NOLINT

template <typename T>
struct remove_reference {
using type = T;
};

inline namespace __std_lib_version1 {
template<typename T>
struct add_const {
Expand Down Expand Up @@ -117,3 +128,13 @@ namespace my_std = std;
using Alias = my_std::add_const<bool>::type;
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use c++14 style type templates
// CHECK-FIXES: using Alias = my_std::add_const_t<bool>;

template <typename T>
struct ImplicitlyInstantiatedConstructor {
template <typename U, typename = std::enable_if_t<std::is_same_v<U, T>>>
ImplicitlyInstantiatedConstructor(U) {}
};

const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference<int>::type(123));
// CHECK-MESSAGES: :[[@LINE-1]]:68: warning: use c++14 style type templates
// CHECK-FIXES: const ImplicitlyInstantiatedConstructor<int> ImplicitInstantiation(std::remove_reference_t<int>(123));
16 changes: 9 additions & 7 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2069,22 +2069,24 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(

#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \
auto TSK = D->getTemplateSpecializationKind(); \
/* For implicit instantiations ("set<int> x;"), we don't want to \
recurse at all, since the instatiated template isn't written in \
the source code anywhere. (Note the instatiated *type* -- \
set<int> -- is written, and will still get a callback of \
TemplateSpecializationType). For explicit instantiations \
("template set<int>;"), we do need a callback, since this \
is the only callback that's made for this instantiation. \
We use getTemplateArgsAsWritten() to distinguish. */ \
if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \
/* The args that remains unspecialized. */ \
TRY_TO(TraverseTemplateArgumentLocsHelper( \
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
is the only callback that's made for this instantiation. */ \
if (TSK != TSK_ImplicitInstantiation) { \
if (const auto *ArgsWritten = D->getTemplateArgsAsWritten()) { \
/* The args that remains unspecialized. */ \
TRY_TO(TraverseTemplateArgumentLocsHelper( \
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
} \
} \
\
if (getDerived().shouldVisitTemplateInstantiations() || \
D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \
TSK == TSK_ExplicitSpecialization) { \
/* Traverse base definition for explicit specializations */ \
TRY_TO(Traverse##DECLKIND##Helper(D)); \
} else { \
Expand Down

0 comments on commit 5e06336

Please sign in to comment.