<div dir="ltr"><div><div>Hi Jason,<br><br></div>Do you care about the distinction between class declarations and class definitions? If not, the following matcher should suffice:<br><br>DeclarationMatcher CLASS_MATCHER<br>
= cxxRecordDecl(<br></div> isDefinition(),<br><div>
unless(isTemplateInstantiation()),<br>
hasAncestor(<br>
namespaceDecl(hasName("test"))<br>
)<br>
).bind("class");<br><br><br></div><div>Similarly, in the code that handles the matcher you could check if the result is a definition. This latter approach is useful if you do care about this distinction.<br><br></div><div>-Adam<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 28, 2016 at 6:11 PM, Jason Murray via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hey all,<br>
<br>
I've been working with AST Matchers with minimal issues for a while<br>
now, but I recently started running into issues when querying matched<br>
CXXRecordDecls for information about their base classes.<br>
<br>
Here's a repro repo: <a href="https://github.com/nopppers/clang-bases-bug" rel="noreferrer" target="_blank">https://github.com/nopppers/clang-bases-bug</a><br>
<br>
Given the following matcher,<br>
<br>
DeclarationMatcher CLASS_MATCHER<br>
= cxxRecordDecl(<br>
unless(isTemplateInstantiation()),<br>
hasAncestor(<br>
namespaceDecl(hasName("test"))<br>
)<br>
).bind("class");<br>
<br>
Calling CXXRecordDecl::getNumBases() or other base-class-related<br>
functions like bases_begin() on the result of the matcher will<br>
sometimes hit an assert. The debug message in the assert is<br>
"queried property of class with no definition"<br>
<br>
The first condition under which the assert will trigger is when the<br>
matcher callback recieves the CXXRecordDecl for the implicit<br>
self-reference that the class has. For example, if the matcher is run<br>
on the following code:<br>
<br>
namespace test<br>
{<br>
class Foo {};<br>
}<br>
<br>
The call to getNumBases() will succeed for the first match, test::Foo,<br>
and assert for the match test::Foo::Foo.<br>
<br>
To circumvent this, I've tried testing for<br>
CXXRecordDecl::isImplicit(), which works around the assert properly.<br>
There is, however, a second situation where the assert is triggered<br>
that I don't understand.<br>
<br>
Running the matcher on the following code<br>
<br>
namespace test<br>
{<br>
template <typename T><br>
class DummyTemplate{};<br>
<br>
class Dummy<br>
{<br>
public:<br>
// DummyTemplate<int> uncommentMeAndTheAssertWontTrigger;<br>
};<br>
<br>
extern DummyTemplate<int> triggersAssertIfAboveIsCommentedOut;<br>
}<br>
<br>
Results in the same assert, but only if the variable declaration in<br>
the class is commented out.<br>
Adding a classTemplateSpecialization matcher reveals some more info:<br>
<br>
Output with class var decl commented out:<br>
<br>
Found CXXRecordDecl<br>
NumBases for test::DummyTemplate: 0<br>
End.<br>
Found CXXRecordDecl<br>
NumBases for test::DummyTemplate: Assertion failed: DD && "queried<br>
property of class with no definition", file<br>
S:\programming\libraries\clang\llvm\tools\clang\include\clang/AST/DeclCXX.h,<br>
line 595<br>
<br>
Output with var decl uncommented:<br>
<br>
Found CXXRecordDecl<br>
NumBases for test::DummyTemplate: 0<br>
End.<br>
Found ClassTemplateSpecializationDecl<br>
NumBases for test::DummyTemplate: 0<br>
End.<br>
Found CXXRecordDecl<br>
NumBases for test::Dummy: 0<br>
End.<br>
<br>
So what is one to do? I'm unsure whether hitting the assert is<br>
intentional in either case. If it is, how can I avoid hitting it in<br>
the second case?<br>
<br>
Repro link again: <a href="https://github.com/nopppers/clang-bases-bug" rel="noreferrer" target="_blank">https://github.com/nopppers/clang-bases-bug</a><br>
<br>
Regards,<br>
Jason Powers Murray<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div>