Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -271,6 +271,17 @@ +Matcher<Decl>labelDeclMatcher<LabelDecl>... +
Matches a declaration of label.
+
+Given
+  goto FOO;
+  FOO: bar();
+labelDecl()
+  matches 'FOO:'
+
+ + Matcher<Decl>linkageSpecDeclMatcher<LinkageSpecDecl>...
Matches a declaration of a linkage specification.
 
@@ -497,6 +508,18 @@
 
+Matcher<Stmt>addrLabelExprMatcher<AddrLabelExpr>... +
Matches address of label statements (GNU extension).
+
+Given
+  FOO: bar();
+  void *ptr = &&FOO;
+  goto *bar;
+addrLabelExpr()
+  matches '&&FOO'
+
+ + Matcher<Stmt>arraySubscriptExprMatcher<ArraySubscriptExpr>...
Matches array subscript expressions.
 
@@ -517,6 +540,21 @@
 
+Matcher<Stmt>atomicExprMatcher<AtomicExpr>... +
Matches atomic builtins.
+Example matches __atomic_load_n(ptr, 1)
+  void foo() { int *ptr; __atomic_load_n(ptr, 1); }
+
+ + +Matcher<Stmt>binaryConditionalOperatorMatcher<BinaryConditionalOperator>... +
Matches binary conditional operator expressions (GNU extension).
+
+Example matches a ?: b
+  (a ?: b) + 42;
+
+ + Matcher<Stmt>binaryOperatorMatcher<BinaryOperator>...
Matches binary operator expressions.
 
@@ -876,6 +914,14 @@
 
+Matcher<Stmt>designatedInitExprMatcher<DesignatedInitExpr>... +
Matches C99 designated initializer expressions [C99 6.7.8].
+
+Example: Matches { [2].y = 1.0, [0].x = 1.0 }
+  point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
+
+ + Matcher<Stmt>doStmtMatcher<DoStmt>...
Matches do statements.
 
@@ -974,6 +1020,16 @@
 
+Matcher<Stmt>implicitValueInitExprMatcher<ImplicitValueInitExpr>... +
Matches implicit initializers of init list expressions.
+
+Given
+  point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 };
+implicitValueInitExpr()
+  matches "[0].y" (implicitly)
+
+ + Matcher<Stmt>initListExprMatcher<InitListExpr>...
Matches init list expressions.
 
@@ -1062,6 +1118,16 @@
 
+Matcher<Stmt>opaqueValueExprMatcher<OpaqueValueExpr>... +
Matches opaque value expressions. They are used as helpers
+to reference another expressions and can be met
+in BinaryConditionalOperators, for example.
+
+Example matches 'a'
+  (a ?: c) + 42;
+
+ + Matcher<Stmt>parenExprMatcher<ParenExpr>...
Matches parentheses used in expressions.
 
@@ -1071,6 +1137,31 @@
 
+Matcher<Stmt>parenListExprMatcher<ParenListExpr>... +
Matches paren list expressions.
+ParenListExprs don't have a predefined type and are used for late parsing.
+In the final AST, they can be met in template declarations.
+
+Given
+  template<typename T> class X {
+    void f() {
+      X x(*this);
+      int a = 0, b = 1; int i = (a, b);
+    }
+  };
+parenListExpr() matches "*this" but NOT matches (a, b) because (a, b)
+has a predefined type and is a ParenExpr, not a ParenListExpr.
+
+ + +Matcher<Stmt>predefinedExprMatcher<PredefinedExpr>... +
Matches predefined identifier expressions [C99 6.4.2.2].
+
+Example: Matches __func__
+  printf("%s", __func__);
+
+ + Matcher<Stmt>returnStmtMatcher<ReturnStmt>...
Matches return statements.
 
@@ -1091,6 +1182,14 @@
 
+Matcher<Stmt>stmtExprMatcher<StmtExpr>... +
Matches statement expression (GNU extension).
+
+Example match: ({ int X = 4; X; })
+  int C = ({ int X = 4; X; });
+
+ + Matcher<Stmt>stringLiteralMatcher<StringLiteral>...
Matches string literals (also matches wide string literals).
 
@@ -1660,6 +1759,20 @@
 
+Matcher<CXXConstructExpr>requiresZeroInitialization +
Matches a constructor call expression which requires
+zero initialization.
+
+Given
+void foo() {
+  struct point { double x; double y; };
+  point pt[2] = { { 1.0, 2.0 } };
+}
+initListExpr(has(cxxConstructExpr(requiresZeroInitialization()))
+will match the implicit array filler for pt[1].
+
+ + Matcher<CXXConstructorDecl>isCopyConstructor
Matches constructor declarations that are copy constructors.
 
@@ -2176,6 +2289,19 @@
 
+Matcher<DesignatedInitExpr>designatorCountIsunsigned N +
Matches designated initializer expressions that contain
+a specific number of designators.
+
+Example: Given
+  point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 };
+  point ptarray2[10] = { [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 };
+designatorCountIs(2)
+  matches '{ [2].y = 1.0, [0].x = 1.0 }',
+  but not '{ [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }'.
+
+ + Matcher<FloatingLiteral>equalsValueT Value
Matches literals that are equal to the given value.
 
@@ -3266,6 +3392,58 @@
 
+Matcher<AbstractConditionalOperator>hasConditionMatcher<Expr> InnerMatcher +
Matches the condition expression of an if statement, for loop,
+or conditional operator.
+
+Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
+  if (true) {}
+
+ + +Matcher<AbstractConditionalOperator>hasFalseExpressionMatcher<Expr> InnerMatcher +
Matches the false branch expression of a conditional operator
+(binary or ternary).
+
+Example matches b
+  condition ? a : b
+  condition ?: b
+
+ + +Matcher<AbstractConditionalOperator>hasTrueExpressionMatcher<Expr> InnerMatcher +
Matches the true branch expression of a conditional operator.
+
+Example 1 (conditional ternary operator): matches a
+  condition ? a : b
+
+Example 2 (conditional binary operator): matches opaqueValueExpr(condition)
+  condition ?: b
+
+ + +Matcher<AddrLabelExpr>hasDeclarationMatcher<Decl> InnerMatcher +
Matches a node if the declaration associated with that node
+matches the given matcher.
+
+The associated declaration is:
+- for type nodes, the declaration of the underlying type
+- for CallExpr, the declaration of the callee
+- for MemberExpr, the declaration of the referenced member
+- for CXXConstructExpr, the declaration of the constructor
+
+Also usable as Matcher<T> for any T supporting the getDecl() member
+function. e.g. various subtypes of clang::Type and various expressions.
+
+Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
+  Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
+  Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
+  Matcher<TypedefType>, Matcher<UnresolvedUsingType>
+
+ + Matcher<ArraySubscriptExpr>hasBaseMatcher<Expr> InnerMatcher
Matches the base expression of an array subscript expression.
 
@@ -3476,8 +3654,8 @@
 
-Matcher<CXXConstructExpr>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<CXXConstructExpr>hasDeclarationMatcher<Decl>  InnerMatcher
+
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -3491,8 +3669,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -3747,8 +3925,8 @@
-Matcher<CallExpr>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<CallExpr>hasDeclarationMatcher<Decl>  InnerMatcher
+
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -3762,8 +3940,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -3781,13 +3959,7 @@ Matcher<CastExpr>hasSourceExpressionMatcher<Expr> InnerMatcher -
Matches if the cast's source expression matches the given matcher.
-
-Example: matches "a string" (matcher =
-                                 hasSourceExpression(cxxConstructExpr()))
-class URL { URL(string); };
-URL url = "a string";
-
+

 
 
 Matcher<ClassTemplateSpecializationDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher
@@ -3850,7 +4022,7 @@
 
 Matcher<CompoundStmt>hasAnySubstatementMatcher<Stmt> InnerMatcher
 
Matches compound statements where at least one substatement matches
-a given matcher.
+a given matcher. Also matches StmtExprs that have CompoundStmt as children.
 
 Given
   { {}; 1+2; }
@@ -3861,38 +4033,13 @@
 
-Matcher<ConditionalOperator>hasConditionMatcher<Expr> InnerMatcher -
Matches the condition expression of an if statement, for loop,
-or conditional operator.
-
-Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true))))
-  if (true) {}
-
- - -Matcher<ConditionalOperator>hasFalseExpressionMatcher<Expr> InnerMatcher -
Matches the false branch expression of a conditional operator.
-
-Example matches b
-  condition ? a : b
-
- - -Matcher<ConditionalOperator>hasTrueExpressionMatcher<Expr> InnerMatcher -
Matches the true branch expression of a conditional operator.
-
-Example matches a
-  condition ? a : b
-
- - Matcher<DecayedType>hasDecayedTypeMatcher<QualType> InnerType
Matches the decayed type, whos decayed type matches InnerMatcher
 
