From ec3d8e61b527c6312f77a4dab095ffc34e954927 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Thu, 2 Jan 2020 13:37:41 -0500 Subject: Handle init statements in readability-else-after-return Adds a new ASTMatcher condition called 'hasInitStatement()' that matches if, switch and range-for statements with an initializer. Reworked clang-tidy readability-else-after-return to handle variables in the if condition or init statements in c++17 ifs. Also checks if removing the else would affect object lifetimes in the else branch. Fixes PR44364. --- clang/docs/LibASTMatchersReference.html | 131 +++++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 17 deletions(-) (limited to 'clang/docs') diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 97c75277c27..338399976f4 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3009,6 +3009,23 @@ expr(isValueDependent()) matches return Size +Matcher<Expr>nullPointerConstant +
Matches expressions that resolve to a null pointer constant, such as
+GNU's __null, C++11's nullptr, or C's NULL macro.
+
+Given:
+  void *v1 = NULL;
+  void *v2 = nullptr;
+  void *v3 = __null; // GNU extension
+  char *cp = (char *)0;
+  int *ip = 0;
+  int i = 0;
+expr(nullPointerConstant())
+  matches the initializer for v1, v2, v3, cp, and ip. Does not match the
+  initializer for i.
+
+ + Matcher<FieldDecl>hasBitWidthunsigned Width
Matches non-static data members that are bit-fields of the specified
 bit width.
@@ -3761,6 +3778,18 @@ but not
 Example matches y (matcher = parmVarDecl(hasDefaultArgument()))
 void x(int val) {}
 void y(int val = 0) {}
+
+Deprecated. Use hasInitializer() instead to be able to
+match on the contents of the default argument.  For example:
+
+void x(int val = 7) {}
+void y(int val = 42) {}
+parmVarDecl(hasInitializer(integerLiteral(equals(42))))
+  matches the parameter of y
+
+A matcher such as
+  parmVarDecl(hasInitializer(anything()))
+is equivalent to parmVarDecl(hasDefaultArgument()).
 
@@ -4479,23 +4508,6 @@ functionDecl(isInstantiated()) -Matcher<internal::Matcher<Expr>>nullPointerConstant -
Matches expressions that resolve to a null pointer constant, such as
-GNU's __null, C++11's nullptr, or C's NULL macro.
-
-Given:
-  void *v1 = NULL;
-  void *v2 = nullptr;
-  void *v3 = __null; // GNU extension
-  char *cp = (char *)0;
-  int *ip = 0;
-  int i = 0;
-expr(nullPointerConstant())
-  matches the initializer for v1, v2, v3, cp, and ip. Does not match the
-  initializer for i.
-
- - Matcher<internal::Matcher<NamedDecl>>hasAnyNameStringRef, ..., StringRef
Matches NamedDecl nodes that have any of the specified names.
 
@@ -5082,6 +5094,29 @@ with compoundStmt()
 
+Matcher<CXXForRangeStmt>hasInitStatementMatcher<Stmt> InnerMatcher +
Matches selection statements with initializer.
+
+Given:
+ void foo() { 
+   if (int i = foobar(); i > 0) {}
+   switch (int i = foobar(); i) {}
+   for (auto& a = get_range(); auto& x : a) {} 
+ }
+ void bar() { 
+   if (foobar() > 0) {}
+   switch (foobar()) {}
+   for (auto& x : get_range()) {} 
+ }
+ifStmt(hasInitStatement(anything()))
+  matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+  matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+  matches the range for statement in foo but not in bar.
+
+ + Matcher<CXXForRangeStmt>hasLoopVariableMatcher<VarDecl> InnerMatcher
Matches the initialization statement of a for loop.
 
@@ -6206,6 +6241,29 @@ Examples matches the if statement
 
+Matcher<IfStmt>hasInitStatementMatcher<Stmt> InnerMatcher +
Matches selection statements with initializer.
+
+Given:
+ void foo() { 
+   if (int i = foobar(); i > 0) {}
+   switch (int i = foobar(); i) {}
+   for (auto& a = get_range(); auto& x : a) {} 
+ }
+ void bar() { 
+   if (foobar() > 0) {}
+   switch (foobar()) {}
+   for (auto& x : get_range()) {} 
+ }
+ifStmt(hasInitStatement(anything()))
+  matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+  matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+  matches the range for statement in foo but not in bar.
+
+ + Matcher<IfStmt>hasThenMatcher<Stmt> InnerMatcher
Matches the then-statement of an if statement.
 
@@ -6943,6 +7001,29 @@ Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
 
+Matcher<SwitchStmt>hasInitStatementMatcher<Stmt> InnerMatcher +
Matches selection statements with initializer.
+
+Given:
+ void foo() { 
+   if (int i = foobar(); i > 0) {}
+   switch (int i = foobar(); i) {}
+   for (auto& a = get_range(); auto& x : a) {} 
+ }
+ void bar() { 
+   if (foobar() > 0) {}
+   switch (foobar()) {}
+   for (auto& x : get_range()) {} 
+ }
+ifStmt(hasInitStatement(anything()))
+  matches the if statement in foo but not in bar.
+switchStmt(hasInitStatement(anything()))
+  matches the switch statement in foo but not in bar.
+cxxForRangeStmt(hasInitStatement(anything()))
+  matches the range for statement in foo but not in bar.
+
+ + Matcher<TagType>hasDeclarationconst Matcher<Decl> InnerMatcher
Matches a node if the declaration associated with that node
 matches the given matcher.
@@ -7170,6 +7251,22 @@ Usable as: Any Matcher
 
+Matcher<T>traverseast_type_traits::TraversalKind TK, const Matcher<T> InnerMatcher +
Causes all nested matchers to be matched with the specified traversal kind.
+
+Given
+  void foo()
+  {
+      int i = 3.0;
+  }
+The matcher
+  traverse(ast_type_traits::TK_IgnoreImplicitCastsAndParentheses,
+    varDecl(hasInitializer(floatLiteral().bind("init")))
+  )
+matches the variable declaration with "init" bound to the "3.0".
+
+ + Matcher<TypedefNameDecl>hasTypeMatcher<QualType> InnerMatcher
Matches if the expression's or declaration's type matches a type
 matcher.
-- 
cgit v1.2.3