diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -96,6 +96,471 @@
+ +The default mode of operation of AST Matchers visits all nodes in the AST, +even if they are not spelled in the source. This is AsIs mode. This mode is +hard to use correctly and requires more development iteration because it means +that the user must write AST Matchers to explicitly traverse or ignore nodes +which are not visible.
+ +In addition, because template instantations are matched in the default mode, +transformations can be accidentally made to template declarations. Finally, +because implicit nodes are matched by default, transformations can be made on +entirely incorrect places in the code.
+ +For these reasons, it is possible to ignore AST nodes which are not spelled in +the source using the IgnoreUnlessSpelledInSource mode. This is likely to be far +less error-prone for users who are not already very familiar with the AST. It is +also likely to be less error-prone for experienced AST users, as difficult cases +do not need to be encountered and matcher expressions adjusted for these +cases.
+ +In clang-query, the mode can be changed with +
+set traversal IgnoreUnlessSpelledInSource ++ +This affects both matchers and AST dump output in results. + +
When using the C++ API such as in clang-tidy checks, the traverse() matcher +is used to set the mode: +
+Finder->addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, + returnStmt(hasReturnArgument(integerLiteral(equals(0)))) + ), this); ++ +
The following table compares the AsIs mode with the IgnoreUnlessSpelledInSource +mode:
+ + + +| AsIs | IgnoreUnlessSpelledInSource | +|
|---|---|---|
AST dump of func1:
+
+struct B
+{
+ B(int);
+};
+
+B func1() {
+ return 42;
+}
+
+
+ |
+
+C++98 dialect:
++FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-ImplicitCastExpr + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 ++C++11, C++14 dialect: + +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 ++C++17, C++20 dialect: + +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 ++ |
+
+All dialects:
+ +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-IntegerLiteral 'int' 42 + |
+
Matcher for returned '42':
+
+struct B
+{
+ B(int);
+};
+
+B func1() {
+ return 42;
+}
+
+
+ |
+
+All dialects:
+
+returnStmt(hasReturnValue(
+ ignoringImplicit(
+ ignoringElidableConstructorCall(
+ ignoringImplicit(
+ cxxConstructExpr(hasArgument(0,
+ ignoringImplicit(
+ integerLiteral().bind("returnVal")
+ )
+ ))
+ )
+ )
+ )
+ ))
+ |
+
+All dialects:
+
+returnStmt(hasReturnValue(
+ integerLiteral().bind("returnVal")
+))
+ |
+
Match result for
+implicitCastExpr()+given: +
+struct B
+{
+ B(int);
+};
+
+B func1() {
+ return 42;
+}
+
+
+ |
++Match found. | ++No match. | +
Match result for:
+
+cxxConstructorDecl(
+ isCopyConstructor()
+ ).bind("prepend_explicit")
+
+given:
+
+struct Other {
+};
+struct Copyable {
+ Other m_o;
+ Copyable();
+};
+
+ |
+
+Match found! Insertion produces incorrect output:
+
+struct Other {
+};
+struct explicit Copyable {
+ Other m_o;
+ Copyable();
+};
+
+ |
++No match found. Incorrect replacement not possible. + | +
Replacement of `begin()` with `cbegin()`:
+
+cxxMemberCallExpr(
+ on(ConstContainerExpr),
+ callee(cxxMethodDecl(hasName("begin")))
+ ).bind("replace_with_cbegin")
+
+given:
+
+void foo()
+{
+ const Container c;
+ c.begin();
+
+ for (auto i : c)
+ {
+
+ }
+}
+
+ |
+
+2 matches found! Replacement produces incorrect output:
+
+void foo()
+{
+ const Container c;
+ c.cbegin();
+
+ for (auto i :.cbegin() c)
+ {
+
+ }
+}
+
+ |
+
+1 match found! Replacement produces correct output:
+
+void foo()
+{
+ const Container c;
+ c.cbegin();
+
+ for (auto i : c)
+ {
+
+ }
+}
+
+ |
+
Replacement of int member with safe_int:
+
+fieldDecl(
+ hasType(asString("int"))
+ ).bind("use_safe_int")
+
+given:
+
+struct S {
+ int m_i;
+};
+
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+
+ |
+
+2 matches found! Replacement produces incorrect output:
+
+struct S {
+ safe_int m_i;
+};
+
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ safe_int m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+
+ |
+
+1 match found! Replacement produces correct output:
+
+struct S {
+ safe_int m_i;
+};
+
+template<typename T>
+struct TemplStruct {
+ TemplStruct() {}
+ ~TemplStruct() {}
+
+private:
+ T m_t;
+};
+
+void instantiate()
+{
+ TemplStruct<int> ti;
+}
+
+ |
+
Add prefix to member initializer
+
+cxxCtorInitializer(
+ forField(fieldDecl())
+ ).bind("add_prefix")
+
+given:
+
+struct Simple {
+};
+
+struct Record {
+ Record() : i(42) {}
+private:
+ int i;
+ Simple s;
+};
+
+ |
+
+2 matches found! Replacement produces incorrect output:
+
+struct Simple {
+};
+
+struct Record {
+ m_Record() : m_i(42) {}
+private:
+ int i;
+ Simple s;
+};
+
+ |
+
+1 match found! Replacement produces correct output:
+
+struct Simple {
+};
+
+struct Record {
+ Record() : m_i(42) {}
+private:
+ int i;
+ Simple s;
+};
+
+ |
+
Ignored default arguments
+
+callExpr(
+ callee(functionDecl(
+ hasName("hasDefaultArg")
+ )),
+ argumentCountIs(1)
+ ).bind("add_prefix")
+
+given:
+
+void hasDefaultArg(int i, int j = 0)
+{
+}
+void callDefaultArg()
+{
+ hasDefaultArg(42);
+}
+
+ |
++No match! + | ++1 match found! + | +
Lambda fields
+
+fieldDecl(
+ hasType(asString("int"))
+ ).bind("make_safe")
+
+given:
+
+struct S
+{
+ int m_i;
+};
+
+void func() {
+ int a = 0;
+ int c = 0;
+
+ auto l = [a, b = c](int d) { int e = d; };
+ l(43);
+}
+
+ |
+
+2 matches found! Replacement produces incorrect output:
+
+struct S
+{
+ safe_int m_i;
+};
+
+void func() {
+ int a = 0;
+ int c = 0;
+
+ auto l = [safe_a, safe_b = c](int d) { int e = d; };
+ l(43);
+}
+ |
+
+1 match found! Replacement produces correct output:
+
+struct S
+{
+ safe_int m_i;
+};
+
+void func() {
+ int a = 0;
+ int c = 0;
+
+ auto l = [a, b = c](int d) { int e = d; };
+ l(43);
+}
+ |
+
+
| Return type | Name | Parameters |
|---|