Skip to content

ASTMatcher unless(hasAncestor(classTemplatePartialSpecializationDecl())) has no effect #138782

Open
@isVoid

Description

@isVoid

Reproducer:

Given the following example.cpp:

#include <type_traits>

template <typename A, typename B>
struct Tensor {};

template <class T>
struct is_tensor : std::false_type {};

template <class A, class B>
struct is_tensor<Tensor<A, B>> : std::true_type {};

The second is_tensor yields the following tree

`-ClassTemplatePartialSpecializationDecl 0x5e81939cb9e8 <line:9:1, line:10:50> col:8 struct is_tensor definition explicit_specialization
  |-DefinitionData empty aggregate standard_layout trivially_copyable trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
  | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr
  | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param
  | |-MoveConstructor exists simple trivial needs_implicit
  | |-CopyAssignment simple trivial has_const_param needs_implicit implicit_has_const_param
  | |-MoveAssignment exists simple trivial needs_implicit
  | `-Destructor simple irrelevant trivial needs_implicit
  |-public 'std::true_type':'std::integral_constant<bool, true>'
  |-TemplateArgument type 'Tensor<type-parameter-0-0, type-parameter-0-1>'
  | `-TemplateSpecializationType 0x5e81939cb000 'Tensor<type-parameter-0-0, type-parameter-0-1>' dependent
  |   |-name: 'Tensor'
  |   | `-ClassTemplateDecl 0x5e81939cae88 <line:3:1, line:4:16> col:8 Tensor
  |   |-TemplateArgument type 'type-parameter-0-0'
  |   | `-TemplateTypeParmType 0x5e8193817f40 'type-parameter-0-0' dependent depth 0 index 0
  |   `-TemplateArgument type 'type-parameter-0-1'
  |     `-TemplateTypeParmType 0x5e8193877fb0 'type-parameter-0-1' dependent depth 0 index 1
  |-TemplateTypeParmDecl 0x5e81939cb720 <line:9:11, col:17> col:17 referenced class depth 0 index 0 A
  |-TemplateTypeParmDecl 0x5e81939cb7a0 <col:20, col:26> col:26 referenced class depth 0 index 1 B
  `-CXXRecordDecl 0x5e81939cbc88 <line:10:1, col:8> col:8 implicit struct is_tensor

It's obvious that the CXXRecordDecl is_tensor is a child of ClassTemplatePartialSpecializationDecl.

Given ASTMatcher setup:

class RecordCallback : public MatchFinder::MatchCallback {
public:
  RecordCallback() = default;
  void run(const MatchFinder::MatchResult & Result) {
    const CXXRecordDecl *RD =
        Result.Nodes.getNodeAs<clang::CXXRecordDecl>("record");

    std::string name = RD->getNameAsString();

    if (name == "is_tensor")
    {
        std::string source_range =
        RD->getSourceRange().printToString(*Result.SourceManager);
        std::cout << source_range << std::endl;
    }
  }
};

void parse(std::vector<std::string> options) {

  auto ast = default_ast_unit_from_command_line(options);

  MatchFinder finder;

  RecordCallback record_callback;

  finder.addMatcher(
    recordDecl(allOf(
      unless(hasAncestor(classTemplatePartialSpecializationDecl())),
      unless(hasAncestor(classTemplateDecl())))).bind("record"),
                    &record_callback);

  finder.matchAST(ast->getASTContext());
}

prints

<example.cpp:9:1, line:10:50>

Expected:

Nothing should be printed because unless(hasAncestor(classTemplatePartialSpecializationDecl())) exclude all recorddecls with CTPSD in ancestors. Noticably, unless(hasAncestor(classTemplateDecl())) works as expected.

Environment:

  • clangdev 20.1.4
  • OS: Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions