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,19 @@
 
+Matcher<Stmt>atomicExprMatcher<AtomicExpr>... +
Matches atomic builtins.
+
+ + +Matcher<Stmt>binaryConditionalOperatorMatcher<BinaryConditionalOperator>... +
Matches binary conditional operator expressions (GNU extension).
+
+Example matches a ?: b
+  (a ?: c) + 42
+
+ + Matcher<Stmt>binaryOperatorMatcher<BinaryOperator>...
Matches binary operator expressions.
 
@@ -876,6 +912,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 +1018,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 +1116,14 @@
 
+Matcher<Stmt>opaqueValueExprMatcher<OpaqueValueExpr>... +
Matches opaque value expressions.
+
+Example matches 'a'
+  (a ?: c) + 42
+
+ + Matcher<Stmt>parenExprMatcher<ParenExpr>...
Matches parentheses used in expressions.
 
@@ -1071,6 +1133,24 @@
 
+Matcher<Stmt>parenListExprMatcher<ParenListExpr>... +
Matches paren list expressions.
+
+Given
+  template<typename T> class X { void f() { X x(*this); } };
+parenListExpr()
+  matches "*this"
+
+ + +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 +1171,14 @@
 
+Matcher<Stmt>stmtExprMatcher<StmtExpr>... +
Matches GNU statement expression.
+
+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 +1748,12 @@
 
+Matcher<CXXConstructExpr>requiresZeroInitialization +
Matches a constructor call expression which requires
+zero initialization.
+
+ + Matcher<CXXConstructorDecl>isCopyConstructor
Matches constructor declarations that are copy constructors.
 
@@ -2176,6 +2270,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.
 
@@ -3256,6 +3363,53 @@
 
+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.
+
+Example matches b
+  condition ? a : b
+
+ + +Matcher<AbstractConditionalOperator>hasTrueExpressionMatcher<Expr> InnerMatcher +
Matches the true branch expression of a conditional operator.
+
+Example matches a
+  condition ? a : 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.
 
@@ -3466,8 +3620,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:
@@ -3481,8 +3635,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>
 
@@ -3737,8 +3891,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:
@@ -3752,8 +3906,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>
 
@@ -3771,7 +3925,8 @@ Matcher<CastExpr>hasSourceExpressionMatcher<Expr> InnerMatcher -
Matches if the cast's source expression matches the given matcher.
+
Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
 
 Example: matches "a string" (matcher =
                                  hasSourceExpression(cxxConstructExpr()))
@@ -3851,38 +4006,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:
@@ -3896,8 +4026,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>
 
@@ -4043,8 +4173,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:
@@ -4058,8 +4188,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>
 
@@ -4306,8 +4436,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:
@@ -4321,15 +4457,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:
@@ -4343,8 +4479,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>
 
@@ -4365,8 +4501,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>
@@ -4515,6 +4651,17 @@
+Matcher<OpaqueValueExpr>hasSourceExpressionMatcher<Expr> InnerMatcher +
Matches if the cast's source expression
+or opaque value's source expression matches the given matcher.
+
+Example: matches "a string" (matcher =
+                                 hasSourceExpression(cxxConstructExpr()))
+class URL { URL(string); };
+URL url = "a string";
+
+ + Matcher<ParenType>innerTypeMatcher<Type>
Matches ParenType nodes where the inner type is a specific type.
 
@@ -4589,8 +4736,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>
 
