summaryrefslogtreecommitdiffstats
path: root/unittests/AST
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/AST')
-rw-r--r--unittests/AST/ASTContextParentMapTest.cpp71
-rw-r--r--unittests/AST/CMakeLists.txt1
-rw-r--r--unittests/AST/CommentLexer.cpp168
-rw-r--r--unittests/AST/CommentParser.cpp18
-rw-r--r--unittests/AST/DeclPrinterTest.cpp47
-rw-r--r--unittests/AST/Makefile6
-rw-r--r--unittests/AST/MatchVerifier.h196
-rw-r--r--unittests/AST/SourceLocationTest.cpp202
-rw-r--r--unittests/AST/StmtPrinterTest.cpp11
9 files changed, 490 insertions, 230 deletions
diff --git a/unittests/AST/ASTContextParentMapTest.cpp b/unittests/AST/ASTContextParentMapTest.cpp
new file mode 100644
index 0000000..c1910a8
--- /dev/null
+++ b/unittests/AST/ASTContextParentMapTest.cpp
@@ -0,0 +1,71 @@
+//===- unittest/AST/ASTContextParentMapTest.cpp - AST parent map test -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tests for the getParents(...) methods of ASTContext.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+#include "MatchVerifier.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using clang::tooling::newFrontendActionFactory;
+using clang::tooling::runToolOnCodeWithArgs;
+using clang::tooling::FrontendActionFactory;
+
+TEST(GetParents, ReturnsParentForDecl) {
+ MatchVerifier<Decl> Verifier;
+ EXPECT_TRUE(Verifier.match("class C { void f(); };",
+ methodDecl(hasParent(recordDecl(hasName("C"))))));
+}
+
+TEST(GetParents, ReturnsParentForStmt) {
+ MatchVerifier<Stmt> Verifier;
+ EXPECT_TRUE(Verifier.match("class C { void f() { if (true) {} } };",
+ ifStmt(hasParent(compoundStmt()))));
+}
+
+TEST(GetParents, ReturnsParentInsideTemplateInstantiations) {
+ MatchVerifier<Decl> DeclVerifier;
+ EXPECT_TRUE(DeclVerifier.match(
+ "template<typename T> struct C { void f() {} };"
+ "void g() { C<int> c; c.f(); }",
+ methodDecl(hasName("f"),
+ hasParent(recordDecl(isTemplateInstantiation())))));
+ EXPECT_TRUE(DeclVerifier.match(
+ "template<typename T> struct C { void f() {} };"
+ "void g() { C<int> c; c.f(); }",
+ methodDecl(hasName("f"),
+ hasParent(recordDecl(unless(isTemplateInstantiation()))))));
+ EXPECT_FALSE(DeclVerifier.match(
+ "template<typename T> struct C { void f() {} };"
+ "void g() { C<int> c; c.f(); }",
+ methodDecl(hasName("f"),
+ allOf(hasParent(recordDecl(unless(isTemplateInstantiation()))),
+ hasParent(recordDecl(isTemplateInstantiation()))))));
+}
+
+TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) {
+ MatchVerifier<Stmt> TemplateVerifier;
+ EXPECT_TRUE(TemplateVerifier.match(
+ "template<typename T> struct C { void f() {} };"
+ "void g() { C<int> c; c.f(); }",
+ compoundStmt(
+ allOf(hasAncestor(recordDecl(isTemplateInstantiation())),
+ hasAncestor(recordDecl(unless(isTemplateInstantiation())))))));
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 1ea293e..ad29428 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -1,4 +1,5 @@
add_clang_unittest(ASTTests
+ ASTContextParentMapTest.cpp
CommentLexer.cpp
CommentParser.cpp
DeclPrinterTest.cpp
diff --git a/unittests/AST/CommentLexer.cpp b/unittests/AST/CommentLexer.cpp
index 2723a61..507daf8 100644
--- a/unittests/AST/CommentLexer.cpp
+++ b/unittests/AST/CommentLexer.cpp
@@ -7,16 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
#include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentCommandTraits.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/STLExtras.h"
-#include <vector>
-
#include "gtest/gtest.h"
+#include <vector>
using namespace llvm;
using namespace clang;
@@ -32,7 +32,7 @@ protected:
DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr),
- Traits(Allocator) {
+ Traits(Allocator, CommentOptions()) {
}
FileSystemOptions FileMgrOpts;
@@ -301,8 +301,10 @@ TEST_F(CommentLexerTest, DoxygenCommand3) {
// Doxygen escape sequences.
TEST_F(CommentLexerTest, DoxygenCommand4) {
- const char *Source =
- "/// \\\\ \\@ \\& \\$ \\# \\< \\> \\% \\\" \\. \\::";
+ const char *Sources[] = {
+ "/// \\\\ \\@ \\& \\$ \\# \\< \\> \\% \\\" \\. \\::",
+ "/// @\\ @@ @& @$ @# @< @> @% @\" @. @::"
+ };
const char *Text[] = {
" ",
"\\", " ", "@", " ", "&", " ", "$", " ", "#", " ",
@@ -310,16 +312,18 @@ TEST_F(CommentLexerTest, DoxygenCommand4) {
"::", ""
};
- std::vector<Token> Toks;
+ for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
+ std::vector<Token> Toks;
- lexString(Source, Toks);
+ lexString(Sources[i], Toks);
- ASSERT_EQ(array_lengthof(Text), Toks.size());
+ ASSERT_EQ(array_lengthof(Text), Toks.size());
- for (size_t i = 0, e = Toks.size(); i != e; i++) {
- if(Toks[i].is(tok::text))
- ASSERT_EQ(StringRef(Text[i]), Toks[i].getText())
- << "index " << i;
+ for (size_t j = 0, e = Toks.size(); j != e; j++) {
+ if(Toks[j].is(tok::text))
+ ASSERT_EQ(StringRef(Text[j]), Toks[j].getText())
+ << "index " << i;
+ }
}
}
@@ -362,7 +366,7 @@ TEST_F(CommentLexerTest, DoxygenCommand6) {
ASSERT_EQ(tok::text, Toks[0].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
- ASSERT_EQ(tok::command, Toks[1].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
ASSERT_EQ(StringRef("brief"), getCommandName(Toks[1]));
ASSERT_EQ(tok::text, Toks[2].getKind());
@@ -382,28 +386,60 @@ TEST_F(CommentLexerTest, DoxygenCommand7) {
ASSERT_EQ(tok::text, Toks[0].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
- ASSERT_EQ(tok::command, Toks[1].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
ASSERT_EQ(StringRef("em"), getCommandName(Toks[1]));
- ASSERT_EQ(tok::command, Toks[2].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[2].getKind());
ASSERT_EQ(StringRef("em"), getCommandName(Toks[2]));
ASSERT_EQ(tok::text, Toks[3].getKind());
ASSERT_EQ(StringRef(" "), Toks[3].getText());
- ASSERT_EQ(tok::command, Toks[4].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[4].getKind());
ASSERT_EQ(StringRef("em"), getCommandName(Toks[4]));
ASSERT_EQ(tok::text, Toks[5].getKind());
ASSERT_EQ(StringRef("\t"), Toks[5].getText());
- ASSERT_EQ(tok::command, Toks[6].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[6].getKind());
ASSERT_EQ(StringRef("em"), getCommandName(Toks[6]));
ASSERT_EQ(tok::newline, Toks[7].getKind());
}
TEST_F(CommentLexerTest, DoxygenCommand8) {
+ const char *Source = "/// @em@em @em\t@em\n";
+ std::vector<Token> Toks;
+
+ lexString(Source, Toks);
+
+ ASSERT_EQ(8U, Toks.size());
+
+ ASSERT_EQ(tok::text, Toks[0].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[0].getText());
+
+ ASSERT_EQ(tok::at_command, Toks[1].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[1]));
+
+ ASSERT_EQ(tok::at_command, Toks[2].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[2]));
+
+ ASSERT_EQ(tok::text, Toks[3].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[3].getText());
+
+ ASSERT_EQ(tok::at_command, Toks[4].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[4]));
+
+ ASSERT_EQ(tok::text, Toks[5].getKind());
+ ASSERT_EQ(StringRef("\t"), Toks[5].getText());
+
+ ASSERT_EQ(tok::at_command, Toks[6].getKind());
+ ASSERT_EQ(StringRef("em"), getCommandName(Toks[6]));
+
+ ASSERT_EQ(tok::newline, Toks[7].getKind());
+}
+
+TEST_F(CommentLexerTest, DoxygenCommand9) {
const char *Source = "/// \\aaa\\bbb \\ccc\t\\ddd\n";
std::vector<Token> Toks;
@@ -435,7 +471,7 @@ TEST_F(CommentLexerTest, DoxygenCommand8) {
ASSERT_EQ(tok::newline, Toks[7].getKind());
}
-TEST_F(CommentLexerTest, DoxygenCommand9) {
+TEST_F(CommentLexerTest, DoxygenCommand10) {
const char *Source = "// \\c\n";
std::vector<Token> Toks;
@@ -446,12 +482,95 @@ TEST_F(CommentLexerTest, DoxygenCommand9) {
ASSERT_EQ(tok::text, Toks[0].getKind());
ASSERT_EQ(StringRef(" "), Toks[0].getText());
- ASSERT_EQ(tok::command, Toks[1].getKind());
+ ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
ASSERT_EQ(StringRef("c"), getCommandName(Toks[1]));
ASSERT_EQ(tok::newline, Toks[2].getKind());
}
+TEST_F(CommentLexerTest, RegisterCustomBlockCommand) {
+ const char *Source =
+ "/// \\NewBlockCommand Aaa.\n"
+ "/// @NewBlockCommand Aaa.\n";
+
+ Traits.registerBlockCommand(StringRef("NewBlockCommand"));
+
+ std::vector<Token> Toks;
+
+ lexString(Source, Toks);
+
+ ASSERT_EQ(8U, Toks.size());
+
+ ASSERT_EQ(tok::text, Toks[0].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[0].getText());
+
+ ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
+ ASSERT_EQ(StringRef("NewBlockCommand"), getCommandName(Toks[1]));
+
+ ASSERT_EQ(tok::text, Toks[2].getKind());
+ ASSERT_EQ(StringRef(" Aaa."), Toks[2].getText());
+
+ ASSERT_EQ(tok::newline, Toks[3].getKind());
+
+ ASSERT_EQ(tok::text, Toks[4].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[4].getText());
+
+ ASSERT_EQ(tok::at_command, Toks[5].getKind());
+ ASSERT_EQ(StringRef("NewBlockCommand"), getCommandName(Toks[5]));
+
+ ASSERT_EQ(tok::text, Toks[6].getKind());
+ ASSERT_EQ(StringRef(" Aaa."), Toks[6].getText());
+
+ ASSERT_EQ(tok::newline, Toks[7].getKind());
+}
+
+TEST_F(CommentLexerTest, RegisterMultipleBlockCommands) {
+ const char *Source =
+ "/// \\Foo\n"
+ "/// \\Bar Baz\n"
+ "/// \\Blech quux=corge\n";
+
+ Traits.registerBlockCommand(StringRef("Foo"));
+ Traits.registerBlockCommand(StringRef("Bar"));
+ Traits.registerBlockCommand(StringRef("Blech"));
+
+ std::vector<Token> Toks;
+
+ lexString(Source, Toks);
+
+ ASSERT_EQ(11U, Toks.size());
+
+ ASSERT_EQ(tok::text, Toks[0].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[0].getText());
+
+ ASSERT_EQ(tok::backslash_command, Toks[1].getKind());
+ ASSERT_EQ(StringRef("Foo"), getCommandName(Toks[1]));
+
+ ASSERT_EQ(tok::newline, Toks[2].getKind());
+
+ ASSERT_EQ(tok::text, Toks[3].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[3].getText());
+
+ ASSERT_EQ(tok::backslash_command, Toks[4].getKind());
+ ASSERT_EQ(StringRef("Bar"), getCommandName(Toks[4]));
+
+ ASSERT_EQ(tok::text, Toks[5].getKind());
+ ASSERT_EQ(StringRef(" Baz"), Toks[5].getText());
+
+ ASSERT_EQ(tok::newline, Toks[6].getKind());
+
+ ASSERT_EQ(tok::text, Toks[7].getKind());
+ ASSERT_EQ(StringRef(" "), Toks[7].getText());
+
+ ASSERT_EQ(tok::backslash_command, Toks[8].getKind());
+ ASSERT_EQ(StringRef("Blech"), getCommandName(Toks[8]));
+
+ ASSERT_EQ(tok::text, Toks[9].getKind());
+ ASSERT_EQ(StringRef(" quux=corge"), Toks[9].getText());
+
+ ASSERT_EQ(tok::newline, Toks[10].getKind());
+}
+
// Empty verbatim block.
TEST_F(CommentLexerTest, VerbatimBlock1) {
const char *Sources[] = {
@@ -1662,7 +1781,8 @@ TEST_F(CommentLexerTest, HTMLCharacterReferences16) {
const char *Sources[] = {
"// &#61;",
"// &#x3d;",
- "// &#X3d;"
+ "// &#X3d;",
+ "// &#X3D;"
};
for (size_t i = 0, e = array_lengthof(Sources); i != e; i++) {
diff --git a/unittests/AST/CommentParser.cpp b/unittests/AST/CommentParser.cpp
index 8fde247..3dce60a 100644
--- a/unittests/AST/CommentParser.cpp
+++ b/unittests/AST/CommentParser.cpp
@@ -7,20 +7,20 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/AST/CommentParser.h"
#include "clang/AST/Comment.h"
+#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentLexer.h"
-#include "clang/AST/CommentParser.h"
#include "clang/AST/CommentSema.h"
-#include "clang/AST/CommentCommandTraits.h"
+#include "clang/Basic/CommentOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
-#include <vector>
-
#include "gtest/gtest.h"
+#include <vector>
using namespace llvm;
using namespace clang;
@@ -39,7 +39,7 @@ protected:
DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr),
- Traits(Allocator) {
+ Traits(Allocator, CommentOptions()) {
}
FileSystemOptions FileMgrOpts;
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
index a2fc839..44fa742 100644
--- a/unittests/AST/DeclPrinterTest.cpp
+++ b/unittests/AST/DeclPrinterTest.cpp
@@ -412,8 +412,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl1) {
" A();"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A();"
+ "A()"));
}
TEST(DeclPrinter, TestCXXConstructorDecl2) {
@@ -422,8 +421,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl2) {
" A(int a);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A(int a);"
+ "A(int a)"));
}
TEST(DeclPrinter, TestCXXConstructorDecl3) {
@@ -432,8 +430,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl3) {
" A(const A &a);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A(const A &a);"
+ "A(const A &a)"));
}
TEST(DeclPrinter, TestCXXConstructorDecl4) {
@@ -442,8 +439,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl4) {
" A(const A &a, int = 0);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A(const A &a, int = 0);"
+ "A(const A &a, int = 0)"));
}
TEST(DeclPrinter, TestCXXConstructorDecl5) {
@@ -452,8 +448,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl5) {
" A(const A &&a);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A(const A &&a);"
+ "A(const A &&a)"));
}
TEST(DeclPrinter, TestCXXConstructorDecl6) {
@@ -462,8 +457,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl6) {
" explicit A(int a);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "explicit A(int a);"
+ "explicit A(int a)"));
}
TEST(DeclPrinter, TestCXXConstructorDecl7) {
@@ -472,7 +466,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl7) {
" constexpr A();"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
+ "A()"));
// WRONG; Should be: "constexpr A();"
}
@@ -482,8 +476,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl8) {
" A() = default;"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A() = default;"
+ "A() = default"));
}
TEST(DeclPrinter, TestCXXConstructorDecl9) {
@@ -492,8 +485,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl9) {
" A() = delete;"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- " = delete"));
- // WRONG; Should be: "A() = delete;"
+ "A() = delete"));
}
TEST(DeclPrinter, TestCXXConstructorDecl10) {
@@ -503,8 +495,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl10) {
" A(const A &a);"
"};",
constructorDecl(ofClass(hasName("A"))).bind("id"),
- ""));
- // WRONG; Should be: "A(const A &a);"
+ "A<T...>(const A<T...> &a)"));
}
#if !defined(_MSC_VER)
@@ -1246,3 +1237,21 @@ TEST(DeclPrinter, TestObjCMethod1) {
"- (int) A:(id)anObject inRange:(long)range"));
}
+TEST(DeclPrinter, TestObjCProtocol1) {
+ ASSERT_TRUE(PrintedDeclObjCMatches(
+ "@protocol P1, P2;",
+ namedDecl(hasName("P1")).bind("id"),
+ "@protocol P1;\n"));
+ ASSERT_TRUE(PrintedDeclObjCMatches(
+ "@protocol P1, P2;",
+ namedDecl(hasName("P2")).bind("id"),
+ "@protocol P2;\n"));
+}
+
+TEST(DeclPrinter, TestObjCProtocol2) {
+ ASSERT_TRUE(PrintedDeclObjCMatches(
+ "@protocol P2 @end"
+ "@protocol P1<P2> @end",
+ namedDecl(hasName("P1")).bind("id"),
+ "@protocol P1<P2>\n@end"));
+}
diff --git a/unittests/AST/Makefile b/unittests/AST/Makefile
index e07fc45..4fb2f5b 100644
--- a/unittests/AST/Makefile
+++ b/unittests/AST/Makefile
@@ -10,10 +10,10 @@
CLANG_LEVEL = ../..
TESTNAME = AST
include $(CLANG_LEVEL)/../../Makefile.config
-LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc
USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
clangRewriteCore.a clangRewriteFrontend.a \
- clangParse.a clangSema.a clangAnalysis.a \
- clangAST.a clangASTMatchers.a clangLex.a clangBasic.a clangEdit.a
+ clangParse.a clangSema.a clangAnalysis.a \
+ clangEdit.a clangAST.a clangASTMatchers.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/unittests/AST/MatchVerifier.h b/unittests/AST/MatchVerifier.h
new file mode 100644
index 0000000..7aa7886
--- /dev/null
+++ b/unittests/AST/MatchVerifier.h
@@ -0,0 +1,196 @@
+//===- unittest/AST/MatchVerifier.h - AST unit test support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides MatchVerifier, a base class to implement gtest matchers that
+// verify things that can be matched on the AST.
+//
+// Also implements matchers based on MatchVerifier:
+// LocationVerifier and RangeVerifier to verify whether a matched node has
+// the expected source location or source range.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+enum Language { Lang_C, Lang_C89, Lang_CXX, Lang_OpenCL };
+
+/// \brief Base class for verifying some property of nodes found by a matcher.
+template <typename NodeType>
+class MatchVerifier : public MatchFinder::MatchCallback {
+public:
+ template <typename MatcherType>
+ testing::AssertionResult match(const std::string &Code,
+ const MatcherType &AMatcher) {
+ return match(Code, AMatcher, Lang_CXX);
+ }
+
+ template <typename MatcherType>
+ testing::AssertionResult match(const std::string &Code,
+ const MatcherType &AMatcher, Language L);
+
+protected:
+ virtual void run(const MatchFinder::MatchResult &Result);
+ virtual void verify(const MatchFinder::MatchResult &Result,
+ const NodeType &Node) {}
+
+ void setFailure(const Twine &Result) {
+ Verified = false;
+ VerifyResult = Result.str();
+ }
+
+ void setSuccess() {
+ Verified = true;
+ }
+
+private:
+ bool Verified;
+ std::string VerifyResult;
+};
+
+/// \brief Runs a matcher over some code, and returns the result of the
+/// verifier for the matched node.
+template <typename NodeType> template <typename MatcherType>
+testing::AssertionResult MatchVerifier<NodeType>::match(
+ const std::string &Code, const MatcherType &AMatcher, Language L) {
+ MatchFinder Finder;
+ Finder.addMatcher(AMatcher.bind(""), this);
+ OwningPtr<tooling::FrontendActionFactory> Factory(
+ tooling::newFrontendActionFactory(&Finder));
+
+ std::vector<std::string> Args;
+ StringRef FileName;
+ switch (L) {
+ case Lang_C:
+ Args.push_back("-std=c99");
+ FileName = "input.c";
+ break;
+ case Lang_C89:
+ Args.push_back("-std=c89");
+ FileName = "input.c";
+ break;
+ case Lang_CXX:
+ Args.push_back("-std=c++98");
+ FileName = "input.cc";
+ break;
+ case Lang_OpenCL:
+ FileName = "input.cl";
+ }
+
+ // Default to failure in case callback is never called
+ setFailure("Could not find match");
+ if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
+ return testing::AssertionFailure() << "Parsing error";
+ if (!Verified)
+ return testing::AssertionFailure() << VerifyResult;
+ return testing::AssertionSuccess();
+}
+
+template <typename NodeType>
+void MatchVerifier<NodeType>::run(const MatchFinder::MatchResult &Result) {
+ const NodeType *Node = Result.Nodes.getNodeAs<NodeType>("");
+ if (!Node) {
+ setFailure("Matched node has wrong type");
+ } else {
+ // Callback has been called, default to success.
+ setSuccess();
+ verify(Result, *Node);
+ }
+}
+
+/// \brief Verify whether a node has the correct source location.
+///
+/// By default, Node.getSourceLocation() is checked. This can be changed
+/// by overriding getLocation().
+template <typename NodeType>
+class LocationVerifier : public MatchVerifier<NodeType> {
+public:
+ void expectLocation(unsigned Line, unsigned Column) {
+ ExpectLine = Line;
+ ExpectColumn = Column;
+ }
+
+protected:
+ void verify(const MatchFinder::MatchResult &Result, const NodeType &Node) {
+ SourceLocation Loc = getLocation(Node);
+ unsigned Line = Result.SourceManager->getSpellingLineNumber(Loc);
+ unsigned Column = Result.SourceManager->getSpellingColumnNumber(Loc);
+ if (Line != ExpectLine || Column != ExpectColumn) {
+ std::string MsgStr;
+ llvm::raw_string_ostream Msg(MsgStr);
+ Msg << "Expected location <" << ExpectLine << ":" << ExpectColumn
+ << ">, found <";
+ Loc.print(Msg, *Result.SourceManager);
+ Msg << '>';
+ this->setFailure(Msg.str());
+ }
+ }
+
+ virtual SourceLocation getLocation(const NodeType &Node) {
+ return Node.getLocation();
+ }
+
+private:
+ unsigned ExpectLine, ExpectColumn;
+};
+
+/// \brief Verify whether a node has the correct source range.
+///
+/// By default, Node.getSourceRange() is checked. This can be changed
+/// by overriding getRange().
+template <typename NodeType>
+class RangeVerifier : public MatchVerifier<NodeType> {
+public:
+ void expectRange(unsigned BeginLine, unsigned BeginColumn,
+ unsigned EndLine, unsigned EndColumn) {
+ ExpectBeginLine = BeginLine;
+ ExpectBeginColumn = BeginColumn;
+ ExpectEndLine = EndLine;
+ ExpectEndColumn = EndColumn;
+ }
+
+protected:
+ void verify(const MatchFinder::MatchResult &Result, const NodeType &Node) {
+ SourceRange R = getRange(Node);
+ SourceLocation Begin = R.getBegin();
+ SourceLocation End = R.getEnd();
+ unsigned BeginLine = Result.SourceManager->getSpellingLineNumber(Begin);
+ unsigned BeginColumn = Result.SourceManager->getSpellingColumnNumber(Begin);
+ unsigned EndLine = Result.SourceManager->getSpellingLineNumber(End);
+ unsigned EndColumn = Result.SourceManager->getSpellingColumnNumber(End);
+ if (BeginLine != ExpectBeginLine || BeginColumn != ExpectBeginColumn ||
+ EndLine != ExpectEndLine || EndColumn != ExpectEndColumn) {
+ std::string MsgStr;
+ llvm::raw_string_ostream Msg(MsgStr);
+ Msg << "Expected range <" << ExpectBeginLine << ":" << ExpectBeginColumn
+ << '-' << ExpectEndLine << ":" << ExpectEndColumn << ">, found <";
+ Begin.print(Msg, *Result.SourceManager);
+ Msg << '-';
+ End.print(Msg, *Result.SourceManager);
+ Msg << '>';
+ this->setFailure(Msg.str());
+ }
+ }
+
+ virtual SourceRange getRange(const NodeType &Node) {
+ return Node.getSourceRange();
+ }
+
+private:
+ unsigned ExpectBeginLine, ExpectBeginColumn, ExpectEndLine, ExpectEndColumn;
+};
+
+} // end namespace ast_matchers
+} // end namespace clang
diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp
index dec833d..b8d8b02 100644
--- a/unittests/AST/SourceLocationTest.cpp
+++ b/unittests/AST/SourceLocationTest.cpp
@@ -17,179 +17,16 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
+#include "MatchVerifier.h"
namespace clang {
namespace ast_matchers {
-using clang::tooling::newFrontendActionFactory;
-using clang::tooling::runToolOnCodeWithArgs;
-using clang::tooling::FrontendActionFactory;
-
-enum Language { Lang_C, Lang_C89, Lang_CXX };
-
-/// \brief Base class for verifying some property of nodes found by a matcher.
-///
-/// FIXME: This class should be shared with other AST tests.
-template <typename NodeType>
-class MatchVerifier : public MatchFinder::MatchCallback {
-public:
- template <typename MatcherType>
- testing::AssertionResult match(const std::string &Code,
- const MatcherType &AMatcher) {
- return match(Code, AMatcher, Lang_CXX);
- }
-
- template <typename MatcherType>
- testing::AssertionResult match(const std::string &Code,
- const MatcherType &AMatcher, Language L);
-
-protected:
- virtual void run(const MatchFinder::MatchResult &Result);
- virtual void verify(const MatchFinder::MatchResult &Result,
- const NodeType &Node) = 0;
-
- void setFailure(const Twine &Result) {
- Verified = false;
- VerifyResult = Result.str();
- }
-
-private:
- bool Verified;
- std::string VerifyResult;
-};
-
-/// \brief Runs a matcher over some code, and returns the result of the
-/// verifier for the matched node.
-template <typename NodeType> template <typename MatcherType>
-testing::AssertionResult MatchVerifier<NodeType>::match(
- const std::string &Code, const MatcherType &AMatcher, Language L) {
- MatchFinder Finder;
- Finder.addMatcher(AMatcher.bind(""), this);
- OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
-
- std::vector<std::string> Args;
- StringRef FileName;
- switch (L) {
- case Lang_C:
- Args.push_back("-std=c99");
- FileName = "input.c";
- break;
- case Lang_C89:
- Args.push_back("-std=c89");
- FileName = "input.c";
- break;
- case Lang_CXX:
- Args.push_back("-std=c++98");
- FileName = "input.cc";
- break;
- }
-
- // Default to failure in case callback is never called
- setFailure("Could not find match");
- if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
- return testing::AssertionFailure() << "Parsing error";
- if (!Verified)
- return testing::AssertionFailure() << VerifyResult;
- return testing::AssertionSuccess();
-}
-
-template <typename NodeType>
-void MatchVerifier<NodeType>::run(const MatchFinder::MatchResult &Result) {
- const NodeType *Node = Result.Nodes.getNodeAs<NodeType>("");
- if (!Node) {
- setFailure("Matched node has wrong type");
- } else {
- // Callback has been called, default to success
- Verified = true;
- verify(Result, *Node);
- }
-}
-
-/// \brief Verify whether a node has the correct source location.
-///
-/// By default, Node.getSourceLocation() is checked. This can be changed
-/// by overriding getLocation().
-template <typename NodeType>
-class LocationVerifier : public MatchVerifier<NodeType> {
-public:
- void expectLocation(unsigned Line, unsigned Column) {
- ExpectLine = Line;
- ExpectColumn = Column;
- }
-
-protected:
- void verify(const MatchFinder::MatchResult &Result, const NodeType &Node) {
- SourceLocation Loc = getLocation(Node);
- unsigned Line = Result.SourceManager->getSpellingLineNumber(Loc);
- unsigned Column = Result.SourceManager->getSpellingColumnNumber(Loc);
- if (Line != ExpectLine || Column != ExpectColumn) {
- std::string MsgStr;
- llvm::raw_string_ostream Msg(MsgStr);
- Msg << "Expected location <" << ExpectLine << ":" << ExpectColumn
- << ">, found <";
- Loc.print(Msg, *Result.SourceManager);
- Msg << '>';
- this->setFailure(Msg.str());
- }
- }
-
- virtual SourceLocation getLocation(const NodeType &Node) {
- return Node.getLocation();
- }
-
-private:
- unsigned ExpectLine, ExpectColumn;
-};
-
-/// \brief Verify whether a node has the correct source range.
-///
-/// By default, Node.getSourceRange() is checked. This can be changed
-/// by overriding getRange().
-template <typename NodeType>
-class RangeVerifier : public MatchVerifier<NodeType> {
-public:
- void expectRange(unsigned BeginLine, unsigned BeginColumn,
- unsigned EndLine, unsigned EndColumn) {
- ExpectBeginLine = BeginLine;
- ExpectBeginColumn = BeginColumn;
- ExpectEndLine = EndLine;
- ExpectEndColumn = EndColumn;
- }
-
-protected:
- void verify(const MatchFinder::MatchResult &Result, const NodeType &Node) {
- SourceRange R = getRange(Node);
- SourceLocation Begin = R.getBegin();
- SourceLocation End = R.getEnd();
- unsigned BeginLine = Result.SourceManager->getSpellingLineNumber(Begin);
- unsigned BeginColumn = Result.SourceManager->getSpellingColumnNumber(Begin);
- unsigned EndLine = Result.SourceManager->getSpellingLineNumber(End);
- unsigned EndColumn = Result.SourceManager->getSpellingColumnNumber(End);
- if (BeginLine != ExpectBeginLine || BeginColumn != ExpectBeginColumn ||
- EndLine != ExpectEndLine || EndColumn != ExpectEndColumn) {
- std::string MsgStr;
- llvm::raw_string_ostream Msg(MsgStr);
- Msg << "Expected range <" << ExpectBeginLine << ":" << ExpectBeginColumn
- << '-' << ExpectEndLine << ":" << ExpectEndColumn << ">, found <";
- Begin.print(Msg, *Result.SourceManager);
- Msg << '-';
- End.print(Msg, *Result.SourceManager);
- Msg << '>';
- this->setFailure(Msg.str());
- }
- }
-
- virtual SourceRange getRange(const NodeType &Node) {
- return Node.getSourceRange();
- }
-
-private:
- unsigned ExpectBeginLine, ExpectBeginColumn, ExpectEndLine, ExpectEndColumn;
-};
+// FIXME: Pull the *Verifier tests into their own test file.
TEST(MatchVerifier, ParseError) {
LocationVerifier<VarDecl> Verifier;
@@ -285,5 +122,38 @@ TEST(CXXConstructorDecl, NoRetFunTypeLocRange) {
EXPECT_TRUE(Verifier.match("class C { C(); };", functionDecl()));
}
+TEST(CompoundLiteralExpr, CompoundVectorLiteralRange) {
+ RangeVerifier<CompoundLiteralExpr> Verifier;
+ Verifier.expectRange(2, 11, 2, 22);
+ EXPECT_TRUE(Verifier.match(
+ "typedef int int2 __attribute__((ext_vector_type(2)));\n"
+ "int2 i2 = (int2){1, 2};", compoundLiteralExpr()));
+}
+
+TEST(CompoundLiteralExpr, ParensCompoundVectorLiteralRange) {
+ RangeVerifier<CompoundLiteralExpr> Verifier;
+ Verifier.expectRange(2, 11, 2, 22);
+ EXPECT_TRUE(Verifier.match(
+ "typedef int int2 __attribute__((ext_vector_type(2)));\n"
+ "int2 i2 = (int2)(1, 2);",
+ compoundLiteralExpr(), Lang_OpenCL));
+}
+
+TEST(InitListExpr, VectorLiteralListBraceRange) {
+ RangeVerifier<InitListExpr> Verifier;
+ Verifier.expectRange(2, 17, 2, 22);
+ EXPECT_TRUE(Verifier.match(
+ "typedef int int2 __attribute__((ext_vector_type(2)));\n"
+ "int2 i2 = (int2){1, 2};", initListExpr()));
+}
+
+TEST(InitListExpr, VectorLiteralInitListParens) {
+ RangeVerifier<InitListExpr> Verifier;
+ Verifier.expectRange(2, 17, 2, 22);
+ EXPECT_TRUE(Verifier.match(
+ "typedef int int2 __attribute__((ext_vector_type(2)));\n"
+ "int2 i2 = (int2)(1, 2);", initListExpr(), Lang_OpenCL));
+}
+
} // end namespace ast_matchers
} // end namespace clang
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index 0fd1b2e..473ee13 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -146,20 +146,14 @@ TEST(StmtPrinter, TestMSIntegerLiteral) {
" 1i8, -1i8, 1ui8, "
" 1i16, -1i16, 1ui16, "
" 1i32, -1i32, 1ui32, "
- " 1i64, -1i64, 1ui64, "
- " 1i128, -1i128, 1ui128, 1Ui128,"
- " 0x10000000000000000i128;"
+ " 1i64, -1i64, 1ui64;"
"}",
"A",
"1 , -1 , 1U , "
"1 , -1 , 1U , "
"1L , -1L , 1UL , "
- "1LL , -1LL , 1ULL , "
- "1 , -1 , 1U , 1U , "
- "18446744073709551616i128"));
+ "1LL , -1LL , 1ULL"));
// Should be: with semicolon
- // WRONG; all 128-bit literals should be printed as 128-bit.
- // (This is because currently we do semantic analysis incorrectly.)
}
TEST(StmtPrinter, TestFloatingPointLiteral) {
@@ -169,4 +163,3 @@ TEST(StmtPrinter, TestFloatingPointLiteral) {
"1.F , -1.F , 1. , -1. , 1.L , -1.L"));
// Should be: with semicolon
}
-
OpenPOWER on IntegriCloud