-Matcher<DeclRefExpr>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<DeclRefExpr>hasDeclarationMatcher<Decl>  InnerMatcher
+
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -3906,8 +4053,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -4053,8 +4200,8 @@
-Matcher<EnumType>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<EnumType>hasDeclarationMatcher<Decl>  InnerMatcher
+
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -4068,8 +4215,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -4316,8 +4463,14 @@
-Matcher<InjectedClassNameType>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<InitListExpr>hasSyntacticFormMatcher<Expr> InnerMatcher
+
Matches the syntactic form of init list expressions
+(if expression have it).
+
+ + +Matcher<InjectedClassNameType>hasDeclarationMatcher<Decl> InnerMatcher +
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -4331,15 +4484,15 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
-Matcher<LabelStmt>hasDeclarationMatcher<Decl> InnerMatcher -
Matches a node if the declaration associated with that node
+Matcher<LabelStmt>hasDeclarationMatcher<Decl>  InnerMatcher
+
Matches a node if the declaration associated with that node
 matches the given matcher.
 
 The associated declaration is:
@@ -4353,8 +4506,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -4375,8 +4528,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType>
@@ -4525,6 +4678,10 @@
+Matcher<OpaqueValueExpr>hasSourceExpressionMatcher<Expr> InnerMatcher +

+
+
 Matcher<ParenType>innerTypeMatcher<Type>
 
Matches ParenType nodes where the inner type is a specific type.
 
@@ -4599,8 +4756,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -4658,8 +4815,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType>
@@ -4697,6 +4854,19 @@ +Matcher<StmtExpr>hasAnySubstatementMatcher<Stmt> InnerMatcher +
Matches compound statements where at least one substatement matches
+a given matcher. Also matches StmtExprs that have CompoundStmt as children.
+
+Given
+  { {}; 1+2; }
+hasAnySubstatement(compoundStmt())
+  matches '{ {}; 1+2; }'
+with compoundStmt()
+  matching '{}'
+
+ + Matcher<Stmt>alignOfExprMatcher<UnaryExprOrTypeTraitExpr> InnerMatcher
Same as unaryExprOrTypeTraitExpr, but only matching
 alignof.
@@ -4737,8 +4907,8 @@
 
 Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>,
   Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>,
-  Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>,
-  Matcher<RecordType>, Matcher<TagType>,
+  Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>,
+  Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>,
   Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>,
   Matcher<TypedefType>, Matcher<UnresolvedUsingType>
 
