Annotations Test(Code);
auto AST = TestTU::withCode(Test.code()).build();
std::vector<HighlightingToken> ActualTokens = getSemanticHighlightings(AST);
- EXPECT_THAT(ActualTokens, getExpectedTokens(Test));
+ EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
}
// Any annotations in OldCode and NewCode are converted into their corresponding
$Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
$Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
}
+ )cpp"
+ R"cpp(
+ struct $Class[[B]] {};
+ struct $Class[[A]] {
+ $Class[[B]] $Field[[BB]];
+ $Class[[A]] &operator=($Class[[A]] &&$Variable[[O]]);
+ };
+
+ $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = default;
)cpp"};
for (const auto &TestCase : TestCases) {
checkHighlightings(TestCase);
}
}
- if (D->isThisDeclarationADefinition()) {
+ bool VisitBody = D->isThisDeclarationADefinition();
+ // If a method is set to default outside the class definition the compiler
+ // generates the method body and adds it to the AST.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
+ VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode();
+
+ if (VisitBody) {
TRY_TO(TraverseStmt(D->getBody())); // Function body.
}
return true;
RecursiveASTVisitorTests/ConstructExpr.cpp
RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
RecursiveASTVisitorTests/CXXMemberCall.cpp
+ RecursiveASTVisitorTests/CXXMethodDecl.cpp
RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
RecursiveASTVisitorTests/DeclRefExpr.cpp
RecursiveASTVisitorTests/ImplicitCtor.cpp
--- /dev/null
+//=------ unittest/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp ------=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include "clang/AST/Expr.h"
+
+using namespace clang;
+
+namespace {
+
+class CXXMethodDeclVisitor
+ : public ExpectedLocationVisitor<CXXMethodDeclVisitor> {
+public:
+ CXXMethodDeclVisitor(bool VisitImplicitCode)
+ : VisitImplicitCode(VisitImplicitCode) {}
+
+ bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+
+ bool VisitDeclRefExpr(DeclRefExpr *D) {
+ Match("declref", D->getLocation());
+ return true;
+ }
+ bool VisitParmVarDecl(ParmVarDecl *P) {
+ Match("parm", P->getLocation());
+ return true;
+ }
+
+private:
+ bool VisitImplicitCode;
+};
+
+TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) {
+ for (bool VisitImplCode : {false, true}) {
+ CXXMethodDeclVisitor Visitor(VisitImplCode);
+ if (VisitImplCode)
+ Visitor.ExpectMatch("declref", 8, 28);
+ else
+ Visitor.DisallowMatch("declref", 8, 28);
+
+ Visitor.ExpectMatch("parm", 8, 27);
+ llvm::StringRef Code = R"cpp(
+ struct B {};
+ struct A {
+ B BB;
+ A &operator=(A &&O);
+ };
+
+ A &A::operator=(A &&O) = default;
+ )cpp";
+ EXPECT_TRUE(Visitor.runOver(Code, CXXMethodDeclVisitor::Lang_CXX11));
+ }
+}
+} // end anonymous namespace