Make isNoThrow and hasDynamicExceptionSpec polymorphic so they can be used with both functionDecl and functionPrototype matchers.

Patch by Don Hinton.

llvm-svn: 272028
This commit is contained in:
Aaron Ballman 2016-06-07 17:34:45 +00:00
parent 4c4bdba28a
commit 230ad97156
4 changed files with 82 additions and 13 deletions

View File

@ -2414,8 +2414,9 @@ Given:
void j() throw(); void j() throw();
void k() throw(int); void k() throw(int);
void l() throw(...); void l() throw(...);
functionDecl(hasDynamicExceptionSpec()) functionDecl(hasDynamicExceptionSpec()) and
matches the declarations of j, k, and l, but not f, g, h, or i. functionProtoType(hasDynamicExceptionSpec())
match the declarations of j, k, and l, but not f, g, h, or i.
</pre></td></tr> </pre></td></tr>
@ -2540,8 +2541,8 @@ Given:
void h() throw(); void h() throw();
void i() throw(int); void i() throw(int);
void j() noexcept(false); void j() noexcept(false);
functionDecl(isNoThrow()) functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
matches the declarations of g, and h, but not f, i or j. match the declarations of g, and h, but not f, i or j.
</pre></td></tr> </pre></td></tr>
@ -2597,6 +2598,37 @@ functionProtoType(parameterCountIs(3))
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec1')"><a name="hasDynamicExceptionSpec1Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec1"><pre>Matches functions that have a dynamic exception specification.
Given:
void f();
void g() noexcept;
void h() noexcept(true);
void i() noexcept(false);
void j() throw();
void k() throw(int);
void l() throw(...);
functionDecl(hasDynamicExceptionSpec()) and
functionProtoType(hasDynamicExceptionSpec())
match the declarations of j, k, and l, but not f, g, h, or i.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('isNoThrow1')"><a name="isNoThrow1Anchor">isNoThrow</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isNoThrow1"><pre>Matches functions that have a non-throwing exception specification.
Given:
void f();
void g() noexcept;
void h() throw();
void i() throw(int);
void j() noexcept(false);
functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
match the declarations of g, and h, but not f, i or j.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs1')"><a name="parameterCountIs1Anchor">parameterCountIs</a></td><td>unsigned N</td></tr> <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('parameterCountIs1')"><a name="parameterCountIs1Anchor">parameterCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="parameterCountIs1"><pre>Matches FunctionDecls and FunctionProtoTypes that have a <tr><td colspan="4" class="doc" id="parameterCountIs1"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
specific parameter count. specific parameter count.

View File

@ -3265,10 +3265,13 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
/// void k() throw(int); /// void k() throw(int);
/// void l() throw(...); /// void l() throw(...);
/// \endcode /// \endcode
/// functionDecl(hasDynamicExceptionSpec()) /// functionDecl(hasDynamicExceptionSpec()) and
/// matches the declarations of j, k, and l, but not f, g, h, or i. /// functionProtoType(hasDynamicExceptionSpec())
AST_MATCHER(FunctionDecl, hasDynamicExceptionSpec) { /// match the declarations of j, k, and l, but not f, g, h, or i.
if (const auto *FnTy = Node.getType()->getAs<FunctionProtoType>()) AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType)) {
if (const FunctionProtoType *FnTy = internal::getFunctionProtoType(Node))
return FnTy->hasDynamicExceptionSpec(); return FnTy->hasDynamicExceptionSpec();
return false; return false;
} }
@ -3283,10 +3286,12 @@ AST_MATCHER(FunctionDecl, hasDynamicExceptionSpec) {
/// void i() throw(int); /// void i() throw(int);
/// void j() noexcept(false); /// void j() noexcept(false);
/// \endcode /// \endcode
/// functionDecl(isNoThrow()) /// functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
/// matches the declarations of g, and h, but not f, i or j. /// match the declarations of g, and h, but not f, i or j.
AST_MATCHER(FunctionDecl, isNoThrow) { AST_POLYMORPHIC_MATCHER(isNoThrow,
const auto *FnTy = Node.getType()->getAs<FunctionProtoType>(); AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType)) {
const FunctionProtoType *FnTy = internal::getFunctionProtoType(Node);
// If the function does not have a prototype, then it is assumed to be a // If the function does not have a prototype, then it is assumed to be a
// throwing function (as it would if the function did not have any exception // throwing function (as it would if the function did not have any exception
@ -3298,7 +3303,7 @@ AST_MATCHER(FunctionDecl, isNoThrow) {
if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType())) if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
return true; return true;
return FnTy->isNothrow(Node.getASTContext()); return FnTy->isNothrow(Finder->getASTContext());
} }
/// \brief Matches constexpr variable and function declarations. /// \brief Matches constexpr variable and function declarations.

View File

@ -106,6 +106,17 @@ inline QualType getUnderlyingType(const TypedefNameDecl &Node) {
return Node.getUnderlyingType(); return Node.getUnderlyingType();
} }
/// \brief Unifies obtaining the FunctionProtoType pointer from both
/// FunctionProtoType and FunctionDecl nodes..
inline const FunctionProtoType *
getFunctionProtoType(const FunctionProtoType &Node) {
return &Node;
}
inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) {
return Node.getType()->getAs<FunctionProtoType>();
}
/// \brief Internal version of BoundNodes. Holds all the bound nodes. /// \brief Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap { class BoundNodesMap {
public: public:

View File

@ -845,6 +845,13 @@ TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) {
notMatches("void f() noexcept(false);", functionDecl(isNoThrow()))); notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow()))); EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow())));
EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow()))); EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow())));
EXPECT_TRUE(notMatches("void f();", functionProtoType(isNoThrow())));
EXPECT_TRUE(notMatches("void f() throw(int);", functionProtoType(isNoThrow())));
EXPECT_TRUE(
notMatches("void f() noexcept(false);", functionProtoType(isNoThrow())));
EXPECT_TRUE(matches("void f() throw();", functionProtoType(isNoThrow())));
EXPECT_TRUE(matches("void f() noexcept;", functionProtoType(isNoThrow())));
} }
TEST(isConstexpr, MatchesConstexprDeclarations) { TEST(isConstexpr, MatchesConstexprDeclarations) {
@ -1396,6 +1403,20 @@ TEST(hasDynamicExceptionSpec, MatchesDynamicExceptionSpecifications) {
matches("void k() throw(int);", functionDecl(hasDynamicExceptionSpec()))); matches("void k() throw(int);", functionDecl(hasDynamicExceptionSpec())));
EXPECT_TRUE( EXPECT_TRUE(
matches("void l() throw(...);", functionDecl(hasDynamicExceptionSpec()))); matches("void l() throw(...);", functionDecl(hasDynamicExceptionSpec())));
EXPECT_TRUE(notMatches("void f();", functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(notMatches("void g() noexcept;",
functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(notMatches("void h() noexcept(true);",
functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(notMatches("void i() noexcept(false);",
functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(
matches("void j() throw();", functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(
matches("void k() throw(int);", functionProtoType(hasDynamicExceptionSpec())));
EXPECT_TRUE(
matches("void l() throw(...);", functionProtoType(hasDynamicExceptionSpec())));
} }
TEST(HasObjectExpression, DoesNotMatchMember) { TEST(HasObjectExpression, DoesNotMatchMember) {