@@ -4827,8 +4997,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType> @@ -4863,8 +5033,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType> @@ -4914,8 +5084,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType> @@ -4955,8 +5125,8 @@ Usable as: Matcher<CallExpr>, Matcher<CXXConstructExpr>, Matcher<DeclRefExpr>, Matcher<EnumType>, Matcher<InjectedClassNameType>, - Matcher<LabelStmt>, Matcher<MemberExpr>, Matcher<QualType>, - Matcher<RecordType>, Matcher<TagType>, + Matcher<LabelStmt>, Matcher<AddrLabelExpr>, Matcher<MemberExpr>, + Matcher<QualType>, Matcher<RecordType>, Matcher<TagType>, Matcher<TemplateSpecializationType>, Matcher<TemplateTypeParmType>, Matcher<TypedefType>, Matcher<UnresolvedUsingType> Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -282,6 +282,18 @@ /// \endcode const internal::VariadicDynCastAllOfMatcher namedDecl; +/// \brief Matches a declaration of label. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// labelDecl() +/// matches 'FOO:' +/// \endcode +const internal::VariadicDynCastAllOfMatcher labelDecl; + /// \brief Matches a declaration of a namespace. /// /// Given @@ -976,6 +988,43 @@ /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher initListExpr; +/// \brief Matches the syntactic form of init list expressions +/// (if expression have it). +AST_MATCHER_P(InitListExpr, hasSyntacticForm, + internal::Matcher, InnerMatcher) { + const Expr *SyntForm = Node.getSyntacticForm(); + return (SyntForm != nullptr && + InnerMatcher.matches(*SyntForm, Finder, Builder)); +} + +/// \brief Matches implicit initializers of init list expressions. +/// +/// Given +/// \code +/// point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; +/// \endcode +/// implicitValueInitExpr() +/// matches "[0].y" (implicitly) +const internal::VariadicDynCastAllOfMatcher +implicitValueInitExpr; + +/// \brief Matches paren list expressions. +/// ParenListExprs don't have a predefined type and are used for late parsing. +/// In the final AST, they can be met in template declarations. +/// +/// Given +/// \code +/// template class X { +/// void f() { +/// X x(*this); +/// int a = 0, b = 1; int i = (a, b); +/// } +/// }; +/// \endcode +/// parenListExpr() matches "*this" but NOT matches (a, b) because (a, b) +/// has a predefined type and is a ParenExpr, not a ParenListExpr. +const internal::VariadicDynCastAllOfMatcher parenListExpr; + /// \brief Matches substitutions of non-type template parameters. /// /// Given @@ -1368,6 +1417,18 @@ /// matches 'FOO:' const internal::VariadicDynCastAllOfMatcher labelStmt; +/// \brief Matches address of label statements (GNU extension). +/// +/// Given +/// \code +/// FOO: bar(); +/// void *ptr = &&FOO; +/// goto *bar; +/// \endcode +/// addrLabelExpr() +/// matches '&&FOO' +const internal::VariadicDynCastAllOfMatcher addrLabelExpr; + /// \brief Matches switch statements. /// /// Given @@ -1537,9 +1598,22 @@ CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; /// \brief Matches GNU __null expression. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - GNUNullExpr> gnuNullExpr; +const internal::VariadicDynCastAllOfMatcher gnuNullExpr; + +/// \brief Matches atomic builtins. +/// Example matches __atomic_load_n(ptr, 1) +/// \code +/// void foo() { int *ptr; __atomic_load_n(ptr, 1); } +/// \endcode +const internal::VariadicDynCastAllOfMatcher atomicExpr; + +/// \brief Matches statement expression (GNU extension). +/// +/// Example match: ({ int X = 4; X; }) +/// \code +/// int C = ({ int X = 4; X; }); +/// \endcode +const internal::VariadicDynCastAllOfMatcher stmtExpr; /// \brief Matches binary operator expressions. /// @@ -1571,6 +1645,28 @@ Stmt, ConditionalOperator> conditionalOperator; +/// \brief Matches binary conditional operator expressions (GNU extension). +/// +/// Example matches a ?: b +/// \code +/// (a ?: b) + 42; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + BinaryConditionalOperator> binaryConditionalOperator; + +/// \brief Matches opaque value expressions. They are used as helpers +/// to reference another expressions and can be met +/// in BinaryConditionalOperators, for example. +/// +/// Example matches 'a' +/// \code +/// (a ?: c) + 42; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + OpaqueValueExpr> opaqueValueExpr; + /// \brief Matches a C++ static_assert declaration. /// /// Example: @@ -1727,6 +1823,41 @@ Stmt, CXXTemporaryObjectExpr> cxxTemporaryObjectExpr; +/// \brief Matches predefined identifier expressions [C99 6.4.2.2]. +/// +/// Example: Matches __func__ +/// \code +/// printf("%s", __func__); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + PredefinedExpr> predefinedExpr; + +/// \brief Matches C99 designated initializer expressions [C99 6.7.8]. +/// +/// Example: Matches { [2].y = 1.0, [0].x = 1.0 } +/// \code +/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + DesignatedInitExpr> designatedInitExpr; + +/// \brief Matches designated initializer expressions that contain +/// a specific number of designators. +/// +/// Example: Given +/// \code +/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 }; +/// point ptarray2[10] = { [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }; +/// \endcode +/// designatorCountIs(2) +/// matches '{ [2].y = 1.0, [0].x = 1.0 }', +/// but not '{ [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }'. +AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) { + return Node.size() == N; +} + /// \brief Matches \c QualTypes in the clang AST. const internal::VariadicAllOfMatcher qualType; @@ -2144,8 +2275,8 @@ /// /// Usable as: Matcher, Matcher, /// Matcher, Matcher, Matcher, -/// Matcher, Matcher, Matcher, -/// Matcher, Matcher, +/// Matcher, Matcher, Matcher, +/// Matcher, Matcher, Matcher, /// Matcher, Matcher, /// Matcher, Matcher inline internal::PolymorphicMatcherWithParam1< @@ -2883,6 +3014,22 @@ return Node.isListInitialization(); } +/// \brief Matches a constructor call expression which requires +/// zero initialization. +/// +/// Given +/// \code +/// void foo() { +/// struct point { double x; double y; }; +/// point pt[2] = { { 1.0, 2.0 } }; +/// } +/// \endcode +/// initListExpr(has(cxxConstructExpr(requiresZeroInitialization())) +/// will match the implicit array filler for pt[1]. +AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) { + return Node.requiresZeroInitialization(); +} + /// \brief Matches the n'th parameter of a function declaration. /// /// Given @@ -3099,11 +3246,11 @@ /// \code /// if (true) {} /// \endcode -AST_POLYMORPHIC_MATCHER_P(hasCondition, - AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, - WhileStmt, DoStmt, - ConditionalOperator), - internal::Matcher, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( + hasCondition, + AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, WhileStmt, DoStmt, + AbstractConditionalOperator), + internal::Matcher, InnerMatcher) { const Expr *const Condition = Node.getCond(); return (Condition != nullptr && InnerMatcher.matches(*Condition, Finder, Builder)); @@ -3242,7 +3389,7 @@ } /// \brief Matches compound statements where at least one substatement matches -/// a given matcher. +/// a given matcher. Also matches StmtExprs that have CompoundStmt as children. /// /// Given /// \code @@ -3252,10 +3399,13 @@ /// matches '{ {}; 1+2; }' /// with compoundStmt() /// matching '{}' -AST_MATCHER_P(CompoundStmt, hasAnySubstatement, - internal::Matcher, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(), - Node.body_end(), Finder, Builder); +AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement, + AST_POLYMORPHIC_SUPPORTED_TYPES(CompoundStmt, + StmtExpr), + internal::Matcher, InnerMatcher) { + const CompoundStmt *CS = CompoundStmtMatcher::get(Node); + return CS && matchesFirstInPointerRange(InnerMatcher, CS->body_begin(), + CS->body_end(), Finder, Builder); } /// \brief Checks that a compound statement contains a specific number of @@ -3354,17 +3504,28 @@ InnerMatcher.matches(*Operand, Finder, Builder)); } -/// \brief Matches if the cast's source expression matches the given matcher. +/// \brief Matches if the cast's source expression +/// or opaque value's source expression matches the given matcher. /// -/// Example: matches "a string" (matcher = -/// hasSourceExpression(cxxConstructExpr())) +/// Example 1: matches "a string" +/// (matcher = castExpr(hasSourceExpression(cxxConstructExpr()))) /// \code /// class URL { URL(string); }; /// URL url = "a string"; /// \endcode -AST_MATCHER_P(CastExpr, hasSourceExpression, - internal::Matcher, InnerMatcher) { - const Expr* const SubExpression = Node.getSubExpr(); +/// +/// Example 2: matches 'b' (matcher = +/// opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr()))) +/// \code +/// int a = b ?: 1; +/// \endcode + +AST_POLYMORPHIC_MATCHER_P(hasSourceExpression, + AST_POLYMORPHIC_SUPPORTED_TYPES(CastExpr, + OpaqueValueExpr), + internal::Matcher, InnerMatcher) { + const Expr *const SubExpression = + internal::GetSourceExpressionMatcher::get(Node); return (SubExpression != nullptr && InnerMatcher.matches(*SubExpression, Finder, Builder)); } @@ -3426,24 +3587,31 @@ /// \brief Matches the true branch expression of a conditional operator. /// -/// Example matches a +/// Example 1 (conditional ternary operator): matches a /// \code /// condition ? a : b /// \endcode -AST_MATCHER_P(ConditionalOperator, hasTrueExpression, +/// +/// Example 2 (conditional binary operator): matches opaqueValueExpr(condition) +/// \code +/// condition ?: b +/// \endcode +AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression, internal::Matcher, InnerMatcher) { const Expr *Expression = Node.getTrueExpr(); return (Expression != nullptr && InnerMatcher.matches(*Expression, Finder, Builder)); } -/// \brief Matches the false branch expression of a conditional operator. +/// \brief Matches the false branch expression of a conditional operator +/// (binary or ternary). /// /// Example matches b /// \code /// condition ? a : b +/// condition ?: b /// \endcode -AST_MATCHER_P(ConditionalOperator, hasFalseExpression, +AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression, internal::Matcher, InnerMatcher) { const Expr *Expression = Node.getFalseExpr(); return (Expression != nullptr && Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -749,6 +749,14 @@ return matchesDecl(Node.getMemberDecl(), Finder, Builder); } + /// \brief Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns + /// whether the inner matcher matches on it. + bool matchesSpecialized(const AddrLabelExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getLabel(), Finder, Builder); + } + /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node /// is \c NULL. bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, @@ -954,8 +962,8 @@ /// \brief All types that are supported by HasDeclarationMatcher above. typedef TypeList HasDeclarationSupportedTypes; @@ -1608,6 +1616,33 @@ return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr; } +template +struct GetSourceExpressionMatcher { + static const Expr *get(const Ty &Node) { + return Node.getSubExpr(); + } +}; + +template <> +inline const Expr *GetSourceExpressionMatcher::get( + const OpaqueValueExpr &Node) { + return Node.getSourceExpr(); +} + +template +struct CompoundStmtMatcher { + static const CompoundStmt *get(const Ty &Node) { + return &Node; + } +}; + +template <> +inline const CompoundStmt * +CompoundStmtMatcher::get(const StmtExpr &Node) { + return Node.getSubStmt(); +} + + } // end namespace internal } // end namespace ast_matchers } // end namespace clang Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -95,6 +95,7 @@ REGISTER_OVERLOADED_2(thisPointerType); REGISTER_MATCHER(accessSpecDecl); + REGISTER_MATCHER(addrLabelExpr); REGISTER_MATCHER(alignOfExpr); REGISTER_MATCHER(allOf); REGISTER_MATCHER(anyOf); @@ -104,9 +105,11 @@ REGISTER_MATCHER(arrayType); REGISTER_MATCHER(asmStmt); REGISTER_MATCHER(asString); + REGISTER_MATCHER(atomicExpr); REGISTER_MATCHER(atomicType); REGISTER_MATCHER(autoType); REGISTER_MATCHER(binaryOperator); + REGISTER_MATCHER(binaryConditionalOperator); REGISTER_MATCHER(blockPointerType); REGISTER_MATCHER(booleanType); REGISTER_MATCHER(breakStmt); @@ -161,6 +164,8 @@ REGISTER_MATCHER(declStmt); REGISTER_MATCHER(defaultStmt); REGISTER_MATCHER(dependentSizedArrayType); + REGISTER_MATCHER(designatedInitExpr); + REGISTER_MATCHER(designatorCountIs); REGISTER_MATCHER(doStmt); REGISTER_MATCHER(eachOf); REGISTER_MATCHER(elaboratedType); @@ -245,6 +250,7 @@ REGISTER_MATCHER(hasSizeExpr); REGISTER_MATCHER(hasSourceExpression); REGISTER_MATCHER(hasStaticStorageDuration); + REGISTER_MATCHER(hasSyntacticForm); REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); REGISTER_MATCHER(hasThen); @@ -259,6 +265,7 @@ REGISTER_MATCHER(ignoringParenCasts); REGISTER_MATCHER(ignoringParenImpCasts); REGISTER_MATCHER(implicitCastExpr); + REGISTER_MATCHER(implicitValueInitExpr); REGISTER_MATCHER(incompleteArrayType); REGISTER_MATCHER(initListExpr); REGISTER_MATCHER(injectedClassNameType); @@ -312,6 +319,7 @@ REGISTER_MATCHER(isVirtualAsWritten); REGISTER_MATCHER(isVolatileQualified); REGISTER_MATCHER(isWritten); + REGISTER_MATCHER(labelDecl); REGISTER_MATCHER(labelStmt); REGISTER_MATCHER(lambdaExpr); REGISTER_MATCHER(lValueReferenceType); @@ -336,12 +344,15 @@ REGISTER_MATCHER(objcObjectPointerType); REGISTER_MATCHER(on); REGISTER_MATCHER(onImplicitObjectArgument); + REGISTER_MATCHER(opaqueValueExpr); REGISTER_MATCHER(parameterCountIs); REGISTER_MATCHER(parenExpr); + REGISTER_MATCHER(parenListExpr); REGISTER_MATCHER(parenType); REGISTER_MATCHER(parmVarDecl); REGISTER_MATCHER(pointee); REGISTER_MATCHER(pointerType); + REGISTER_MATCHER(predefinedExpr); REGISTER_MATCHER(qualType); REGISTER_MATCHER(realFloatingPointType); REGISTER_MATCHER(recordDecl); @@ -350,6 +361,7 @@ REGISTER_MATCHER(refersToDeclaration); REGISTER_MATCHER(refersToIntegralType); REGISTER_MATCHER(refersToType); + REGISTER_MATCHER(requiresZeroInitialization); REGISTER_MATCHER(returns); REGISTER_MATCHER(returnStmt); REGISTER_MATCHER(rValueReferenceType); @@ -360,6 +372,7 @@ REGISTER_MATCHER(statementCountIs); REGISTER_MATCHER(staticAssertDecl); REGISTER_MATCHER(stmt); + REGISTER_MATCHER(stmtExpr); REGISTER_MATCHER(stringLiteral); REGISTER_MATCHER(substNonTypeTemplateParmExpr); REGISTER_MATCHER(substTemplateTypeParmType); Index: unittests/AST/MatchVerifier.h =================================================================== --- unittests/AST/MatchVerifier.h +++ unittests/AST/MatchVerifier.h @@ -62,6 +62,9 @@ std::vector& Args, Language L); + template + testing::AssertionResult match(const Decl *D, const MatcherType &AMatcher); + protected: void run(const MatchFinder::MatchResult &Result) override; virtual void verify(const MatchFinder::MatchResult &Result, @@ -127,6 +130,22 @@ return testing::AssertionSuccess(); } +/// \brief Runs a matcher over some AST, and returns the result of the +/// verifier for the matched node. +template template +testing::AssertionResult MatchVerifier::match( + const Decl *D, const MatcherType &AMatcher) { + MatchFinder Finder; + Finder.addMatcher(AMatcher.bind(""), this); + + setFailure("Could not find match"); + Finder.match(*D, D->getASTContext()); + + if (!Verified) + return testing::AssertionFailure() << VerifyResult; + return testing::AssertionSuccess(); +} + template void MatchVerifier::run(const MatchFinder::MatchResult &Result) { const NodeType *Node = Result.Nodes.getNodeAs(""); Index: unittests/ASTMatchers/ASTMatchersTest.h =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.h +++ unittests/ASTMatchers/ASTMatchersTest.h @@ -126,6 +126,13 @@ } template +testing::AssertionResult matchesC99(const std::string &Code, + const T &AMatcher) { + return matchesConditionally(Code, AMatcher, true, "-std=c99", + FileContentMappings(), "input.c"); +} + +template testing::AssertionResult notMatchesC(const std::string &Code, const T &AMatcher) { return matchesConditionally(Code, AMatcher, false, "", FileContentMappings(), Index: unittests/ASTMatchers/ASTMatchersTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTest.cpp +++ unittests/ASTMatchers/ASTMatchersTest.cpp @@ -1209,7 +1209,12 @@ EXPECT_TRUE(matches("void f() { while(true) { continue; } }", continueStmt())); EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", gotoStmt())); - EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", labelStmt())); + EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", + labelStmt( + hasDeclaration( + labelDecl(hasName("FOO")))))); + EXPECT_TRUE(matches("void f() { FOO: ; void *ptr = &&FOO; goto *ptr; }", + addrLabelExpr())); EXPECT_TRUE(matches("void f() { return; }", returnStmt())); } @@ -2527,6 +2532,82 @@ EXPECT_TRUE(matches("int* i = __null;", gnuNullExpr())); } +TEST(Matcher, AtomicExpr) { + EXPECT_TRUE(matches("void foo() { int *ptr; __atomic_load_n(ptr, 1); }", + atomicExpr())); +} + +TEST(Matcher, Initializers) { + const char *ToMatch = "void foo() { struct point { double x; double y; };" + " struct point ptarray[10] = " + " { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }"; + EXPECT_TRUE(matchesConditionally( + ToMatch, + initListExpr( + has( + cxxConstructExpr( + requiresZeroInitialization())), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(1.0))), + has(implicitValueInitExpr( + hasType(asString("double")))))), + has( + initListExpr( + hasType(asString("struct point")), + has(floatLiteral(equals(2.0))), + has(floatLiteral(equals(1.0))))) + ), true, "-std=gnu++98")); + + EXPECT_TRUE(matchesC99(ToMatch, + initListExpr( + hasSyntacticForm( + initListExpr( + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(1.0))), + has(integerLiteral( + equals(2))))), + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(2.0))), + has(integerLiteral( + equals(2))))), + has( + designatedInitExpr( + designatorCountIs(2), + has(floatLiteral( + equals(1.0))), + has(integerLiteral( + equals(0))))) + ))))); +} + +TEST(Matcher, ParenListExpr) { + EXPECT_TRUE( + matches( + " template class foo { void bar() { foo X(*this); } }; ", + varDecl(hasInitializer(parenListExpr(has(unaryOperator())))))); +} + +TEST(Matcher, StmtExpr) { + EXPECT_TRUE(matches("void declToImport() { int C = ({int X=4; X;}); }", + varDecl(hasInitializer(stmtExpr())))); +} + +TEST(Matcher, ImportPredefinedExpr) { + // __func__ expands as StringLiteral("foo") + EXPECT_TRUE(matches("void foo() { __func__; }", + predefinedExpr( + hasType(asString("const char [4]")), + has(stringLiteral())))); +} + TEST(Matcher, AsmStatement) { EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt())); } @@ -2750,6 +2831,28 @@ EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse)); EXPECT_TRUE( notMatches("void x() { true ? false : true; }", ConditionalFalse)); + + EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse)); + EXPECT_TRUE( + notMatches("void x() { true ? false : true; }", ConditionalFalse)); +} + +TEST(Matcher, BinaryConditionalOperator) { + StatementMatcher AlwaysOne = binaryConditionalOperator( + hasCondition(implicitCastExpr( + has( + opaqueValueExpr( + hasSourceExpression((integerLiteral(equals(1)))))))), + hasFalseExpression(integerLiteral(equals(0)))); + + EXPECT_TRUE(matches("void x() { 1 ?: 0; }", AlwaysOne)); + + StatementMatcher FourNotFive = binaryConditionalOperator( + hasTrueExpression(opaqueValueExpr( + hasSourceExpression((integerLiteral(equals(4)))))), + hasFalseExpression(integerLiteral(equals(5)))); + + EXPECT_TRUE(matches("void x() { 4 ?: 5; }", FourNotFive)); } TEST(ArraySubscriptMatchers, ArraySubscripts) {