steveire updated this revision to Diff 267750.
steveire added a comment.
Update
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D80961/new/
https://reviews.llvm.org/D80961
Files:
clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
clang/include/clang/AST/ASTNodeTraverser.h
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/lib/AST/ASTDumper.cpp
clang/lib/ASTMatchers/ASTMatchFinder.cpp
clang/lib/ASTMatchers/ASTMatchersInternal.cpp
clang/unittests/AST/ASTTraverserTest.cpp
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
clang/unittests/Tooling/TransformerTest.cpp
Index: clang/unittests/Tooling/TransformerTest.cpp
===================================================================
--- clang/unittests/Tooling/TransformerTest.cpp
+++ clang/unittests/Tooling/TransformerTest.cpp
@@ -695,6 +695,70 @@
EXPECT_EQ(ErrorCount, 0);
}
+TEST_F(TransformerTest, TemplateInstantiation) {
+
+ std::string NonTemplatesInput = R"cpp(
+struct S {
+ int m_i;
+};
+)cpp";
+ std::string NonTemplatesExpected = R"cpp(
+struct S {
+ safe_int m_i;
+};
+)cpp";
+
+ std::string TemplatesInput = R"cpp(
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+)cpp";
+
+ auto MatchedField = fieldDecl(hasType(asString("int"))).bind("theField");
+
+ // Changes the 'int' in 'S', but not the 'T' in 'TemplStruct':
+ testRule(makeRule(traverse(TK_IgnoreUnlessSpelledInSource, MatchedField),
+ changeTo(cat("safe_int ", name("theField")))),
+ NonTemplatesInput + TemplatesInput,
+ NonTemplatesExpected + TemplatesInput);
+
+ // In AsIs mode, template instantiations are modified, which is
+ // often not desired:
+
+ std::string IncorrectTemplatesExpected = R"cpp(
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ safe_int m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+)cpp";
+
+ // Changes the 'int' in 'S', and (incorrectly) the 'T' in 'TemplStruct':
+ testRule(makeRule(traverse(TK_AsIs, MatchedField),
+ changeTo(cat("safe_int ", name("theField")))),
+
+ NonTemplatesInput + TemplatesInput,
+ NonTemplatesExpected + IncorrectTemplatesExpected);
+}
+
// Transformation of macro source text when the change encompasses the entirety
// of the expanded text.
TEST_F(TransformerTest, SimpleMacro) {
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1890,7 +1890,60 @@
substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
- staticAssertDecl(has(integerLiteral())))));
+ staticAssertDecl(has(declRefExpr())))));
+
+ Code = R"cpp(
+
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+template<typename T>
+T timesTwo(T input)
+{
+ return input * 2;
+}
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+ TemplStruct<double> td;
+ (void)timesTwo<int>(2);
+ (void)timesTwo<double>(2);
+}
+
+)cpp";
+ {
+ auto M = cxxRecordDecl(hasName("TemplStruct"),
+ has(fieldDecl(hasType(asString("int")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M = cxxRecordDecl(hasName("TemplStruct"),
+ has(fieldDecl(hasType(asString("double")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M =
+ functionDecl(hasName("timesTwo"),
+ hasParameter(0, parmVarDecl(hasType(asString("int")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
+ {
+ auto M =
+ functionDecl(hasName("timesTwo"),
+ hasParameter(0, parmVarDecl(hasType(asString("double")))));
+ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
+ EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
+ }
}
template <typename MatcherT>
@@ -3337,24 +3390,24 @@
StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));
EXPECT_TRUE(matches(R"(
- void* operator new(decltype(sizeof(void*)), void*);
+ void* operator new(decltype(sizeof(void*)), void*);
int *foo(void* Storage) {
- return new (Storage) int;
+ return new (Storage) int;
})",
IsPlacementNew));
EXPECT_TRUE(matches(R"(
- void* operator new(decltype(sizeof(void*)), void*, unsigned);
+ void* operator new(decltype(sizeof(void*)), void*, unsigned);
int *foo(void* Storage) {
- return new (Storage, 16) int;
+ return new (Storage, 16) int;
})",
cxxNewExpr(hasPlacementArg(
1, ignoringImpCasts(integerLiteral(equals(16)))))));
EXPECT_TRUE(notMatches(R"(
- void* operator new(decltype(sizeof(void*)), void*);
+ void* operator new(decltype(sizeof(void*)), void*);
int *foo(void* Storage) {
- return new int;
+ return new int;
})",
IsPlacementNew));
}
Index: clang/unittests/AST/ASTTraverserTest.cpp
===================================================================
--- clang/unittests/AST/ASTTraverserTest.cpp
+++ clang/unittests/AST/ASTTraverserTest.cpp
@@ -68,6 +68,14 @@
void Visit(const TemplateArgument &A, SourceRange R = {},
const Decl *From = nullptr, const char *Label = nullptr) {
OS << "TemplateArgument";
+ switch (A.getKind()) {
+ case TemplateArgument::Type: {
+ OS << " type " << A.getAsType().getAsString();
+ break;
+ }
+ default:
+ break;
+ }
}
template <typename... T> void Visit(T...) {}
@@ -420,8 +428,9 @@
{
auto FN = ast_matchers::match(
- functionDecl(hasName("template_test"),
- hasDescendant(staticAssertDecl().bind("staticAssert"))),
+ traverse(TK_AsIs, functionDecl(hasName("template_test"),
+ hasDescendant(staticAssertDecl().bind(
+ "staticAssert")))),
AST->getASTContext());
EXPECT_EQ(FN.size(), 2u);
@@ -873,4 +882,141 @@
}
}
+TEST(Traverse, IgnoreUnlessSpelledInSourceTemplateInstantiations) {
+
+ auto AST = buildASTFromCode(R"cpp(
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+template<typename T>
+T timesTwo(T input)
+{
+ return input * 2;
+}
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+ TemplStruct<double> td;
+ (void)timesTwo<int>(2);
+ (void)timesTwo<double>(2);
+}
+)cpp");
+ {
+ auto BN = ast_matchers::match(
+ classTemplateDecl(hasName("TemplStruct")).bind("rec"),
+ AST->getASTContext());
+ EXPECT_EQ(BN.size(), 1u);
+
+ EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+ BN[0].getNodeAs<Decl>("rec")),
+ R"cpp(
+ClassTemplateDecl 'TemplStruct'
+|-TemplateTypeParmDecl 'T'
+`-CXXRecordDecl 'TemplStruct'
+ |-CXXRecordDecl 'TemplStruct'
+ |-CXXConstructorDecl 'TemplStruct<T>'
+ | `-CompoundStmt
+ |-CXXDestructorDecl '~TemplStruct<T>'
+ | `-CompoundStmt
+ |-AccessSpecDecl
+ `-FieldDecl 'm_t'
+)cpp");
+
+ EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("rec")),
+ R"cpp(
+ClassTemplateDecl 'TemplStruct'
+|-TemplateTypeParmDecl 'T'
+|-CXXRecordDecl 'TemplStruct'
+| |-CXXRecordDecl 'TemplStruct'
+| |-CXXConstructorDecl 'TemplStruct<T>'
+| | `-CompoundStmt
+| |-CXXDestructorDecl '~TemplStruct<T>'
+| | `-CompoundStmt
+| |-AccessSpecDecl
+| `-FieldDecl 'm_t'
+|-ClassTemplateSpecializationDecl 'TemplStruct'
+| |-TemplateArgument type int
+| |-CXXRecordDecl 'TemplStruct'
+| |-CXXConstructorDecl 'TemplStruct'
+| | `-CompoundStmt
+| |-CXXDestructorDecl '~TemplStruct'
+| | `-CompoundStmt
+| |-AccessSpecDecl
+| |-FieldDecl 'm_t'
+| `-CXXConstructorDecl 'TemplStruct'
+| `-ParmVarDecl ''
+`-ClassTemplateSpecializationDecl 'TemplStruct'
+ |-TemplateArgument type double
+ |-CXXRecordDecl 'TemplStruct'
+ |-CXXConstructorDecl 'TemplStruct'
+ | `-CompoundStmt
+ |-CXXDestructorDecl '~TemplStruct'
+ | `-CompoundStmt
+ |-AccessSpecDecl
+ |-FieldDecl 'm_t'
+ `-CXXConstructorDecl 'TemplStruct'
+ `-ParmVarDecl ''
+)cpp");
+ }
+ {
+ auto BN = ast_matchers::match(
+ functionTemplateDecl(hasName("timesTwo")).bind("fn"),
+ AST->getASTContext());
+ EXPECT_EQ(BN.size(), 1u);
+
+ EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource,
+ BN[0].getNodeAs<Decl>("fn")),
+ R"cpp(
+FunctionTemplateDecl 'timesTwo'
+|-TemplateTypeParmDecl 'T'
+`-FunctionDecl 'timesTwo'
+ |-ParmVarDecl 'input'
+ `-CompoundStmt
+ `-ReturnStmt
+ `-BinaryOperator
+ |-DeclRefExpr 'input'
+ `-IntegerLiteral
+)cpp");
+
+ EXPECT_EQ(dumpASTString(TK_AsIs, BN[0].getNodeAs<Decl>("fn")),
+ R"cpp(
+FunctionTemplateDecl 'timesTwo'
+|-TemplateTypeParmDecl 'T'
+|-FunctionDecl 'timesTwo'
+| |-ParmVarDecl 'input'
+| `-CompoundStmt
+| `-ReturnStmt
+| `-BinaryOperator
+| |-DeclRefExpr 'input'
+| `-IntegerLiteral
+|-FunctionDecl 'timesTwo'
+| |-TemplateArgument type int
+| |-ParmVarDecl 'input'
+| `-CompoundStmt
+| `-ReturnStmt
+| `-BinaryOperator
+| |-ImplicitCastExpr
+| | `-DeclRefExpr 'input'
+| `-IntegerLiteral
+`-FunctionDecl 'timesTwo'
+ |-TemplateArgument type double
+ |-ParmVarDecl 'input'
+ `-CompoundStmt
+ `-ReturnStmt
+ `-BinaryOperator
+ |-ImplicitCastExpr
+ | `-DeclRefExpr 'input'
+ `-ImplicitCastExpr
+ `-IntegerLiteral
+)cpp");
+ }
+}
+
} // namespace clang
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -282,6 +282,13 @@
TraversalKindScope RAII(Finder->getASTContext(),
Implementation->TraversalKind());
+ if (Finder->getASTContext().getParentMapContext().getTraversalKind() ==
+ TK_IgnoreUnlessSpelledInSource) {
+ if (Finder->isMatchingInImplicitTemplateInstantiation()) {
+ return false;
+ }
+ }
+
auto N =
Finder->getASTContext().getParentMapContext().traverseIgnored(DynNode);
Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -561,6 +561,114 @@
bool shouldVisitTemplateInstantiations() const { return true; }
bool shouldVisitImplicitCode() const { return true; }
+ bool m_traversingImplicitTemplateInstantiation = false;
+
+ bool isMatchingInImplicitTemplateInstantiation() const override {
+ return m_traversingImplicitTemplateInstantiation;
+ }
+
+ struct ImplicitTemplateInstantiationScope {
+ ImplicitTemplateInstantiationScope(MatchASTVisitor *V, bool b) : m_V(V) {
+ m_B = V->m_traversingImplicitTemplateInstantiation;
+ V->m_traversingImplicitTemplateInstantiation = b;
+ }
+ ~ImplicitTemplateInstantiationScope() {
+ m_V->m_traversingImplicitTemplateInstantiation = m_B;
+ }
+
+ private:
+ MatchASTVisitor *m_V;
+ bool m_B;
+ };
+
+#define TRY_TO(CALL_EXPR) \
+ do { \
+ if (!getDerived().CALL_EXPR) \
+ return false; \
+ } while (false)
+
+ bool TraverseTemplateInstantiations(ClassTemplateDecl *D) {
+ for (auto *SD : D->specializations()) {
+ for (auto *RD : SD->redecls()) {
+ // We don't want to visit injected-class-names in this traversal.
+ if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+ continue;
+
+ switch (cast<ClassTemplateSpecializationDecl>(RD)
+ ->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation: {
+ ImplicitTemplateInstantiationScope RAII(this, true);
+ TRY_TO(TraverseDecl(RD));
+ break;
+ }
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool TraverseTemplateInstantiations(VarTemplateDecl *D) {
+ for (auto *SD : D->specializations()) {
+ for (auto *RD : SD->redecls()) {
+ switch (
+ cast<VarTemplateSpecializationDecl>(RD)->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation: {
+ ImplicitTemplateInstantiationScope RAII(this, true);
+ TRY_TO(TraverseDecl(RD));
+ break;
+ }
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool TraverseTemplateInstantiations(FunctionTemplateDecl *D) {
+ for (auto *FD : D->specializations()) {
+ for (auto *RD : FD->redecls()) {
+ switch (RD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation: {
+ // We don't know what kind of FunctionDecl this is.
+ ImplicitTemplateInstantiationScope RAII(this, true);
+ TRY_TO(TraverseDecl(RD));
+ break;
+ }
+
+ // FIXME: For now traverse explicit instantiations here. Change that
+ // once they are represented as dedicated nodes in the AST.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ TRY_TO(TraverseDecl(RD));
+ break;
+
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+
private:
class TimeBucketRegion {
public:
Index: clang/lib/AST/ASTDumper.cpp
===================================================================
--- clang/lib/AST/ASTDumper.cpp
+++ clang/lib/AST/ASTDumper.cpp
@@ -129,9 +129,10 @@
Visit(D->getTemplatedDecl());
- for (const auto *Child : D->specializations())
- dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
- !D->isCanonicalDecl());
+ if (GetTraversalKind() == TK_AsIs)
+ for (const auto *Child : D->specializations())
+ dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
+ !D->isCanonicalDecl());
}
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1056,6 +1056,8 @@
virtual ASTContext &getASTContext() const = 0;
+ virtual bool isMatchingInImplicitTemplateInstantiation() const = 0;
+
protected:
virtual bool matchesChildOf(const DynTypedNode &Node, ASTContext &Ctx,
const DynTypedMatcher &Matcher,
Index: clang/include/clang/AST/ASTNodeTraverser.h
===================================================================
--- clang/include/clang/AST/ASTNodeTraverser.h
+++ clang/include/clang/AST/ASTNodeTraverser.h
@@ -78,6 +78,7 @@
bool getDeserialize() const { return Deserialize; }
void SetTraversalKind(TraversalKind TK) { Traversal = TK; }
+ TraversalKind GetTraversalKind() const { return Traversal; }
void Visit(const Decl *D) {
getNodeDelegate().AddChild([=] {
@@ -475,8 +476,9 @@
Visit(D->getTemplatedDecl());
- for (const auto *Child : D->specializations())
- dumpTemplateDeclSpecialization(Child);
+ if (Traversal == TK_AsIs)
+ for (const auto *Child : D->specializations())
+ dumpTemplateDeclSpecialization(Child);
}
void VisitTypeAliasDecl(const TypeAliasDecl *D) {
Index: clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
+++ clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp
@@ -28,11 +28,12 @@
void TemporaryObjectsCheck::registerMatchers(MatchFinder *Finder) {
// Matcher for default constructors.
- Finder->addMatcher(
- cxxTemporaryObjectExpr(hasDeclaration(cxxConstructorDecl(hasParent(
- cxxRecordDecl(matchesAnyName(Names))))))
- .bind("temps"),
- this);
+ Finder->addMatcher(traverse(ast_type_traits::TK_AsIs,
+ cxxTemporaryObjectExpr(
+ hasDeclaration(cxxConstructorDecl(hasParent(
+ cxxRecordDecl(matchesAnyName(Names))))))
+ .bind("temps")),
+ this);
// Matcher for user-defined constructors.
Finder->addMatcher(
Index: clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -39,8 +39,7 @@
void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
- varDecl(hasStaticStorageDuration()))),
- unless(isInTemplateInstantiation()))
+ varDecl(hasStaticStorageDuration()))))
.bind("memberExpression"),
this);
}
Index: clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
@@ -127,30 +127,35 @@
auto IsBoundToType = refersToType(equalsBoundNode("type"));
Finder->addMatcher(
- ExplicitSingleVarDecl(hasType(autoType(hasDeducedType(
+ traverse(TK_AsIs, ExplicitSingleVarDecl(
+ hasType(autoType(hasDeducedType(
pointerType(pointee(unless(functionType())))))),
- "auto"),
+ "auto")),
this);
Finder->addMatcher(
- ExplicitSingleVarDeclInTemplate(
- allOf(hasType(autoType(hasDeducedType(pointerType(
- pointee(hasUnqualifiedType(qualType().bind("type")),
- unless(functionType())))))),
- anyOf(hasAncestor(
- functionDecl(hasAnyTemplateArgument(IsBoundToType))),
- hasAncestor(classTemplateSpecializationDecl(
- hasAnyTemplateArgument(IsBoundToType))))),
- "auto"),
+ traverse(TK_AsIs,
+ ExplicitSingleVarDeclInTemplate(
+ allOf(hasType(autoType(hasDeducedType(pointerType(pointee(
+ hasUnqualifiedType(qualType().bind("type")),
+ unless(functionType())))))),
+ anyOf(hasAncestor(functionDecl(
+ hasAnyTemplateArgument(IsBoundToType))),
+ hasAncestor(classTemplateSpecializationDecl(
+ hasAnyTemplateArgument(IsBoundToType))))),
+ "auto")),
this);
if (!AddConstToQualified)
return;
- Finder->addMatcher(ExplicitSingleVarDecl(
- hasType(pointerType(pointee(autoType()))), "auto_ptr"),
- this);
Finder->addMatcher(
- ExplicitSingleVarDecl(hasType(lValueReferenceType(pointee(autoType()))),
- "auto_ref"),
+ traverse(TK_AsIs,
+ ExplicitSingleVarDecl(hasType(pointerType(pointee(autoType()))),
+ "auto_ptr")),
+ this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, ExplicitSingleVarDecl(
+ hasType(lValueReferenceType(pointee(autoType()))),
+ "auto_ref")),
this);
}
Index: clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -55,13 +55,15 @@
hasParent(explicitCastExpr(hasDestinationType(booleanType())))));
Finder->addMatcher(
- cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer),
- hasType(pointsTo(ValidContainer)),
- hasType(references(ValidContainer))))),
- callee(cxxMethodDecl(hasName("size"))), WrongUse,
- unless(hasAncestor(cxxMethodDecl(
- ofClass(equalsBoundNode("container"))))))
- .bind("SizeCallExpr"),
+ traverse(TK_AsIs,
+ cxxMemberCallExpr(
+ on(expr(anyOf(hasType(ValidContainer),
+ hasType(pointsTo(ValidContainer)),
+ hasType(references(ValidContainer))))),
+ callee(cxxMethodDecl(hasName("size"))), WrongUse,
+ unless(hasAncestor(
+ cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
+ .bind("SizeCallExpr")),
this);
// Empty constructor matcher.
@@ -86,13 +88,15 @@
expr(hasType(pointsTo(ValidContainer))).bind("Pointee"))),
expr(hasType(ValidContainer)).bind("STLObject"));
Finder->addMatcher(
- cxxOperatorCallExpr(
- hasAnyOverloadedOperatorName("==", "!="),
- anyOf(allOf(hasArgument(0, WrongComparend), hasArgument(1, STLArg)),
- allOf(hasArgument(0, STLArg), hasArgument(1, WrongComparend))),
- unless(hasAncestor(
- cxxMethodDecl(ofClass(equalsBoundNode("container"))))))
- .bind("BinCmp"),
+ traverse(TK_AsIs,
+ cxxOperatorCallExpr(hasAnyOverloadedOperatorName("==", "!="),
+ anyOf(allOf(hasArgument(0, WrongComparend),
+ hasArgument(1, STLArg)),
+ allOf(hasArgument(0, STLArg),
+ hasArgument(1, WrongComparend))),
+ unless(hasAncestor(cxxMethodDecl(
+ ofClass(equalsBoundNode("container"))))))
+ .bind("BinCmp")),
this);
}
Index: clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp
@@ -69,15 +69,17 @@
"find_last_of", "find_last_not_of");
Finder->addMatcher(
- cxxMemberCallExpr(
- callee(functionDecl(StringFindFunctions).bind("func")),
- anyOf(argumentCountIs(1), argumentCountIs(2)),
- hasArgument(0, SingleChar),
- on(expr(
- hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
- recordDecl(hasAnyName(SmallVector<StringRef, 4>(
- StringLikeClasses.begin(), StringLikeClasses.end()))))))),
- unless(hasSubstitutedType())))),
+ traverse(TK_AsIs,
+ cxxMemberCallExpr(
+ callee(functionDecl(StringFindFunctions).bind("func")),
+ anyOf(argumentCountIs(1), argumentCountIs(2)),
+ hasArgument(0, SingleChar),
+ on(expr(hasType(hasUnqualifiedDesugaredType(
+ recordType(hasDeclaration(recordDecl(
+ hasAnyName(SmallVector<StringRef, 4>(
+ StringLikeClasses.begin(),
+ StringLikeClasses.end()))))))),
+ unless(hasSubstitutedType()))))),
this);
}
Index: clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
@@ -21,29 +21,32 @@
// Using declaration: warning and fix-it.
Finder->addMatcher(
- usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
- .bind("using_decl"),
+ traverse(TK_AsIs, usingDecl(hasAnyUsingShadowDecl(
+ hasTargetDecl(hasName(MatchText))))
+ .bind("using_decl")),
this);
// DeclRefExpr: warning, no fix-it.
Finder->addMatcher(
- declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr()))
- .bind("decl_ref_expr"),
+ traverse(TK_AsIs, declRefExpr(to(functionDecl(hasName(MatchText))),
+ unless(callExpr()))
+ .bind("decl_ref_expr")),
this);
auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
// CallExpr: warning, fix-it.
- Finder->addMatcher(callExpr(DirectCallToUncaughtException,
- unless(hasAncestor(initListExpr())))
- .bind("call_expr"),
- this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, callExpr(DirectCallToUncaughtException,
+ unless(hasAncestor(initListExpr())))
+ .bind("call_expr")),
+ this);
// CallExpr in initialisation list: warning, fix-it with avoiding narrowing
// conversions.
- Finder->addMatcher(callExpr(DirectCallToUncaughtException,
- hasAncestor(initListExpr()))
- .bind("init_call_expr"),
+ Finder->addMatcher(traverse(TK_AsIs, callExpr(DirectCallToUncaughtException,
+ hasAncestor(initListExpr()))
+ .bind("init_call_expr")),
this);
}
Index: clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
@@ -34,10 +34,13 @@
void UseOverrideCheck::registerMatchers(MatchFinder *Finder) {
if (IgnoreDestructors)
Finder->addMatcher(
- cxxMethodDecl(isOverride(), unless(cxxDestructorDecl())).bind("method"),
+ traverse(TK_AsIs,
+ cxxMethodDecl(isOverride(), unless(cxxDestructorDecl()))
+ .bind("method")),
this);
else
- Finder->addMatcher(cxxMethodDecl(isOverride()).bind("method"), this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, cxxMethodDecl(isOverride()).bind("method")), this);
}
// Re-lex the tokens to get precise locations to insert 'override' and remove
Index: clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp
@@ -95,19 +95,23 @@
//
// std::auto_ptr<int> fn(std::auto_ptr<int>);
// ^~~~~~~~~~~~~ ^~~~~~~~~~~~~
- Finder->addMatcher(typeLoc(loc(qualType(AutoPtrType,
- // Skip elaboratedType() as the named
- // type will match soon thereafter.
- unless(elaboratedType()))))
- .bind(AutoPtrTokenId),
- this);
+ Finder->addMatcher(
+ traverse(TK_AsIs,
+ typeLoc(loc(qualType(AutoPtrType,
+ // Skip elaboratedType() as the named
+ // type will match soon thereafter.
+ unless(elaboratedType()))))
+ .bind(AutoPtrTokenId)),
+ this);
// using std::auto_ptr;
// ^~~~~~~~~~~~~~~~~~~
- Finder->addMatcher(usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(
- hasName("auto_ptr"), isFromStdNamespace()))))
- .bind(AutoPtrTokenId),
- this);
+ Finder->addMatcher(
+ traverse(TK_AsIs,
+ usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(namedDecl(
+ hasName("auto_ptr"), isFromStdNamespace()))))
+ .bind(AutoPtrTokenId)),
+ this);
// Find ownership transfers via copy construction and assignment.
// AutoPtrOwnershipTransferId is bound to the part that has to be wrapped
@@ -119,9 +123,10 @@
expr(isLValue(), hasType(AutoPtrType)).bind(AutoPtrOwnershipTransferId);
Finder->addMatcher(
- cxxOperatorCallExpr(hasOverloadedOperatorName("="),
- callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
- hasArgument(1, MovableArgumentMatcher)),
+ traverse(TK_AsIs,
+ cxxOperatorCallExpr(hasOverloadedOperatorName("="),
+ callee(cxxMethodDecl(ofClass(AutoPtrDecl))),
+ hasArgument(1, MovableArgumentMatcher))),
this);
Finder->addMatcher(
traverse(ast_type_traits::TK_AsIs,
Index: clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -114,6 +114,8 @@
// pointer, 'make_smart_ptr' refers to 'std::make_shared' or
// 'std::make_unique' or other function that creates smart_ptr.
+ TraversalKindScope RAII(*Result.Context, TK_AsIs);
+
SourceManager &SM = *Result.SourceManager;
const auto *Construct =
Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
Index: clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp
@@ -34,7 +34,8 @@
auto IoStateType =
qualType(hasDeclaration(IoStateDecl), unless(elaboratedType()));
- Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, typeLoc(loc(IoStateType)).bind("TypeLoc")), this);
}
void DeprecatedIosBaseAliasesCheck::check(
Index: clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ clang-tools-extra/clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -18,23 +18,25 @@
void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- cxxThrowExpr(
- unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))),
- // The thrown value is not derived from 'std::exception'.
- has(expr(unless(
- hasType(qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
- isSameOrDerivedFrom(hasName("::std::exception")))))))))),
- // This condition is always true, but will bind to the
- // template value if the thrown type is templated.
- anyOf(has(expr(
- hasType(substTemplateTypeParmType().bind("templ_type")))),
- anything()),
- // Bind to the declaration of the type of the value that
- // is thrown. 'anything()' is necessary to always succeed
- // in the 'eachOf' because builtin types are not
- // 'namedDecl'.
- eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
- .bind("bad_throw"),
+ traverse(
+ TK_AsIs,
+ cxxThrowExpr(
+ unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))),
+ // The thrown value is not derived from 'std::exception'.
+ has(expr(unless(hasType(
+ qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
+ isSameOrDerivedFrom(hasName("::std::exception")))))))))),
+ // This condition is always true, but will bind to the
+ // template value if the thrown type is templated.
+ anyOf(has(expr(hasType(
+ substTemplateTypeParmType().bind("templ_type")))),
+ anything()),
+ // Bind to the declaration of the type of the value that
+ // is thrown. 'anything()' is necessary to always succeed
+ // in the 'eachOf' because builtin types are not
+ // 'namedDecl'.
+ eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
+ .bind("bad_throw")),
this);
}
Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
+++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp
@@ -168,10 +168,11 @@
.bind("class")))))
.bind("method");
- Finder->addMatcher(expr(anyOf(callExpr(callee(Methods)).bind("call"),
- declRefExpr(to(Methods)).bind("ref")),
- LocationFilter),
- this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, expr(anyOf(callExpr(callee(Methods)).bind("call"),
+ declRefExpr(to(Methods)).bind("ref")),
+ LocationFilter)),
+ this);
Finder->addMatcher(
usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(Methods)), LocationFilter)
Index: clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp
@@ -216,11 +216,13 @@
void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- cxxMethodDecl(
- unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
- cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
- isOverloadedOperator())))
- .bind("method"),
+ traverse(
+ TK_AsIs,
+ cxxMethodDecl(
+ unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
+ cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
+ isOverloadedOperator())))
+ .bind("method")),
this);
}
Index: clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.cpp
@@ -30,18 +30,20 @@
// Check whether destination object is not TriviallyCopyable.
// Applicable to all three memory manipulation functions.
- Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
- "::memset", "::memcpy", "::memmove"))),
- hasArgument(0, NotTriviallyCopyableObject))
- .bind("dest"),
- this);
+ Finder->addMatcher(
+ traverse(TK_AsIs, callExpr(callee(functionDecl(hasAnyName(
+ "::memset", "::memcpy", "::memmove"))),
+ hasArgument(0, NotTriviallyCopyableObject))
+ .bind("dest")),
+ this);
// Check whether source object is not TriviallyCopyable.
// Only applicable to memcpy() and memmove().
Finder->addMatcher(
- callExpr(callee(functionDecl(hasAnyName("::memcpy", "::memmove"))),
- hasArgument(1, NotTriviallyCopyableObject))
- .bind("src"),
+ traverse(TK_AsIs, callExpr(callee(functionDecl(
+ hasAnyName("::memcpy", "::memmove"))),
+ hasArgument(1, NotTriviallyCopyableObject))
+ .bind("src")),
this);
}
Index: clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp
@@ -79,20 +79,22 @@
expr(ignoringParenImpCasts(hasType(isInteger()))).bind(LoopIncrementName);
Finder->addMatcher(
- forStmt(
- hasCondition(anyOf(
- binaryOperator(hasOperatorName("<"),
- hasLHS(LoopVarConversionMatcher),
- hasRHS(LoopBoundMatcher)),
- binaryOperator(hasOperatorName("<="),
- hasLHS(LoopVarConversionMatcher),
- hasRHS(LoopBoundMatcher)),
- binaryOperator(hasOperatorName(">"), hasLHS(LoopBoundMatcher),
- hasRHS(LoopVarConversionMatcher)),
- binaryOperator(hasOperatorName(">="), hasLHS(LoopBoundMatcher),
- hasRHS(LoopVarConversionMatcher)))),
- hasIncrement(IncrementMatcher))
- .bind(LoopName),
+ traverse(TK_AsIs,
+ forStmt(hasCondition(anyOf(
+ binaryOperator(hasOperatorName("<"),
+ hasLHS(LoopVarConversionMatcher),
+ hasRHS(LoopBoundMatcher)),
+ binaryOperator(hasOperatorName("<="),
+ hasLHS(LoopVarConversionMatcher),
+ hasRHS(LoopBoundMatcher)),
+ binaryOperator(hasOperatorName(">"),
+ hasLHS(LoopBoundMatcher),
+ hasRHS(LoopVarConversionMatcher)),
+ binaryOperator(hasOperatorName(">="),
+ hasLHS(LoopBoundMatcher),
+ hasRHS(LoopVarConversionMatcher)))),
+ hasIncrement(IncrementMatcher))
+ .bind(LoopName)),
this);
}
Index: clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
@@ -97,9 +97,10 @@
// the sizeof size_t.
if (WarnOnSizeOfConstant) {
Finder->addMatcher(
- expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
- unless(SizeOfZero))
- .bind("sizeof-constant"),
+ traverse(TK_AsIs,
+ expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))),
+ unless(SizeOfZero))
+ .bind("sizeof-constant")),
this);
}
@@ -186,14 +187,15 @@
const auto DenomType = qualType(hasCanonicalType(type().bind("denom-type")));
Finder->addMatcher(
- binaryOperator(hasOperatorName("/"),
- hasLHS(expr(ignoringParenImpCasts(
- anyOf(sizeOfExpr(has(NumType)),
- sizeOfExpr(has(expr(hasType(NumType)))))))),
- hasRHS(expr(ignoringParenImpCasts(
- anyOf(sizeOfExpr(has(DenomType)),
- sizeOfExpr(has(expr(hasType(DenomType)))))))))
- .bind("sizeof-divide-expr"),
+ traverse(TK_AsIs,
+ binaryOperator(hasOperatorName("/"),
+ hasLHS(expr(ignoringParenImpCasts(anyOf(
+ sizeOfExpr(has(NumType)),
+ sizeOfExpr(has(expr(hasType(NumType)))))))),
+ hasRHS(expr(ignoringParenImpCasts(anyOf(
+ sizeOfExpr(has(DenomType)),
+ sizeOfExpr(has(expr(hasType(DenomType)))))))))
+ .bind("sizeof-divide-expr")),
this);
// Detect expression like: sizeof(...) * sizeof(...)); most likely an error.
Index: clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp
@@ -29,57 +29,66 @@
// Match expressions like `a *= b` and `a /= b` where `a` has type
// `absl::Duration` and `b` is not of a built-in type.
Finder->addMatcher(
- cxxOperatorCallExpr(
- argumentCountIs(2),
- hasArgument(
- 0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
- hasArgument(1, expr().bind("arg")),
- callee(functionDecl(
- hasParent(functionTemplateDecl()),
- unless(hasTemplateArgument(0, refersToType(builtinType()))),
- hasAnyName("operator*=", "operator/="))))
- .bind("OuterExpr"),
+ traverse(
+ ast_type_traits::TK_AsIs,
+ cxxOperatorCallExpr(
+ argumentCountIs(2),
+ hasArgument(
+ 0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
+ hasArgument(1, expr().bind("arg")),
+ callee(functionDecl(
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("operator*=", "operator/="))))
+ .bind("OuterExpr")),
this);
// Match expressions like `a.operator*=(b)` and `a.operator/=(b)` where `a`
// has type `absl::Duration` and `b` is not of a built-in type.
Finder->addMatcher(
- cxxMemberCallExpr(
- callee(cxxMethodDecl(
- ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
- hasParent(functionTemplateDecl()),
- unless(hasTemplateArgument(0, refersToType(builtinType()))),
- hasAnyName("operator*=", "operator/="))),
- argumentCountIs(1), hasArgument(0, expr().bind("arg")))
- .bind("OuterExpr"),
+ traverse(
+ ast_type_traits::TK_AsIs,
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(
+ ofClass(cxxRecordDecl(hasName("::absl::Duration"))),
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("operator*=", "operator/="))),
+ argumentCountIs(1), hasArgument(0, expr().bind("arg")))
+ .bind("OuterExpr")),
this);
// Match expressions like `a * b`, `a / b`, `operator*(a, b)`, and
// `operator/(a, b)` where `a` has type `absl::Duration` and `b` is not of a
// built-in type.
Finder->addMatcher(
- callExpr(callee(functionDecl(
- hasParent(functionTemplateDecl()),
- unless(hasTemplateArgument(0, refersToType(builtinType()))),
- hasAnyName("::absl::operator*", "::absl::operator/"))),
- argumentCountIs(2),
- hasArgument(0, expr(hasType(
- cxxRecordDecl(hasName("::absl::Duration"))))),
- hasArgument(1, expr().bind("arg")))
- .bind("OuterExpr"),
+ traverse(
+ ast_type_traits::TK_AsIs,
+ callExpr(
+ callee(functionDecl(
+ hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(0, refersToType(builtinType()))),
+ hasAnyName("::absl::operator*", "::absl::operator/"))),
+ argumentCountIs(2),
+ hasArgument(
+ 0, expr(hasType(cxxRecordDecl(hasName("::absl::Duration"))))),
+ hasArgument(1, expr().bind("arg")))
+ .bind("OuterExpr")),
this);
// Match expressions like `a * b` and `operator*(a, b)` where `a` is not of a
// built-in type and `b` has type `absl::Duration`.
Finder->addMatcher(
- callExpr(callee(functionDecl(
- hasParent(functionTemplateDecl()),
- unless(hasTemplateArgument(0, refersToType(builtinType()))),
- hasName("::absl::operator*"))),
- argumentCountIs(2), hasArgument(0, expr().bind("arg")),
- hasArgument(1, expr(hasType(
- cxxRecordDecl(hasName("::absl::Duration"))))))
- .bind("OuterExpr"),
+ traverse(
+ ast_type_traits::TK_AsIs,
+ callExpr(callee(functionDecl(hasParent(functionTemplateDecl()),
+ unless(hasTemplateArgument(
+ 0, refersToType(builtinType()))),
+ hasName("::absl::operator*"))),
+ argumentCountIs(2), hasArgument(0, expr().bind("arg")),
+ hasArgument(1, expr(hasType(cxxRecordDecl(
+ hasName("::absl::Duration"))))))
+ .bind("OuterExpr")),
this);
// For the factory functions, we match only the non-templated overloads that
Index: clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/TimeSubtractionCheck.cpp
@@ -114,7 +114,7 @@
hasLHS(TimeInverseMatcher))
.bind("binop")))
.bind("outer_call");
- Finder->addMatcher(CallMatcher, this);
+ Finder->addMatcher(traverse(TK_AsIs, CallMatcher), this);
// Match cases where we know the second operand is a 'Time'. Since
// subtracting a 'Time' from a 'Duration' is not defined, in these cases,
@@ -122,7 +122,7 @@
auto OperandMatcher =
binaryOperator(hasOperatorName("-"), hasRHS(TimeInverseMatcher))
.bind("binop");
- Finder->addMatcher(OperandMatcher, this);
+ Finder->addMatcher(traverse(TK_AsIs, OperandMatcher), this);
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits