forked from OSchip/llvm-project
Re-apply r222646 (was reverted in r222667). Adding 4 ASTMatchers: typedefDecl, isInMainFile, isInSystemFile, isInFileMatchingName
Change to original: ifndef out tests in Windows due to /-separated paths. Summary: Often one is only interested in matches within the main-file or matches that are not within a system-header, for which this patch adds isInMainFile and isInSystemFile. They take no arguments and narrow down the matches. The isInFileMatchingName is mainly thought for interactive clang-query-sessions, to make a matcher more specific without restarting the session with the files you are interested in for that moment. It takes a string that will be used as regular-expression to match the filename of where the matched node is expanded. Patch by Hendrik von Prince. llvm-svn: 222765
This commit is contained in:
parent
c81c3f554c
commit
d3aa1f4a63
|
@ -307,6 +307,16 @@ Example matches X, Z
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="typedefDecl0"><pre>Matches typedef declarations.
|
||||
|
||||
Given
|
||||
typedef int X;
|
||||
typedefDecl()
|
||||
matches "typedef int X"
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('unresolvedUsingValueDecl0')"><a name="unresolvedUsingValueDecl0Anchor">unresolvedUsingValueDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1UnresolvedUsingValueDecl.html">UnresolvedUsingValueDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="unresolvedUsingValueDecl0"><pre>Matches unresolved using value declarations.
|
||||
|
||||
|
@ -339,6 +349,15 @@ usingDirectiveDecl()
|
|||
matches using namespace X </pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('valueDecl0')"><a name="valueDecl0Anchor">valueDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="valueDecl0"><pre>Matches any value declaration.
|
||||
|
||||
Example matches A, B, C and F
|
||||
enum X { A, B, C };
|
||||
void F();
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('varDecl0')"><a name="varDecl0Anchor">varDecl</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>>...</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="varDecl0"><pre>Matches variable declarations.
|
||||
|
||||
|
@ -1654,6 +1673,48 @@ f.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isExpansionInFileMatching0')"><a name="isExpansionInFileMatching0Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching0"><pre>Matches AST nodes that were expanded within files whose name is
|
||||
partially matching a given regex.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInFileMatching("AST.*"))
|
||||
#include "ASTMatcher.h"
|
||||
class X {};
|
||||
ASTMatcher.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isExpansionInMainFile0')"><a name="isExpansionInMainFile0Anchor">isExpansionInMainFile</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInMainFile0"><pre>Matches AST nodes that were expanded within the main-file.
|
||||
|
||||
Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
|
||||
#include <Y.h>
|
||||
class X {};
|
||||
Y.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader0')"><a name="isExpansionInSystemHeader0Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader0"><pre>Matches AST nodes that were expanded within system-header-files.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInSystemHeader())
|
||||
#include <SystemHeader.h>
|
||||
class X {};
|
||||
SystemHeader.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('isImplicit0')"><a name="isImplicit0Anchor">isImplicit</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isImplicit0"><pre>Matches a declaration that has been implicitly added
|
||||
by the compiler (eg. implicit defaultcopy constructors).
|
||||
|
@ -1858,7 +1919,7 @@ memberExpr(isArrow())
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>></td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html">NamedDecl</a>></td><td class="name" onclick="toggle('hasName0')"><a name="hasName0Anchor">hasName</a></td><td>std::string Name</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasName0"><pre>Matches NamedDecl nodes that have the specified name.
|
||||
|
||||
Supports specifying enclosing namespaces or classes by prefixing the name
|
||||
|
@ -1990,6 +2051,48 @@ and reference to that variable declaration within a compound statement.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isExpansionInFileMatching1')"><a name="isExpansionInFileMatching1Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching1"><pre>Matches AST nodes that were expanded within files whose name is
|
||||
partially matching a given regex.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInFileMatching("AST.*"))
|
||||
#include "ASTMatcher.h"
|
||||
class X {};
|
||||
ASTMatcher.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isExpansionInMainFile1')"><a name="isExpansionInMainFile1Anchor">isExpansionInMainFile</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInMainFile1"><pre>Matches AST nodes that were expanded within the main-file.
|
||||
|
||||
Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
|
||||
#include <Y.h>
|
||||
class X {};
|
||||
Y.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader1')"><a name="isExpansionInSystemHeader1Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader1"><pre>Matches AST nodes that were expanded within system-header-files.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInSystemHeader())
|
||||
#include <SystemHeader.h>
|
||||
class X {};
|
||||
SystemHeader.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
|
||||
|
||||
|
@ -2061,6 +2164,48 @@ classTemplateSpecializationDecl(templateArgumentCountIs(1))
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('isExpansionInFileMatching2')"><a name="isExpansionInFileMatching2Anchor">isExpansionInFileMatching</a></td><td>std::string RegExp</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInFileMatching2"><pre>Matches AST nodes that were expanded within files whose name is
|
||||
partially matching a given regex.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInFileMatching("AST.*"))
|
||||
#include "ASTMatcher.h"
|
||||
class X {};
|
||||
ASTMatcher.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('isExpansionInMainFile2')"><a name="isExpansionInMainFile2Anchor">isExpansionInMainFile</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInMainFile2"><pre>Matches AST nodes that were expanded within the main-file.
|
||||
|
||||
Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
|
||||
#include <Y.h>
|
||||
class X {};
|
||||
Y.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('isExpansionInSystemHeader2')"><a name="isExpansionInSystemHeader2Anchor">isExpansionInSystemHeader</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isExpansionInSystemHeader2"><pre>Matches AST nodes that were expanded within system-header-files.
|
||||
|
||||
Example matches Y but not X
|
||||
(matcher = recordDecl(isExpansionInSystemHeader())
|
||||
#include <SystemHeader.h>
|
||||
class X {};
|
||||
SystemHeader.h:
|
||||
class Y {};
|
||||
|
||||
Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>>, Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('equalsBoundNode2')"><a name="equalsBoundNode2Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="equalsBoundNode2"><pre>Matches if a node equals a previously bound node.
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
#include "clang/AST/DeclFriend.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/ASTMatchers/ASTMatchersInternal.h"
|
||||
#include "clang/ASTMatchers/ASTMatchersMacros.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
@ -142,6 +143,97 @@ typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
|
|||
/// Usable as: Any Matcher
|
||||
inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
|
||||
|
||||
/// \brief Matches typedef declarations.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// typedef int X;
|
||||
/// \endcode
|
||||
/// typedefDecl()
|
||||
/// matches "typedef int X"
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
|
||||
|
||||
/// \brief Matches AST nodes that were expanded within the main-file.
|
||||
///
|
||||
/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
|
||||
/// \code
|
||||
/// #include <Y.h>
|
||||
/// class X {};
|
||||
/// \endcode
|
||||
/// Y.h:
|
||||
/// \code
|
||||
/// class Y {};
|
||||
/// \endcode
|
||||
///
|
||||
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
|
||||
AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
|
||||
TypeLoc)) {
|
||||
auto &SourceManager = Finder->getASTContext().getSourceManager();
|
||||
return SourceManager.isInMainFile(
|
||||
SourceManager.getExpansionLoc(Node.getLocStart()));
|
||||
}
|
||||
|
||||
/// \brief Matches AST nodes that were expanded within system-header-files.
|
||||
///
|
||||
/// Example matches Y but not X
|
||||
/// (matcher = recordDecl(isExpansionInSystemHeader())
|
||||
/// \code
|
||||
/// #include <SystemHeader.h>
|
||||
/// class X {};
|
||||
/// \endcode
|
||||
/// SystemHeader.h:
|
||||
/// \code
|
||||
/// class Y {};
|
||||
/// \endcode
|
||||
///
|
||||
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
|
||||
AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
|
||||
TypeLoc)) {
|
||||
auto &SourceManager = Finder->getASTContext().getSourceManager();
|
||||
auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
|
||||
if (ExpansionLoc.isInvalid()) {
|
||||
return false;
|
||||
}
|
||||
return SourceManager.isInSystemHeader(ExpansionLoc);
|
||||
}
|
||||
|
||||
/// \brief Matches AST nodes that were expanded within files whose name is
|
||||
/// partially matching a given regex.
|
||||
///
|
||||
/// Example matches Y but not X
|
||||
/// (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
|
||||
/// \code
|
||||
/// #include "ASTMatcher.h"
|
||||
/// class X {};
|
||||
/// \endcode
|
||||
/// ASTMatcher.h:
|
||||
/// \code
|
||||
/// class Y {};
|
||||
/// \endcode
|
||||
///
|
||||
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
|
||||
AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
|
||||
TypeLoc),
|
||||
std::string, RegExp) {
|
||||
auto &SourceManager = Finder->getASTContext().getSourceManager();
|
||||
auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
|
||||
if (ExpansionLoc.isInvalid()) {
|
||||
return false;
|
||||
}
|
||||
auto FileEntry =
|
||||
SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
|
||||
if (!FileEntry) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Filename = FileEntry->getName();
|
||||
llvm::Regex RE(RegExp);
|
||||
return RE.match(Filename);
|
||||
}
|
||||
|
||||
/// \brief Matches declarations.
|
||||
///
|
||||
/// Examples matches \c X, \c C, and the friend declaration inside \c C;
|
||||
|
|
|
@ -143,6 +143,10 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(
|
|||
bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
|
||||
const Twine &FileName = "input.cc");
|
||||
|
||||
/// The first part of the pair is the filename, the second part the
|
||||
/// file-content.
|
||||
typedef std::vector<std::pair<std::string, std::string>> FileContentMappings;
|
||||
|
||||
/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and
|
||||
/// with additional other flags.
|
||||
///
|
||||
|
@ -152,9 +156,10 @@ bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
|
|||
/// \param FileName The file name which 'Code' will be mapped as.
|
||||
///
|
||||
/// \return - True if 'ToolAction' was successfully executed.
|
||||
bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
|
||||
const std::vector<std::string> &Args,
|
||||
const Twine &FileName = "input.cc");
|
||||
bool runToolOnCodeWithArgs(
|
||||
clang::FrontendAction *ToolAction, const Twine &Code,
|
||||
const std::vector<std::string> &Args, const Twine &FileName = "input.cc",
|
||||
const FileContentMappings &VirtualMappedFiles = FileContentMappings());
|
||||
|
||||
/// \brief Builds an AST for 'Code'.
|
||||
///
|
||||
|
|
|
@ -242,7 +242,10 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(isExpr);
|
||||
REGISTER_MATCHER(isExternC);
|
||||
REGISTER_MATCHER(isImplicit);
|
||||
REGISTER_MATCHER(isExpansionInFileMatching);
|
||||
REGISTER_MATCHER(isExpansionInMainFile);
|
||||
REGISTER_MATCHER(isInstantiated);
|
||||
REGISTER_MATCHER(isExpansionInSystemHeader);
|
||||
REGISTER_MATCHER(isInteger);
|
||||
REGISTER_MATCHER(isIntegral);
|
||||
REGISTER_MATCHER(isInTemplateInstantiation);
|
||||
|
@ -314,6 +317,7 @@ RegistryMaps::RegistryMaps() {
|
|||
REGISTER_MATCHER(to);
|
||||
REGISTER_MATCHER(tryStmt);
|
||||
REGISTER_MATCHER(type);
|
||||
REGISTER_MATCHER(typedefDecl);
|
||||
REGISTER_MATCHER(typedefType);
|
||||
REGISTER_MATCHER(typeLoc);
|
||||
REGISTER_MATCHER(unaryExprOrTypeTraitExpr);
|
||||
|
|
|
@ -123,17 +123,25 @@ getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs,
|
|||
|
||||
bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
|
||||
const std::vector<std::string> &Args,
|
||||
const Twine &FileName) {
|
||||
const Twine &FileName,
|
||||
const FileContentMappings &VirtualMappedFiles) {
|
||||
|
||||
SmallString<16> FileNameStorage;
|
||||
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
|
||||
llvm::IntrusiveRefCntPtr<FileManager> Files(
|
||||
new FileManager(FileSystemOptions()));
|
||||
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), ToolAction,
|
||||
Files.get());
|
||||
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef),
|
||||
ToolAction, Files.get());
|
||||
|
||||
SmallString<1024> CodeStorage;
|
||||
Invocation.mapVirtualFile(FileNameRef,
|
||||
Code.toNullTerminatedStringRef(CodeStorage));
|
||||
|
||||
for (auto &FilenameWithContent : VirtualMappedFiles) {
|
||||
Invocation.mapVirtualFile(FilenameWithContent.first,
|
||||
FilenameWithContent.second);
|
||||
}
|
||||
|
||||
return Invocation.run();
|
||||
}
|
||||
|
||||
|
|
|
@ -4625,5 +4625,58 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
|
|||
.bind("data")));
|
||||
}
|
||||
|
||||
TEST(TypeDefDeclMatcher, Match) {
|
||||
EXPECT_TRUE(matches("typedef int typedefDeclTest;",
|
||||
typedefDecl(hasName("typedefDeclTest"))));
|
||||
}
|
||||
|
||||
// FIXME: Figure out how to specify paths so the following tests pass on Windows.
|
||||
#ifndef LLVM_ON_WIN32
|
||||
|
||||
TEST(Matcher, IsExpansionInMainFileMatcher) {
|
||||
EXPECT_TRUE(matches("class X {};",
|
||||
recordDecl(hasName("X"), isExpansionInMainFile())));
|
||||
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInMainFile())));
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/other", "class X {};"));
|
||||
EXPECT_TRUE(matchesConditionally("#include <other>\n",
|
||||
recordDecl(isExpansionInMainFile()), false,
|
||||
"-isystem/", M));
|
||||
}
|
||||
|
||||
TEST(Matcher, IsExpansionInSystemHeader) {
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/other", "class X {};"));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include \"other\"\n", recordDecl(isExpansionInSystemHeader()), true,
|
||||
"-isystem/", M));
|
||||
EXPECT_TRUE(matchesConditionally("#include \"other\"\n",
|
||||
recordDecl(isExpansionInSystemHeader()),
|
||||
false, "-I/", M));
|
||||
EXPECT_TRUE(notMatches("class X {};",
|
||||
recordDecl(isExpansionInSystemHeader())));
|
||||
EXPECT_TRUE(notMatches("", recordDecl(isExpansionInSystemHeader())));
|
||||
}
|
||||
|
||||
TEST(Matcher, IsExpansionInFileMatching) {
|
||||
FileContentMappings M;
|
||||
M.push_back(std::make_pair("/foo", "class A {};"));
|
||||
M.push_back(std::make_pair("/bar", "class B {};"));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include <foo>\n"
|
||||
"#include <bar>\n"
|
||||
"class X {};",
|
||||
recordDecl(isExpansionInFileMatching("b.*"), hasName("B")), true,
|
||||
"-isystem/", M));
|
||||
EXPECT_TRUE(matchesConditionally(
|
||||
"#include <foo>\n"
|
||||
"#include <bar>\n"
|
||||
"class X {};",
|
||||
recordDecl(isExpansionInFileMatching("f.*"), hasName("X")), false,
|
||||
"-isystem/", M));
|
||||
}
|
||||
|
||||
#endif // LLVM_ON_WIN32
|
||||
|
||||
} // end namespace ast_matchers
|
||||
} // end namespace clang
|
||||
|
|
|
@ -22,6 +22,7 @@ using clang::tooling::buildASTFromCodeWithArgs;
|
|||
using clang::tooling::newFrontendActionFactory;
|
||||
using clang::tooling::runToolOnCodeWithArgs;
|
||||
using clang::tooling::FrontendActionFactory;
|
||||
using clang::tooling::FileContentMappings;
|
||||
|
||||
class BoundNodesCallback {
|
||||
public:
|
||||
|
@ -58,10 +59,10 @@ private:
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
testing::AssertionResult matchesConditionally(const std::string &Code,
|
||||
const T &AMatcher,
|
||||
bool ExpectMatch,
|
||||
llvm::StringRef CompileArg) {
|
||||
testing::AssertionResult matchesConditionally(
|
||||
const std::string &Code, const T &AMatcher, bool ExpectMatch,
|
||||
llvm::StringRef CompileArg,
|
||||
const FileContentMappings &VirtualMappedFiles = FileContentMappings()) {
|
||||
bool Found = false, DynamicFound = false;
|
||||
MatchFinder Finder;
|
||||
VerifyMatch VerifyFound(nullptr, &Found);
|
||||
|
@ -73,7 +74,8 @@ testing::AssertionResult matchesConditionally(const std::string &Code,
|
|||
newFrontendActionFactory(&Finder));
|
||||
// Some tests use typeof, which is a gnu extension.
|
||||
std::vector<std::string> Args(1, CompileArg);
|
||||
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args)) {
|
||||
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, "input.cc",
|
||||
VirtualMappedFiles)) {
|
||||
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
|
||||
}
|
||||
if (Found != DynamicFound) {
|
||||
|
|
Loading…
Reference in New Issue