Skip to content

Commit a4bdcda

Browse files
committed
Support Attr in DynTypedNode and ASTMatchers.
Differential Revision: https://reviews.llvm.org/D89743
1 parent 9ed7416 commit a4bdcda

17 files changed

+208
-36
lines changed

clang-tools-extra/clang-change-namespace/ChangeNamespace.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
442442
hasDeclaration(DeclMatcher),
443443
unless(templateSpecializationType()))))),
444444
hasParent(nestedNameSpecifierLoc()),
445-
hasAncestor(isImplicit()),
445+
hasAncestor(decl(isImplicit())),
446446
hasAncestor(UsingShadowDeclInClass),
447447
hasAncestor(functionDecl(isDefaulted())))),
448448
hasAncestor(decl().bind("dc")))
@@ -466,7 +466,7 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
466466
hasAncestor(decl(IsInMovedNs).bind("dc")),
467467
loc(nestedNameSpecifier(
468468
specifiesType(hasDeclaration(DeclMatcher.bind("from_decl"))))),
469-
unless(anyOf(hasAncestor(isImplicit()),
469+
unless(anyOf(hasAncestor(decl(isImplicit())),
470470
hasAncestor(UsingShadowDeclInClass),
471471
hasAncestor(functionDecl(isDefaulted())),
472472
hasAncestor(typeLoc(loc(qualType(hasDeclaration(
@@ -495,7 +495,7 @@ void ChangeNamespaceTool::registerMatchers(ast_matchers::MatchFinder *Finder) {
495495
hasAncestor(cxxRecordDecl()))),
496496
hasParent(namespaceDecl()));
497497
Finder->addMatcher(expr(hasAncestor(decl().bind("dc")), IsInMovedNs,
498-
unless(hasAncestor(isImplicit())),
498+
unless(hasAncestor(decl(isImplicit()))),
499499
anyOf(callExpr(callee(FuncMatcher)).bind("call"),
500500
declRefExpr(to(FuncMatcher.bind("func_decl")))
501501
.bind("func_ref"))),

clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ void ProBoundsConstantArrayIndexCheck::registerPPCallbacks(
3838
void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
3939
// Note: if a struct contains an array member, the compiler-generated
4040
// constructor has an arraySubscriptExpr.
41-
Finder->addMatcher(
42-
arraySubscriptExpr(
43-
hasBase(ignoringImpCasts(hasType(constantArrayType().bind("type")))),
44-
hasIndex(expr().bind("index")), unless(hasAncestor(isImplicit())))
45-
.bind("expr"),
46-
this);
41+
Finder->addMatcher(arraySubscriptExpr(hasBase(ignoringImpCasts(hasType(
42+
constantArrayType().bind("type")))),
43+
hasIndex(expr().bind("index")),
44+
unless(hasAncestor(decl(isImplicit()))))
45+
.bind("expr"),
46+
this);
4747

4848
Finder->addMatcher(
4949
cxxOperatorCallExpr(

clang/docs/LibASTMatchersReference.html

+26-2
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,24 @@ <h2 id="decl-matchers">Node Matchers</h2>
582582
</pre></td></tr>
583583

584584

585+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>&gt;</td><td class="name" onclick="toggle('attr0')"><a name="attr0Anchor">attr</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>&gt;...</td></tr>
586+
<tr><td colspan="4" class="doc" id="attr0"><pre>Matches attributes.
587+
Attributes may be attached with a variety of different syntaxes (including
588+
keywords, C++11 attributes, GNU ``__attribute``` and MSVC `__declspec``,
589+
and ``#pragma``s). They may also be implicit.
590+
591+
Given
592+
struct [[nodiscard]] Foo{};
593+
void bar(int * __attribute__((nonnull)) );
594+
__declspec(noinline) void baz();
595+
596+
#pragma omp declare simd
597+
int min();
598+
attr()
599+
matches "nodiscard", "nonnull", "noinline", and the whole "#pragma" line.
600+
</pre></td></tr>
601+
602+
585603
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;</td><td class="name" onclick="toggle('cxxCtorInitializer0')"><a name="cxxCtorInitializer0Anchor">cxxCtorInitializer</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>&gt;...</td></tr>
586604
<tr><td colspan="4" class="doc" id="cxxCtorInitializer0"><pre>Matches constructor initializers.
587605

@@ -2744,6 +2762,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
27442762
</pre></td></tr>
27452763

27462764

2765+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Attr.html">Attr</a>&gt;</td><td class="name" onclick="toggle('isImplicit1')"><a name="isImplicit1Anchor">isImplicit</a></td><td></td></tr>
2766+
<tr><td colspan="4" class="doc" id="isImplicit1"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
2767+
implicit default/copy constructors).
2768+
</pre></td></tr>
2769+
2770+
27472771
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('hasAnyOperatorName0')"><a name="hasAnyOperatorName0Anchor">hasAnyOperatorName</a></td><td>StringRef, ..., StringRef</td></tr>
27482772
<tr><td colspan="4" class="doc" id="hasAnyOperatorName0"><pre>Matches operator expressions (binary or unary) that have any of the
27492773
specified names.
@@ -3808,8 +3832,8 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
38083832

38093833

38103834
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
3811-
<tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches a declaration that has been implicitly added
3812-
by the compiler (eg. implicit default/copy constructors).
3835+
<tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches an entity that has been implicitly added by the compiler (e.g.
3836+
implicit default/copy constructors).
38133837
</pre></td></tr>
38143838

38153839

clang/include/clang/AST/ASTFwd.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ class OMPClause;
3030
#define GEN_CLANG_CLAUSE_CLASS
3131
#define CLAUSE_CLASS(Enum, Str, Class) class Class;
3232
#include "llvm/Frontend/OpenMP/OMP.inc"
33+
class Attr;
34+
#define ATTR(A) class A##Attr;
35+
#include "clang/Basic/AttrList.inc"
3336

3437
} // end namespace clang
3538

clang/include/clang/AST/ASTTypeTraits.h

+13-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525
#include "llvm/Support/AlignOf.h"
2626

2727
namespace llvm {
28-
2928
class raw_ostream;
30-
31-
}
29+
} // namespace llvm
3230

3331
namespace clang {
3432

@@ -66,6 +64,7 @@ class ASTNodeKind {
6664
static ASTNodeKind getFromNode(const Stmt &S);
6765
static ASTNodeKind getFromNode(const Type &T);
6866
static ASTNodeKind getFromNode(const OMPClause &C);
67+
static ASTNodeKind getFromNode(const Attr &A);
6968
/// \}
7069

7170
/// Returns \c true if \c this and \c Other represent the same kind.
@@ -152,6 +151,9 @@ class ASTNodeKind {
152151
#define GEN_CLANG_CLAUSE_CLASS
153152
#define CLAUSE_CLASS(Enum, Str, Class) NKI_##Class,
154153
#include "llvm/Frontend/OpenMP/OMP.inc"
154+
NKI_Attr,
155+
#define ATTR(A) NKI_##A##Attr,
156+
#include "clang/Basic/AttrList.inc"
155157
NKI_NumberOfKinds
156158
};
157159

@@ -201,6 +203,7 @@ KIND_TO_KIND_ID(Decl)
201203
KIND_TO_KIND_ID(Stmt)
202204
KIND_TO_KIND_ID(Type)
203205
KIND_TO_KIND_ID(OMPClause)
206+
KIND_TO_KIND_ID(Attr)
204207
KIND_TO_KIND_ID(CXXBaseSpecifier)
205208
#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
206209
#include "clang/AST/DeclNodes.inc"
@@ -211,6 +214,8 @@ KIND_TO_KIND_ID(CXXBaseSpecifier)
211214
#define GEN_CLANG_CLAUSE_CLASS
212215
#define CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class)
213216
#include "llvm/Frontend/OpenMP/OMP.inc"
217+
#define ATTR(A) KIND_TO_KIND_ID(A##Attr)
218+
#include "clang/Basic/AttrList.inc"
214219
#undef KIND_TO_KIND_ID
215220

216221
inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
@@ -486,6 +491,11 @@ struct DynTypedNode::BaseConverter<
486491
T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>>
487492
: public DynCastPtrConverter<T, OMPClause> {};
488493

494+
template <typename T>
495+
struct DynTypedNode::BaseConverter<
496+
T, std::enable_if_t<std::is_base_of<Attr, T>::value>>
497+
: public DynCastPtrConverter<T, Attr> {};
498+
489499
template <>
490500
struct DynTypedNode::BaseConverter<
491501
NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};

clang/include/clang/ASTMatchers/ASTMatchFinder.h

+2
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class MatchFinder {
167167
MatchCallback *Action);
168168
void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
169169
MatchCallback *Action);
170+
void addMatcher(const AttrMatcher &NodeMatch, MatchCallback *Action);
170171
/// @}
171172

172173
/// Adds a matcher to execute when running over the AST.
@@ -219,6 +220,7 @@ class MatchFinder {
219220
std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
220221
std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
221222
TemplateArgumentLoc;
223+
std::vector<std::pair<AttrMatcher, MatchCallback *>> Attr;
222224
/// All the callbacks in one container to simplify iteration.
223225
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
224226
};

clang/include/clang/ASTMatchers/ASTMatchers.h

+27-7
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ using CXXBaseSpecifierMatcher = internal::Matcher<CXXBaseSpecifier>;
148148
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
149149
using TemplateArgumentMatcher = internal::Matcher<TemplateArgument>;
150150
using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>;
151+
using AttrMatcher = internal::Matcher<Attr>;
151152
/// @}
152153

153154
/// Matches any node.
@@ -752,9 +753,10 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate,
752753
InnerMatcher.matches(*Decl, Finder, Builder));
753754
}
754755

755-
/// Matches a declaration that has been implicitly added
756-
/// by the compiler (eg. implicit default/copy constructors).
757-
AST_MATCHER(Decl, isImplicit) {
756+
/// Matches an entity that has been implicitly added by the compiler (e.g.
757+
/// implicit default/copy constructors).
758+
AST_POLYMORPHIC_MATCHER(isImplicit,
759+
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Attr)) {
758760
return Node.isImplicit();
759761
}
760762

@@ -3489,8 +3491,8 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) {
34893491
/// Usable as: Any Matcher
34903492
extern const internal::ArgumentAdaptingMatcherFunc<
34913493
internal::HasParentMatcher,
3492-
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
3493-
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
3494+
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc, Attr>,
3495+
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc, Attr>>
34943496
hasParent;
34953497

34963498
/// Matches AST nodes that have an ancestor that matches the provided
@@ -3506,8 +3508,8 @@ extern const internal::ArgumentAdaptingMatcherFunc<
35063508
/// Usable as: Any Matcher
35073509
extern const internal::ArgumentAdaptingMatcherFunc<
35083510
internal::HasAncestorMatcher,
3509-
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>,
3510-
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>>
3511+
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc, Attr>,
3512+
internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc, Attr>>
35113513
hasAncestor;
35123514

35133515
/// Matches if the provided matcher does not match.
@@ -7133,6 +7135,24 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
71337135
return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder);
71347136
}
71357137

7138+
/// Matches attributes.
7139+
/// Attributes may be attached with a variety of different syntaxes (including
7140+
/// keywords, C++11 attributes, GNU ``__attribute``` and MSVC `__declspec``,
7141+
/// and ``#pragma``s). They may also be implicit.
7142+
///
7143+
/// Given
7144+
/// \code
7145+
/// struct [[nodiscard]] Foo{};
7146+
/// void bar(int * __attribute__((nonnull)) );
7147+
/// __declspec(noinline) void baz();
7148+
///
7149+
/// #pragma omp declare simd
7150+
/// int min();
7151+
/// \endcode
7152+
/// attr()
7153+
/// matches "nodiscard", "nonnull", "noinline", and the whole "#pragma" line.
7154+
extern const internal::VariadicAllOfMatcher<Attr> attr;
7155+
71367156
/// Overloads for the \c equalsNode matcher.
71377157
/// FIXME: Implement for other node types.
71387158
/// @{

clang/include/clang/ASTMatchers/ASTMatchersInternal.h

+11-7
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,8 @@ class ASTMatchFinder {
757757
std::is_base_of<NestedNameSpecifier, T>::value ||
758758
std::is_base_of<NestedNameSpecifierLoc, T>::value ||
759759
std::is_base_of<TypeLoc, T>::value ||
760-
std::is_base_of<QualType, T>::value,
760+
std::is_base_of<QualType, T>::value ||
761+
std::is_base_of<Attr, T>::value,
761762
"unsupported type for recursive matching");
762763
return matchesChildOf(DynTypedNode::create(Node), getASTContext(), Matcher,
763764
Builder, Bind);
@@ -771,7 +772,8 @@ class ASTMatchFinder {
771772
std::is_base_of<NestedNameSpecifier, T>::value ||
772773
std::is_base_of<NestedNameSpecifierLoc, T>::value ||
773774
std::is_base_of<TypeLoc, T>::value ||
774-
std::is_base_of<QualType, T>::value,
775+
std::is_base_of<QualType, T>::value ||
776+
std::is_base_of<Attr, T>::value,
775777
"unsupported type for recursive matching");
776778
return matchesDescendantOf(DynTypedNode::create(Node), getASTContext(),
777779
Matcher, Builder, Bind);
@@ -785,7 +787,8 @@ class ASTMatchFinder {
785787
static_assert(std::is_base_of<Decl, T>::value ||
786788
std::is_base_of<NestedNameSpecifierLoc, T>::value ||
787789
std::is_base_of<Stmt, T>::value ||
788-
std::is_base_of<TypeLoc, T>::value,
790+
std::is_base_of<TypeLoc, T>::value ||
791+
std::is_base_of<Attr, T>::value,
789792
"type not allowed for recursive matching");
790793
return matchesAncestorOf(DynTypedNode::create(Node), getASTContext(),
791794
Matcher, Builder, MatchMode);
@@ -954,7 +957,7 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
954957

955958
bool matchesNode(const NamedDecl &Node) const override;
956959

957-
private:
960+
private:
958961
/// Unqualified match routine.
959962
///
960963
/// It is much faster than the full match, but it only works for unqualified
@@ -1175,7 +1178,8 @@ struct IsBaseType {
11751178
std::is_same<T, NestedNameSpecifier>::value ||
11761179
std::is_same<T, NestedNameSpecifierLoc>::value ||
11771180
std::is_same<T, CXXCtorInitializer>::value ||
1178-
std::is_same<T, TemplateArgumentLoc>::value;
1181+
std::is_same<T, TemplateArgumentLoc>::value ||
1182+
std::is_same<T, Attr>::value;
11791183
};
11801184
template <typename T>
11811185
const bool IsBaseType<T>::value;
@@ -1185,7 +1189,7 @@ const bool IsBaseType<T>::value;
11851189
/// Useful for matchers like \c anything and \c unless.
11861190
using AllNodeBaseTypes =
11871191
TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType,
1188-
Type, TypeLoc, CXXCtorInitializer>;
1192+
Type, TypeLoc, CXXCtorInitializer, Attr>;
11891193

11901194
/// Helper meta-function to extract the argument out of a function of
11911195
/// type void(Arg).
@@ -1212,7 +1216,7 @@ template <class T, class Tuple> constexpr T *new_from_tuple(Tuple &&t) {
12121216
using AdaptativeDefaultFromTypes = AllNodeBaseTypes;
12131217
using AdaptativeDefaultToTypes =
12141218
TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc,
1215-
QualType>;
1219+
QualType, Attr>;
12161220

12171221
/// All types that are supported by HasDeclarationMatcher above.
12181222
using HasDeclarationSupportedTypes =

clang/lib/AST/ASTTypeTraits.cpp

+19-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "clang/AST/ASTTypeTraits.h"
1616
#include "clang/AST/ASTContext.h"
17+
#include "clang/AST/Attr.h"
1718
#include "clang/AST/DeclCXX.h"
1819
#include "clang/AST/NestedNameSpecifier.h"
1920
#include "clang/AST/OpenMPClause.h"
@@ -44,6 +45,9 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
4445
#define GEN_CLANG_CLAUSE_CLASS
4546
#define CLAUSE_CLASS(Enum, Str, Class) {NKI_OMPClause, #Class},
4647
#include "llvm/Frontend/OpenMP/OMP.inc"
48+
{NKI_None, "Attr"},
49+
#define ATTR(A) {NKI_Attr, #A "Attr"},
50+
#include "clang/Basic/AttrList.inc"
4751
};
4852

4953
bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const {
@@ -134,7 +138,17 @@ ASTNodeKind ASTNodeKind::getFromNode(const OMPClause &C) {
134138
llvm_unreachable("unexpected OpenMP clause kind");
135139
#include "llvm/Frontend/OpenMP/OMP.inc"
136140
}
137-
llvm_unreachable("invalid stmt kind");
141+
llvm_unreachable("invalid omp clause kind");
142+
}
143+
144+
ASTNodeKind ASTNodeKind::getFromNode(const Attr &A) {
145+
switch (A.getKind()) {
146+
#define ATTR(A) \
147+
case attr::A: \
148+
return ASTNodeKind(NKI_##A##Attr);
149+
#include "clang/Basic/AttrList.inc"
150+
}
151+
llvm_unreachable("invalid attr kind");
138152
}
139153

140154
void DynTypedNode::print(llvm::raw_ostream &OS,
@@ -162,6 +176,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
162176
S->printPretty(OS, nullptr, PP);
163177
else if (const Type *T = get<Type>())
164178
QualType(T, 0).print(OS, PP);
179+
else if (const Attr *A = get<Attr>())
180+
A->printPretty(OS, PP);
165181
else
166182
OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n";
167183
}
@@ -195,5 +211,7 @@ SourceRange DynTypedNode::getSourceRange() const {
195211
return SourceRange(C->getBeginLoc(), C->getEndLoc());
196212
if (const auto *CBS = get<CXXBaseSpecifier>())
197213
return CBS->getSourceRange();
214+
if (const auto *A = get<Attr>())
215+
return A->getRange();
198216
return SourceRange();
199217
}

clang/lib/AST/ParentMapContext.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,11 @@ class ParentMapContext::ParentMap::ASTVisitor
429429
[&] { return VisitorBase::TraverseNestedNameSpecifierLoc(NNSLocNode); },
430430
&Map.OtherParents);
431431
}
432+
bool TraverseAttr(Attr *AttrNode) {
433+
return TraverseNode(
434+
AttrNode, AttrNode, [&] { return VisitorBase::TraverseAttr(AttrNode); },
435+
&Map.PointerParents);
436+
}
432437

433438
// Using generic TraverseNode for Stmt would prevent data-recursion.
434439
bool dataTraverseStmtPre(Stmt *StmtNode) {

0 commit comments

Comments
 (0)