r368052 - [AST] Traverse attributes inside DEF_TRAVERSE_DECL macro
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 6 08:46:13 PDT 2019
Author: ibiryukov
Date: Tue Aug 6 08:46:12 2019
New Revision: 368052
URL: http://llvm.org/viewvc/llvm-project?rev=368052&view=rev
Log:
[AST] Traverse attributes inside DEF_TRAVERSE_DECL macro
Summary:
Instead of traversing inside the TraverseDecl() function.
Previously the attributes were traversed after Travese(Some)Decl
returns.
Logically attributes are properties of particular Decls and should be
traversed alongside other "child" nodes.
None of the tests relied on this behavior, hopefully this is an indication
that the change is relatively safe.
This change started with a discussion on cfe-dev, for details see:
https://lists.llvm.org/pipermail/cfe-dev/2019-July/062899.html
Reviewers: rsmith, gribozavr
Reviewed By: gribozavr
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64907
Added:
cfe/trunk/unittests/AST/RecursiveASTVisitorTest.cpp
Modified:
cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
cfe/trunk/unittests/AST/CMakeLists.txt
Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=368052&r1=368051&r2=368052&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Aug 6 08:46:12 2019
@@ -722,12 +722,6 @@ bool RecursiveASTVisitor<Derived>::Trave
break;
#include "clang/AST/DeclNodes.inc"
}
-
- // Visit any attributes attached to this declaration.
- for (auto *I : D->attrs()) {
- if (!getDerived().TraverseAttr(I))
- return false;
- }
return true;
}
@@ -1407,6 +1401,11 @@ bool RecursiveASTVisitor<Derived>::Trave
{ CODE; } \
if (ReturnValue && ShouldVisitChildren) \
TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
+ if (ReturnValue) { \
+ /* Visit any attributes attached to this declaration. */ \
+ for (auto *I : D->attrs()) \
+ TRY_TO(getDerived().TraverseAttr(I)); \
+ } \
if (ReturnValue && getDerived().shouldTraversePostOrder()) \
TRY_TO(WalkUpFrom##DECL(D)); \
return ReturnValue; \
Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=368052&r1=368051&r2=368052&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Tue Aug 6 08:46:12 2019
@@ -26,6 +26,7 @@ add_clang_unittest(ASTTests
Language.cpp
NamedDeclPrinterTest.cpp
OMPStructuredBlockTest.cpp
+ RecursiveASTVisitorTest.cpp
SourceLocationTest.cpp
StmtPrinterTest.cpp
StructuralEquivalenceTest.cpp
Added: cfe/trunk/unittests/AST/RecursiveASTVisitorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/RecursiveASTVisitorTest.cpp?rev=368052&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/RecursiveASTVisitorTest.cpp (added)
+++ cfe/trunk/unittests/AST/RecursiveASTVisitorTest.cpp Tue Aug 6 08:46:12 2019
@@ -0,0 +1,106 @@
+//===- unittest/AST/RecursiveASTVisitorTest.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 "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock-generated-matchers.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cassert>
+
+using namespace clang;
+using ::testing::ElementsAre;
+
+namespace {
+class ProcessASTAction : public clang::ASTFrontendAction {
+public:
+ ProcessASTAction(llvm::unique_function<void(clang::ASTContext &)> Process)
+ : Process(std::move(Process)) {
+ assert(this->Process);
+ }
+
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ class Consumer : public ASTConsumer {
+ public:
+ Consumer(llvm::function_ref<void(ASTContext &CTx)> Process)
+ : Process(Process) {}
+
+ void HandleTranslationUnit(ASTContext &Ctx) override { Process(Ctx); }
+
+ private:
+ llvm::function_ref<void(ASTContext &CTx)> Process;
+ };
+
+ return llvm::make_unique<Consumer>(Process);
+ }
+
+private:
+ llvm::unique_function<void(clang::ASTContext &)> Process;
+};
+
+enum class VisitEvent {
+ StartTraverseFunction,
+ EndTraverseFunction,
+ StartTraverseAttr,
+ EndTraverseAttr
+};
+
+class CollectInterestingEvents
+ : public RecursiveASTVisitor<CollectInterestingEvents> {
+public:
+ bool TraverseFunctionDecl(FunctionDecl *D) {
+ Events.push_back(VisitEvent::StartTraverseFunction);
+ bool Ret = RecursiveASTVisitor::TraverseFunctionDecl(D);
+ Events.push_back(VisitEvent::EndTraverseFunction);
+
+ return Ret;
+ }
+
+ bool TraverseAttr(Attr *A) {
+ Events.push_back(VisitEvent::StartTraverseAttr);
+ bool Ret = RecursiveASTVisitor::TraverseAttr(A);
+ Events.push_back(VisitEvent::EndTraverseAttr);
+
+ return Ret;
+ }
+
+ std::vector<VisitEvent> takeEvents() && { return std::move(Events); }
+
+private:
+ std::vector<VisitEvent> Events;
+};
+
+std::vector<VisitEvent> collectEvents(llvm::StringRef Code) {
+ CollectInterestingEvents Visitor;
+ clang::tooling::runToolOnCode(
+ new ProcessASTAction(
+ [&](clang::ASTContext &Ctx) { Visitor.TraverseAST(Ctx); }),
+ Code);
+ return std::move(Visitor).takeEvents();
+}
+} // namespace
+
+TEST(RecursiveASTVisitorTest, AttributesInsideDecls) {
+ /// Check attributes are traversed inside TraverseFunctionDecl.
+ llvm::StringRef Code = R"cpp(
+__attribute__((annotate("something"))) int foo() { return 10; }
+ )cpp";
+
+ EXPECT_THAT(collectEvents(Code),
+ ElementsAre(VisitEvent::StartTraverseFunction,
+ VisitEvent::StartTraverseAttr,
+ VisitEvent::EndTraverseAttr,
+ VisitEvent::EndTraverseFunction));
+}
More information about the cfe-commits
mailing list