@@ -4648,8 +4795,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>
@@ -4687,6 +4834,15 @@
+Matcher<StmtExpr>hasSubStmtMatcher<CompoundStmt> InnerMatcher +
Matches if the substatement of GNU statement expression matches.
+
+Example matches true (matcher =
+  stmtExpr(hasSubStmt(has(declStmt(hasSingleDecl(varDecl())))))
+  int C = ({ int X = 4; X: });
+
+ + Matcher<Stmt>alignOfExprMatcher<UnaryExprOrTypeTraitExpr> InnerMatcher
Same as unaryExprOrTypeTraitExpr, but only matching
 alignof.
@@ -4727,8 +4883,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>
 
@@ -4817,8 +4973,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> @@ -4853,8 +5009,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> @@ -4904,8 +5060,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> @@ -4945,8 +5101,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,37 @@ /// 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. +/// +/// Given +/// \code +/// template class X { void f() { X x(*this); } }; +/// \endcode +/// parenListExpr() +/// matches "*this" +const internal::VariadicDynCastAllOfMatcher parenListExpr; + /// \brief Matches substitutions of non-type template parameters. /// /// Given @@ -1368,6 +1411,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 @@ -1541,6 +1596,36 @@ Stmt, GNUNullExpr> gnuNullExpr; +/// \brief Matches atomic builtins. +const internal::VariadicDynCastAllOfMatcher< + Stmt, + AtomicExpr> atomicExpr; + +/// \brief Matches GNU statement expression. +/// +/// Example match: ({ int X = 4; X: }) +/// \code +/// int C = ({ int X = 4; X: }); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + StmtExpr> stmtExpr; + + +/// \brief Matches if the substatement of GNU statement expression matches. +/// +/// Example matches true (matcher = +/// stmtExpr(hasSubStmt(has(declStmt(hasSingleDecl(varDecl()))))) +/// \code +/// int C = ({ int X = 4; X: }); +/// \endcode +AST_MATCHER_P(StmtExpr, hasSubStmt, + internal::Matcher, InnerMatcher) { + const CompoundStmt * const SubStmt = Node.getSubStmt(); + return (SubStmt != nullptr && + InnerMatcher.matches(*SubStmt, Finder, Builder)); +} + /// \brief Matches binary operator expressions. /// /// Example matches a || b @@ -1571,6 +1656,26 @@ Stmt, ConditionalOperator> conditionalOperator; +/// \brief Matches binary conditional operator expressions (GNU extension). +/// +/// Example matches a ?: b +/// \code +/// (a ?: c) + 42 +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + BinaryConditionalOperator> binaryConditionalOperator; + +/// \brief Matches opaque value expressions. +/// +/// Example matches 'a' +/// \code +/// (a ?: c) + 42 +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + OpaqueValueExpr> opaqueValueExpr; + /// \brief Matches a C++ static_assert declaration. /// /// Example: @@ -1727,6 +1832,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; @@ -2129,8 +2269,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< @@ -2868,6 +3008,12 @@ return Node.isListInitialization(); } +/// \brief Matches a constructor call expression which requires +/// zero initialization. +AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) { + return Node.requiresZeroInitialization(); +} + /// \brief Matches the n'th parameter of a function declaration. /// /// Given @@ -3084,11 +3230,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)); @@ -3339,7 +3485,8 @@ 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())) @@ -3347,9 +3494,12 @@ /// class URL { URL(string); }; /// URL url = "a string"; /// \endcode -AST_MATCHER_P(CastExpr, hasSourceExpression, - internal::Matcher, InnerMatcher) { - const Expr* const SubExpression = Node.getSubExpr(); +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)); } @@ -3415,7 +3565,7 @@ /// \code /// condition ? a : b /// \endcode -AST_MATCHER_P(ConditionalOperator, hasTrueExpression, +AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression, internal::Matcher, InnerMatcher) { const Expr *Expression = Node.getTrueExpr(); return (Expression != nullptr && @@ -3428,7 +3578,7 @@ /// \code /// condition ? a : 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 @@ -756,6 +756,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, @@ -961,8 +969,8 @@ /// \brief All types that are supported by HasDeclarationMatcher above. typedef TypeList HasDeclarationSupportedTypes; @@ -1615,6 +1623,19 @@ 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(); +} + } // 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); @@ -244,6 +249,7 @@ REGISTER_MATCHER(hasSizeExpr); REGISTER_MATCHER(hasSourceExpression); REGISTER_MATCHER(hasStaticStorageDuration); + REGISTER_MATCHER(hasSyntacticForm); REGISTER_MATCHER(hasTargetDecl); REGISTER_MATCHER(hasTemplateArgument); REGISTER_MATCHER(hasThen); @@ -258,6 +264,7 @@ REGISTER_MATCHER(ignoringParenCasts); REGISTER_MATCHER(ignoringParenImpCasts); REGISTER_MATCHER(implicitCastExpr); + REGISTER_MATCHER(implicitValueInitExpr); REGISTER_MATCHER(incompleteArrayType); REGISTER_MATCHER(initListExpr); REGISTER_MATCHER(injectedClassNameType); @@ -311,6 +318,7 @@ REGISTER_MATCHER(isVirtualAsWritten); REGISTER_MATCHER(isVolatileQualified); REGISTER_MATCHER(isWritten); + REGISTER_MATCHER(labelDecl); REGISTER_MATCHER(labelStmt); REGISTER_MATCHER(lambdaExpr); REGISTER_MATCHER(lValueReferenceType); @@ -335,12 +343,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); @@ -349,6 +360,7 @@ REGISTER_MATCHER(refersToDeclaration); REGISTER_MATCHER(refersToIntegralType); REGISTER_MATCHER(refersToType); + REGISTER_MATCHER(requiresZeroInitialization); REGISTER_MATCHER(returns); REGISTER_MATCHER(returnStmt); REGISTER_MATCHER(rValueReferenceType); @@ -359,6 +371,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())); } @@ -2522,6 +2527,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(hasSubStmt(compoundStmt())))))); +} + +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())); } @@ -2745,6 +2826,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) {