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 k() throw(int);
void l() throw(...);
functionDecl(hasDynamicExceptionSpec())
matches the declarations of j, k, and l, but not f, g, h, or i.
functionDecl(hasDynamicExceptionSpec()) and
functionProtoType(hasDynamicExceptionSpec())
match the declarations of j, k, and l, but not f, g, h, or i.
</pre></td></tr>
@ -2540,8 +2541,8 @@ Given:
void h() throw();
void i() throw(int);
void j() noexcept(false);
functionDecl(isNoThrow())
matches the declarations of g, and h, but not f, i or j.
functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
match the declarations of g, and h, but not f, i or j.
</pre></td></tr>
@ -2597,6 +2598,37 @@ functionProtoType(parameterCountIs(3))
</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 colspan="4" class="doc" id="parameterCountIs1"><pre>Matches FunctionDecls and FunctionProtoTypes that have a
specific parameter count.

View File

@ -3265,10 +3265,13 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
/// void k() throw(int);
/// void l() throw(...);
/// \endcode
/// functionDecl(hasDynamicExceptionSpec())
/// matches the declarations of j, k, and l, but not f, g, h, or i.
AST_MATCHER(FunctionDecl, hasDynamicExceptionSpec) {
if (const auto *FnTy = Node.getType()->getAs<FunctionProtoType>())
/// functionDecl(hasDynamicExceptionSpec()) and
/// functionProtoType(hasDynamicExceptionSpec())
/// match the declarations of j, k, and l, but not f, g, h, or i.
AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
FunctionProtoType)) {
if (const FunctionProtoType *FnTy = internal::getFunctionProtoType(Node))
return FnTy->hasDynamicExceptionSpec();
return false;
}
@ -3283,10 +3286,12 @@ AST_MATCHER(FunctionDecl, hasDynamicExceptionSpec) {
/// void i() throw(int);
/// void j() noexcept(false);
/// \endcode
/// functionDecl(isNoThrow())
/// matches the declarations of g, and h, but not f, i or j.
AST_MATCHER(FunctionDecl, isNoThrow) {
const auto *FnTy = Node.getType()->getAs<FunctionProtoType>();
/// functionDecl(isNoThrow()) and functionProtoType(isNoThrow())
/// match the declarations of g, and h, but not f, i or j.
AST_POLYMORPHIC_MATCHER(isNoThrow,
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
// 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()))
return true;
return FnTy->isNothrow(Node.getASTContext());
return FnTy->isNothrow(Finder->getASTContext());
}
/// \brief Matches constexpr variable and function declarations.

View File

@ -106,6 +106,17 @@ inline QualType getUnderlyingType(const TypedefNameDecl &Node) {
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.
class BoundNodesMap {
public:

View File

@ -845,6 +845,13 @@ TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) {
notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
EXPECT_TRUE(matches("void f() throw();", 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) {
@ -1396,6 +1403,20 @@ TEST(hasDynamicExceptionSpec, MatchesDynamicExceptionSpecifications) {
matches("void k() throw(int);", functionDecl(hasDynamicExceptionSpec())));
EXPECT_TRUE(
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) {