aboutsummaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/AST/ASTContextParentMapTest.cpp39
-rw-r--r--unittests/AST/ASTTypeTraitsTest.cpp7
-rw-r--r--unittests/AST/DeclPrinterTest.cpp46
-rw-r--r--unittests/AST/NamedDeclPrinterTest.cpp42
-rw-r--r--unittests/AST/SourceLocationTest.cpp26
-rw-r--r--unittests/AST/StmtPrinterTest.cpp4
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp765
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.h14
-rw-r--r--unittests/ASTMatchers/Dynamic/ParserTest.cpp14
-rw-r--r--unittests/ASTMatchers/Dynamic/RegistryTest.cpp31
-rw-r--r--unittests/Basic/SourceManagerTest.cpp2
-rw-r--r--unittests/Basic/VirtualFileSystemTest.cpp172
-rw-r--r--unittests/CMakeLists.txt2
-rw-r--r--unittests/CodeGen/BufferSourceTest.cpp4
-rw-r--r--unittests/Driver/CMakeLists.txt2
-rw-r--r--unittests/Driver/ToolChainTest.cpp120
-rw-r--r--unittests/Format/CMakeLists.txt1
-rw-r--r--unittests/Format/FormatTest.cpp791
-rw-r--r--unittests/Format/FormatTestJS.cpp198
-rw-r--r--unittests/Format/FormatTestJava.cpp9
-rw-r--r--unittests/Format/FormatTestProto.cpp11
-rw-r--r--unittests/Format/FormatTestSelective.cpp68
-rw-r--r--unittests/Format/SortIncludesTest.cpp255
-rw-r--r--unittests/Lex/LexerTest.cpp2
-rw-r--r--unittests/Lex/PPCallbacksTest.cpp16
-rw-r--r--unittests/Lex/PPConditionalDirectiveRecordTest.cpp2
-rw-r--r--unittests/Tooling/CMakeLists.txt2
-rw-r--r--unittests/Tooling/CommentHandlerTest.cpp4
-rw-r--r--unittests/Tooling/CompilationDatabaseTest.cpp56
-rw-r--r--unittests/Tooling/LookupTest.cpp108
-rw-r--r--unittests/Tooling/RefactoringCallbacksTest.cpp4
-rw-r--r--unittests/Tooling/RefactoringTest.cpp114
-rw-r--r--unittests/Tooling/RewriterTestContext.h29
-rw-r--r--unittests/Tooling/ToolingTest.cpp117
-rw-r--r--unittests/libclang/LibclangTest.cpp29
35 files changed, 2621 insertions, 485 deletions
diff --git a/unittests/AST/ASTContextParentMapTest.cpp b/unittests/AST/ASTContextParentMapTest.cpp
index 0dcb175e07b31..b1d7db4164ef2 100644
--- a/unittests/AST/ASTContextParentMapTest.cpp
+++ b/unittests/AST/ASTContextParentMapTest.cpp
@@ -27,8 +27,9 @@ using clang::tooling::FrontendActionFactory;
TEST(GetParents, ReturnsParentForDecl) {
MatchVerifier<Decl> Verifier;
- EXPECT_TRUE(Verifier.match("class C { void f(); };",
- methodDecl(hasParent(recordDecl(hasName("C"))))));
+ EXPECT_TRUE(
+ Verifier.match("class C { void f(); };",
+ cxxMethodDecl(hasParent(recordDecl(hasName("C"))))));
}
TEST(GetParents, ReturnsParentForStmt) {
@@ -37,24 +38,38 @@ TEST(GetParents, ReturnsParentForStmt) {
ifStmt(hasParent(compoundStmt()))));
}
+TEST(GetParents, ReturnsParentForTypeLoc) {
+ MatchVerifier<TypeLoc> Verifier;
+ EXPECT_TRUE(
+ Verifier.match("namespace a { class b {}; } void f(a::b) {}",
+ typeLoc(hasParent(typeLoc(hasParent(functionDecl()))))));
+}
+
+TEST(GetParents, ReturnsParentForNestedNameSpecifierLoc) {
+ MatchVerifier<NestedNameSpecifierLoc> Verifier;
+ EXPECT_TRUE(Verifier.match("namespace a { class b {}; } void f(a::b) {}",
+ nestedNameSpecifierLoc(hasParent(typeLoc()))));
+}
+
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())))));
+ cxxMethodDecl(hasName("f"),
+ hasParent(cxxRecordDecl(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()))))));
+ cxxMethodDecl(hasName("f"),
+ hasParent(cxxRecordDecl(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()))))));
+ cxxMethodDecl(
+ hasName("f"),
+ allOf(hasParent(cxxRecordDecl(unless(isTemplateInstantiation()))),
+ hasParent(cxxRecordDecl(isTemplateInstantiation()))))));
}
TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) {
@@ -62,9 +77,9 @@ TEST(GetParents, ReturnsMultipleParentsInTemplateInstantiations) {
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())))))));
+ compoundStmt(allOf(
+ hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
+ hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
}
} // end namespace ast_matchers
diff --git a/unittests/AST/ASTTypeTraitsTest.cpp b/unittests/AST/ASTTypeTraitsTest.cpp
index eeb01ccad1dfe..b6356538a12ae 100644
--- a/unittests/AST/ASTTypeTraitsTest.cpp
+++ b/unittests/AST/ASTTypeTraitsTest.cpp
@@ -162,5 +162,12 @@ TEST(DynTypedNode, StmtPrint) {
EXPECT_TRUE(Verifier.match("void f() {}", stmt()));
}
+TEST(DynTypedNode, QualType) {
+ QualType Q;
+ DynTypedNode Node = DynTypedNode::create(Q);
+ EXPECT_TRUE(Node == Node);
+ EXPECT_FALSE(Node < Node);
+}
+
} // namespace ast_type_traits
} // namespace clang
diff --git a/unittests/AST/DeclPrinterTest.cpp b/unittests/AST/DeclPrinterTest.cpp
index d8cb97709229b..d06fbfea6f5e5 100644
--- a/unittests/AST/DeclPrinterTest.cpp
+++ b/unittests/AST/DeclPrinterTest.cpp
@@ -471,7 +471,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl1) {
"struct A {"
" A();"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A()"));
}
@@ -480,7 +480,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl2) {
"struct A {"
" A(int a);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A(int a)"));
}
@@ -489,7 +489,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl3) {
"struct A {"
" A(const A &a);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A(const A &a)"));
}
@@ -498,7 +498,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl4) {
"struct A {"
" A(const A &a, int = 0);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A(const A &a, int = 0)"));
}
@@ -507,7 +507,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl5) {
"struct A {"
" A(const A &&a);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A(const A &&a)"));
}
@@ -516,7 +516,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl6) {
"struct A {"
" explicit A(int a);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"explicit A(int a)"));
}
@@ -525,7 +525,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl7) {
"struct A {"
" constexpr A();"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"constexpr A()"));
}
@@ -534,7 +534,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl8) {
"struct A {"
" A() = default;"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A() = default"));
}
@@ -543,7 +543,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl9) {
"struct A {"
" A() = delete;"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A() = delete"));
}
@@ -553,7 +553,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl10) {
"struct A {"
" A(const A &a);"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A<T...>(const A<T...> &a)"));
// WRONG; Should be: "A(const A<T...> &a);"
}
@@ -564,7 +564,7 @@ TEST(DeclPrinter, TestCXXConstructorDecl11) {
"struct A : public T... {"
" A(T&&... ts) : T(ts)... {}"
"};",
- constructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxConstructorDecl(ofClass(hasName("A"))).bind("id"),
"A<T...>(T &&...ts) : T(ts)..."));
// WRONG; Should be: "A(T &&...ts) : T(ts)... {}"
}
@@ -574,7 +574,7 @@ TEST(DeclPrinter, TestCXXDestructorDecl1) {
"struct A {"
" ~A();"
"};",
- destructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxDestructorDecl(ofClass(hasName("A"))).bind("id"),
"~A()"));
}
@@ -583,7 +583,7 @@ TEST(DeclPrinter, TestCXXDestructorDecl2) {
"struct A {"
" virtual ~A();"
"};",
- destructorDecl(ofClass(hasName("A"))).bind("id"),
+ cxxDestructorDecl(ofClass(hasName("A"))).bind("id"),
"virtual ~A()"));
}
@@ -592,7 +592,7 @@ TEST(DeclPrinter, TestCXXConversionDecl1) {
"struct A {"
" operator int();"
"};",
- methodDecl(ofClass(hasName("A"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("A"))).bind("id"),
"operator int()"));
}
@@ -601,7 +601,7 @@ TEST(DeclPrinter, TestCXXConversionDecl2) {
"struct A {"
" operator bool();"
"};",
- methodDecl(ofClass(hasName("A"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("A"))).bind("id"),
"operator bool()"));
}
@@ -611,7 +611,7 @@ TEST(DeclPrinter, TestCXXConversionDecl3) {
"struct A {"
" operator Z();"
"};",
- methodDecl(ofClass(hasName("A"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("A"))).bind("id"),
"operator Z()"));
}
@@ -621,7 +621,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction1) {
"struct Z {"
" void *operator new(std::size_t);"
"};",
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void *operator new(std::size_t)"));
// Should be: with semicolon
}
@@ -632,7 +632,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction2) {
"struct Z {"
" void *operator new[](std::size_t);"
"};",
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void *operator new[](std::size_t)"));
// Should be: with semicolon
}
@@ -642,7 +642,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction3) {
"struct Z {"
" void operator delete(void *);"
"};",
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete(void *) noexcept"));
// Should be: with semicolon, without noexcept?
}
@@ -652,7 +652,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction4) {
"struct Z {"
" void operator delete(void *);"
"};",
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete(void *)"));
// Should be: with semicolon
}
@@ -662,7 +662,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_AllocationFunction5) {
"struct Z {"
" void operator delete[](void *);"
"};",
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
"void operator delete[](void *) noexcept"));
// Should be: with semicolon, without noexcept?
}
@@ -690,7 +690,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_Operator1) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
Code,
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
Expected));
}
}
@@ -714,7 +714,7 @@ TEST(DeclPrinter, TestCXXMethodDecl_Operator2) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
Code,
- methodDecl(ofClass(hasName("Z"))).bind("id"),
+ cxxMethodDecl(ofClass(hasName("Z"))).bind("id"),
Expected));
}
}
diff --git a/unittests/AST/NamedDeclPrinterTest.cpp b/unittests/AST/NamedDeclPrinterTest.cpp
index cf97a0abf6c8b..92df4577ac779 100644
--- a/unittests/AST/NamedDeclPrinterTest.cpp
+++ b/unittests/AST/NamedDeclPrinterTest.cpp
@@ -131,3 +131,45 @@ TEST(NamedDeclPrinter, TestNamespace2) {
"A",
"A"));
}
+
+TEST(NamedDeclPrinter, TestUnscopedUnnamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "enum { A };",
+ "A",
+ "A"));
+}
+
+TEST(NamedDeclPrinter, TestNamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "enum X { A };",
+ "A",
+ "X::A"));
+}
+
+TEST(NamedDeclPrinter, TestScopedNamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "enum class X { A };",
+ "A",
+ "X::A"));
+}
+
+TEST(NamedDeclPrinter, TestClassWithUnscopedUnnamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "class X { enum { A }; };",
+ "A",
+ "X::A"));
+}
+
+TEST(NamedDeclPrinter, TestClassWithUnscopedNamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "class X { enum Y { A }; };",
+ "A",
+ "X::Y::A"));
+}
+
+TEST(NamedDeclPrinter, TestClassWithScopedNamedEnum) {
+ ASSERT_TRUE(PrintedWrittenNamedDeclCXX11Matches(
+ "class X { enum class Y { A }; };",
+ "A",
+ "X::Y::A"));
+}
diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp
index b0a8f85f0e403..4c77def61bc4a 100644
--- a/unittests/AST/SourceLocationTest.cpp
+++ b/unittests/AST/SourceLocationTest.cpp
@@ -92,13 +92,13 @@ TEST(ParmVarDecl, KNRRange) {
TEST(CXXNewExpr, ArrayRange) {
RangeVerifier<CXXNewExpr> Verifier;
Verifier.expectRange(1, 12, 1, 22);
- EXPECT_TRUE(Verifier.match("void f() { new int[10]; }", newExpr()));
+ EXPECT_TRUE(Verifier.match("void f() { new int[10]; }", cxxNewExpr()));
}
TEST(CXXNewExpr, ParenRange) {
RangeVerifier<CXXNewExpr> Verifier;
Verifier.expectRange(1, 12, 1, 20);
- EXPECT_TRUE(Verifier.match("void f() { new int(); }", newExpr()));
+ EXPECT_TRUE(Verifier.match("void f() { new int(); }", cxxNewExpr()));
}
TEST(MemberExpr, ImplicitMemberRange) {
@@ -221,7 +221,7 @@ TEST(TemplateSpecializationTypeLoc, AngleBracketLocations) {
TEST(CXXNewExpr, TypeParenRange) {
RangeVerifier<CXXNewExpr> Verifier;
Verifier.expectRange(1, 10, 1, 18);
- EXPECT_TRUE(Verifier.match("int* a = new (int);", newExpr()));
+ EXPECT_TRUE(Verifier.match("int* a = new (int);", cxxNewExpr()));
}
class UnaryTransformTypeLocParensRangeVerifier : public RangeVerifier<TypeLoc> {
@@ -252,7 +252,7 @@ TEST(CXXFunctionalCastExpr, SourceRange) {
"int foo() {\n"
" return int{};\n"
"}",
- functionalCastExpr(), Lang_CXX11));
+ cxxFunctionalCastExpr(), Lang_CXX11));
}
TEST(CXXConstructExpr, SourceRange) {
@@ -262,7 +262,7 @@ TEST(CXXConstructExpr, SourceRange) {
"struct A { A(int, int); };\n"
"void f(A a);\n"
"void g() { f({0, 0}); }",
- constructExpr(), Lang_CXX11));
+ cxxConstructExpr(), Lang_CXX11));
}
TEST(CXXTemporaryObjectExpr, SourceRange) {
@@ -271,7 +271,7 @@ TEST(CXXTemporaryObjectExpr, SourceRange) {
EXPECT_TRUE(Verifier.match(
"struct A { A(int, int); };\n"
"A a( A{0, 0} );",
- temporaryObjectExpr(), Lang_CXX11));
+ cxxTemporaryObjectExpr(), Lang_CXX11));
}
TEST(CXXUnresolvedConstructExpr, SourceRange) {
@@ -284,7 +284,7 @@ TEST(CXXUnresolvedConstructExpr, SourceRange) {
"U foo() {\n"
" return U{};\n"
"}",
- unresolvedConstructExpr(), Args, Lang_CXX11));
+ cxxUnresolvedConstructExpr(), Args, Lang_CXX11));
}
TEST(UsingDecl, SourceRange) {
@@ -434,11 +434,11 @@ TEST(FriendDecl, FriendConstructorDestructorLocation) {
LocationVerifier<FriendDecl> ConstructorVerifier;
ConstructorVerifier.expectLocation(6, 11);
EXPECT_TRUE(ConstructorVerifier.match(
- Code, friendDecl(has(constructorDecl(ofClass(hasName("B")))))));
+ Code, friendDecl(has(cxxConstructorDecl(ofClass(hasName("B")))))));
LocationVerifier<FriendDecl> DestructorVerifier;
DestructorVerifier.expectLocation(6, 19);
EXPECT_TRUE(DestructorVerifier.match(
- Code, friendDecl(has(destructorDecl(ofClass(hasName("B")))))));
+ Code, friendDecl(has(cxxDestructorDecl(ofClass(hasName("B")))))));
}
TEST(FriendDecl, FriendConstructorDestructorRange) {
@@ -452,11 +452,11 @@ TEST(FriendDecl, FriendConstructorDestructorRange) {
RangeVerifier<FriendDecl> ConstructorVerifier;
ConstructorVerifier.expectRange(6, 1, 6, 13);
EXPECT_TRUE(ConstructorVerifier.match(
- Code, friendDecl(has(constructorDecl(ofClass(hasName("B")))))));
+ Code, friendDecl(has(cxxConstructorDecl(ofClass(hasName("B")))))));
RangeVerifier<FriendDecl> DestructorVerifier;
DestructorVerifier.expectRange(6, 1, 6, 22);
EXPECT_TRUE(DestructorVerifier.match(
- Code, friendDecl(has(destructorDecl(ofClass(hasName("B")))))));
+ Code, friendDecl(has(cxxDestructorDecl(ofClass(hasName("B")))))));
}
TEST(FriendDecl, FriendTemplateFunctionLocation) {
@@ -527,7 +527,7 @@ TEST(FriendDecl, InstantiationSourceRange) {
" friend void operator+<>(S<T> src);\n"
"};\n"
"void test(S<double> s) { +s; }",
- friendDecl(hasParent(recordDecl(isTemplateInstantiation())))));
+ friendDecl(hasParent(cxxRecordDecl(isTemplateInstantiation())))));
}
TEST(ObjCMessageExpr, CXXConstructExprRange) {
@@ -539,7 +539,7 @@ TEST(ObjCMessageExpr, CXXConstructExprRange) {
"+ (void) f1: (A)arg;\n"
"@end\n"
"void f2() { A a; [B f1: (a)]; }\n",
- constructExpr(), Lang_OBJCXX));
+ cxxConstructExpr(), Lang_OBJCXX));
}
} // end namespace ast_matchers
diff --git a/unittests/AST/StmtPrinterTest.cpp b/unittests/AST/StmtPrinterTest.cpp
index b1fd2c1eb42c1..bc7fd54e4ad96 100644
--- a/unittests/AST/StmtPrinterTest.cpp
+++ b/unittests/AST/StmtPrinterTest.cpp
@@ -196,7 +196,7 @@ TEST(StmtPrinter, TestCXXConversionDeclImplicit) {
"void foo(A a, A b) {"
" bar(a & b);"
"}",
- memberCallExpr(anything()).bind("id"),
+ cxxMemberCallExpr(anything()).bind("id"),
"a & b"));
}
@@ -210,7 +210,7 @@ TEST(StmtPrinter, TestCXXConversionDeclExplicit) {
"void foo(A a, A b) {"
" auto x = (a & b).operator void *();"
"}",
- memberCallExpr(anything()).bind("id"),
+ cxxMemberCallExpr(anything()).bind("id"),
"(a & b)"));
// WRONG; Should be: (a & b).operator void *()
}
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 8ef3f15e4c086..cd18df8410b73 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -36,7 +36,7 @@ TEST(HasNameDeathTest, DiesOnEmptyPattern) {
TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
ASSERT_DEBUG_DEATH({
- DeclarationMatcher IsDerivedFromEmpty = recordDecl(isDerivedFrom(""));
+ DeclarationMatcher IsDerivedFromEmpty = cxxRecordDecl(isDerivedFrom(""));
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
}, "");
}
@@ -122,7 +122,7 @@ TEST(DeclarationMatcher, MatchClass) {
}
TEST(DeclarationMatcher, ClassIsDerived) {
- DeclarationMatcher IsDerivedFromX = recordDecl(isDerivedFrom("X"));
+ DeclarationMatcher IsDerivedFromX = cxxRecordDecl(isDerivedFrom("X"));
EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX));
@@ -130,7 +130,7 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
EXPECT_TRUE(notMatches("", IsDerivedFromX));
- DeclarationMatcher IsAX = recordDecl(isSameOrDerivedFrom("X"));
+ DeclarationMatcher IsAX = cxxRecordDecl(isSameOrDerivedFrom("X"));
EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX));
EXPECT_TRUE(matches("class X {};", IsAX));
@@ -139,7 +139,7 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(notMatches("", IsAX));
DeclarationMatcher ZIsDerivedFromX =
- recordDecl(hasName("Z"), isDerivedFrom("X"));
+ cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
EXPECT_TRUE(
matches("class X {}; class Y : public X {}; class Z : public Y {};",
ZIsDerivedFromX));
@@ -258,14 +258,14 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(
notMatches("template<int> struct X;"
"template<int i> struct X : public X<i-1> {};",
- recordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
+ cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
EXPECT_TRUE(matches(
"struct A {};"
"template<int> struct X;"
"template<int i> struct X : public X<i-1> {};"
"template<> struct X<0> : public A {};"
"struct B : public X<42> {};",
- recordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
+ cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
// FIXME: Once we have better matchers for template type matching,
// get rid of the Variable(...) matching and match the right template
@@ -282,15 +282,15 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_char"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
isDerivedFrom("Base2")))))));
const char *RecursiveTemplateTwoParameters =
@@ -307,39 +307,39 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_char"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
"namespace ns { class X {}; class Y : public X {}; }",
- recordDecl(isDerivedFrom("::ns::X"))));
+ cxxRecordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(notMatches(
"class X {}; class Y : public X {};",
- recordDecl(isDerivedFrom("::ns::X"))));
+ cxxRecordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(matches(
"class X {}; class Y : public X {};",
- recordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
+ cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
EXPECT_TRUE(matches(
"template<typename T> class X {};"
"template<typename T> using Z = X<T>;"
"template <typename T> class Y : Z<T> {};",
- recordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
+ cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
}
TEST(DeclarationMatcher, hasMethod) {
EXPECT_TRUE(matches("class A { void func(); };",
- recordDecl(hasMethod(hasName("func")))));
+ cxxRecordDecl(hasMethod(hasName("func")))));
EXPECT_TRUE(notMatches("class A { void func(); };",
- recordDecl(hasMethod(isPublic()))));
+ cxxRecordDecl(hasMethod(isPublic()))));
}
TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
@@ -349,7 +349,7 @@ TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
"};"
"template <typename T> struct B : A<T>::template F<T> {};"
"B<int> b;",
- recordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
+ cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
}
TEST(DeclarationMatcher, hasDeclContext) {
@@ -453,11 +453,20 @@ TEST(AllOf, AllOverloadsWork) {
hasArgument(3, integerLiteral(equals(4)))))));
}
-TEST(DeclarationMatcher, MatchAnyOf) {
- DeclarationMatcher YOrZDerivedFromX =
- recordDecl(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+TEST(ConstructVariadic, MismatchedTypes_Regression) {
EXPECT_TRUE(
- matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
+ matches("const int a = 0;",
+ internal::DynTypedMatcher::constructVariadic(
+ internal::DynTypedMatcher::VO_AnyOf,
+ ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(),
+ {isConstQualified(), arrayType()})
+ .convertTo<QualType>()));
+}
+
+TEST(DeclarationMatcher, MatchAnyOf) {
+ DeclarationMatcher YOrZDerivedFromX = cxxRecordDecl(
+ anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+ EXPECT_TRUE(matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
EXPECT_TRUE(
notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
@@ -485,7 +494,7 @@ TEST(DeclarationMatcher, MatchAnyOf) {
EXPECT_TRUE(
matches("void f() try { } catch (int) { } catch (...) { }",
- catchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
+ cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
}
TEST(DeclarationMatcher, MatchHas) {
@@ -592,7 +601,7 @@ TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
TEST(DeclarationMatcher, MatchNot) {
DeclarationMatcher NotClassX =
- recordDecl(
+ cxxRecordDecl(
isDerivedFrom("Y"),
unless(hasName("X")));
EXPECT_TRUE(notMatches("", NotClassX));
@@ -709,11 +718,11 @@ TEST(DeclarationMatcher, HasAttr) {
TEST(DeclarationMatcher, MatchCudaDecl) {
EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"
"void g() { f<<<1, 2>>>(); }",
- CUDAKernelCallExpr()));
+ cudaKernelCallExpr()));
EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",
hasAttr(clang::attr::CUDADevice)));
EXPECT_TRUE(notMatchesWithCuda("void f() {}",
- CUDAKernelCallExpr()));
+ cudaKernelCallExpr()));
EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",
hasAttr(clang::attr::CUDAGlobal)));
}
@@ -898,7 +907,8 @@ TEST(TypeMatcher, MatchesClassType) {
EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));
EXPECT_TRUE(notMatches("class A {};", TypeA));
- TypeMatcher TypeDerivedFromA = hasDeclaration(recordDecl(isDerivedFrom("A")));
+ TypeMatcher TypeDerivedFromA =
+ hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));
EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
TypeDerivedFromA));
@@ -909,6 +919,57 @@ TEST(TypeMatcher, MatchesClassType) {
EXPECT_TRUE(
matches("class A { public: A *a; class B {}; };", TypeAHasClassB));
+
+ EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",
+ varDecl(hasType(namedDecl(hasName("S"))))));
+}
+
+TEST(TypeMatcher, MatchesDeclTypes) {
+ // TypedefType -> TypedefNameDecl
+ EXPECT_TRUE(matches("typedef int I; void f(I i);",
+ parmVarDecl(hasType(namedDecl(hasName("I"))))));
+ // ObjCObjectPointerType
+ EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",
+ parmVarDecl(hasType(objcObjectPointerType()))));
+ // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl
+ EXPECT_TRUE(matchesObjC(
+ "@interface Foo @end void f(Foo *f);",
+ parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));
+ // TemplateTypeParmType
+ EXPECT_TRUE(matches("template <typename T> void f(T t);",
+ parmVarDecl(hasType(templateTypeParmType()))));
+ // TemplateTypeParmType -> TemplateTypeParmDecl
+ EXPECT_TRUE(matches("template <typename T> void f(T t);",
+ parmVarDecl(hasType(namedDecl(hasName("T"))))));
+ // InjectedClassNameType
+ EXPECT_TRUE(matches("template <typename T> struct S {"
+ " void f(S s);"
+ "};",
+ parmVarDecl(hasType(injectedClassNameType()))));
+ EXPECT_TRUE(notMatches("template <typename T> struct S {"
+ " void g(S<T> s);"
+ "};",
+ parmVarDecl(hasType(injectedClassNameType()))));
+ // InjectedClassNameType -> CXXRecordDecl
+ EXPECT_TRUE(matches("template <typename T> struct S {"
+ " void f(S s);"
+ "};",
+ parmVarDecl(hasType(namedDecl(hasName("S"))))));
+
+ static const char Using[] = "template <typename T>"
+ "struct Base {"
+ " typedef T Foo;"
+ "};"
+ ""
+ "template <typename T>"
+ "struct S : private Base<T> {"
+ " using typename Base<T>::Foo;"
+ " void f(Foo);"
+ "};";
+ // UnresolvedUsingTypenameDecl
+ EXPECT_TRUE(matches(Using, unresolvedUsingTypenameDecl(hasName("Foo"))));
+ // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl
+ EXPECT_TRUE(matches(Using, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));
}
TEST(Matcher, BindMatchedNodes) {
@@ -928,7 +989,7 @@ TEST(Matcher, BindMatchedNodes) {
new VerifyIdIsBoundTo<Decl>("b")));
StatementMatcher MethodX =
- callExpr(callee(methodDecl(hasName("x")))).bind("x");
+ callExpr(callee(cxxMethodDecl(hasName("x")))).bind("x");
EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
MethodX,
@@ -1042,13 +1103,14 @@ TEST(HasTypeLoc, MatchesDeclaratorDecls) {
TEST(Matcher, Call) {
// FIXME: Do we want to overload Call() to directly take
// Matcher<Decl>, too?
- StatementMatcher MethodX = callExpr(hasDeclaration(methodDecl(hasName("x"))));
+ StatementMatcher MethodX =
+ callExpr(hasDeclaration(cxxMethodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
StatementMatcher MethodOnY =
- memberCallExpr(on(hasType(recordDecl(hasName("Y")))));
+ cxxMemberCallExpr(on(hasType(recordDecl(hasName("Y")))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -1067,7 +1129,7 @@ TEST(Matcher, Call) {
MethodOnY));
StatementMatcher MethodOnYPointer =
- memberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
+ cxxMemberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
@@ -1094,9 +1156,9 @@ TEST(Matcher, Lambda) {
TEST(Matcher, ForRange) {
EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"
"void f() { for (auto &a : as); }",
- forRangeStmt()));
+ cxxForRangeStmt()));
EXPECT_TRUE(notMatches("void f() { for (int i; i<5; ++i); }",
- forRangeStmt()));
+ cxxForRangeStmt()));
}
TEST(Matcher, SubstNonTypeTemplateParm) {
@@ -1110,6 +1172,20 @@ TEST(Matcher, SubstNonTypeTemplateParm) {
substNonTypeTemplateParmExpr()));
}
+TEST(Matcher, NonTypeTemplateParmDecl) {
+ EXPECT_TRUE(matches("template <int N> void f();",
+ nonTypeTemplateParmDecl(hasName("N"))));
+ EXPECT_TRUE(
+ notMatches("template <typename T> void f();", nonTypeTemplateParmDecl()));
+}
+
+TEST(Matcher, templateTypeParmDecl) {
+ EXPECT_TRUE(matches("template <typename T> void f();",
+ templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(
+ notMatches("template <int N> void f();", templateTypeParmDecl()));
+}
+
TEST(Matcher, UserDefinedLiteral) {
EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
" return i + 1;"
@@ -1130,9 +1206,10 @@ TEST(Matcher, FlowControl) {
TEST(HasType, MatchesAsString) {
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
- memberCallExpr(on(hasType(asString("class Y *"))))));
- EXPECT_TRUE(matches("class X { void x(int x) {} };",
- methodDecl(hasParameter(0, hasType(asString("int"))))));
+ cxxMemberCallExpr(on(hasType(asString("class Y *"))))));
+ EXPECT_TRUE(
+ matches("class X { void x(int x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(asString("int"))))));
EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };",
fieldDecl(hasType(asString("ns::A")))));
EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };",
@@ -1140,7 +1217,7 @@ TEST(HasType, MatchesAsString) {
}
TEST(Matcher, OverloadedOperatorCall) {
- StatementMatcher OpCall = operatorCallExpr();
+ StatementMatcher OpCall = cxxOperatorCallExpr();
// Unary operator
EXPECT_TRUE(matches("class Y { }; "
"bool operator!(Y x) { return false; }; "
@@ -1167,22 +1244,22 @@ TEST(Matcher, OverloadedOperatorCall) {
TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
StatementMatcher OpCallAndAnd =
- operatorCallExpr(hasOverloadedOperatorName("&&"));
+ cxxOperatorCallExpr(hasOverloadedOperatorName("&&"));
EXPECT_TRUE(matches("class Y { }; "
"bool operator&&(Y x, Y y) { return true; }; "
"Y a; Y b; bool c = a && b;", OpCallAndAnd));
StatementMatcher OpCallLessLess =
- operatorCallExpr(hasOverloadedOperatorName("<<"));
+ cxxOperatorCallExpr(hasOverloadedOperatorName("<<"));
EXPECT_TRUE(notMatches("class Y { }; "
"bool operator&&(Y x, Y y) { return true; }; "
"Y a; Y b; bool c = a && b;",
OpCallLessLess));
StatementMatcher OpStarCall =
- operatorCallExpr(hasOverloadedOperatorName("*"));
+ cxxOperatorCallExpr(hasOverloadedOperatorName("*"));
EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }",
OpStarCall));
DeclarationMatcher ClassWithOpStar =
- recordDecl(hasMethod(hasOverloadedOperatorName("*")));
+ cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")));
EXPECT_TRUE(matches("class Y { int operator*(); };",
ClassWithOpStar));
EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
@@ -1194,26 +1271,25 @@ TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
TEST(Matcher, NestedOverloadedOperatorCalls) {
EXPECT_TRUE(matchAndVerifyResultTrue(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
- new VerifyIdIsBoundTo<CXXOperatorCallExpr>("x", 2)));
- EXPECT_TRUE(matches(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasParent(operatorCallExpr()))));
- EXPECT_TRUE(matches(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasDescendant(operatorCallExpr()))));
+ "class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
+ new VerifyIdIsBoundTo<CXXOperatorCallExpr>("x", 2)));
+ EXPECT_TRUE(matches("class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasParent(cxxOperatorCallExpr()))));
+ EXPECT_TRUE(
+ matches("class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr()))));
}
TEST(Matcher, ThisPointerType) {
StatementMatcher MethodOnY =
- memberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
+ cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -1245,7 +1321,7 @@ TEST(Matcher, VariableUsage) {
StatementMatcher Reference =
declRefExpr(to(
varDecl(hasInitializer(
- memberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
+ cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
EXPECT_TRUE(matches(
"class Y {"
@@ -1279,6 +1355,29 @@ TEST(Matcher, VarDecl_Storage) {
EXPECT_TRUE(matches("void f() { static int X; }", M));
}
+TEST(Matcher, VarDecl_StorageDuration) {
+ std::string T =
+ "void f() { int x; static int y; } int a;";
+
+ EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration())));
+ EXPECT_TRUE(
+ notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration())));
+ EXPECT_TRUE(
+ notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration())));
+
+ EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration())));
+ EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration())));
+
+ // FIXME: It is really hard to test with thread_local itself because not all
+ // targets support TLS, which causes this to be an error depending on what
+ // platform the test is being run on. We do not have access to the TargetInfo
+ // object to be able to test whether the platform supports TLS or not.
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasThreadStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("y"), hasThreadStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("a"), hasThreadStorageDuration())));
+}
+
TEST(Matcher, FindsVarDeclInFunctionParameter) {
EXPECT_TRUE(matches(
"void f(int i) {}",
@@ -1287,7 +1386,7 @@ TEST(Matcher, FindsVarDeclInFunctionParameter) {
TEST(Matcher, CalledVariable) {
StatementMatcher CallOnVariableY =
- memberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
+ cxxMemberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(matches(
"class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
@@ -1370,6 +1469,14 @@ TEST(IsInteger, ReportsNoFalsePositives) {
to(varDecl(hasType(isInteger()))))))));
}
+TEST(IsAnyCharacter, MatchesCharacters) {
+ EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter()))));
+}
+
+TEST(IsAnyCharacter, ReportsNoFalsePositives) {
+ EXPECT_TRUE(notMatches("int i;", varDecl(hasType(isAnyCharacter()))));
+}
+
TEST(IsArrow, MatchesMemberVariablesViaArrow) {
EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
memberExpr(isArrow())));
@@ -1398,18 +1505,25 @@ TEST(IsArrow, MatchesMemberCallsViaArrow) {
}
TEST(Callee, MatchesDeclarations) {
- StatementMatcher CallMethodX = callExpr(callee(methodDecl(hasName("x"))));
+ StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
- CallMethodX = callExpr(callee(conversionDecl()));
+ CallMethodX = callExpr(callee(cxxConversionDecl()));
EXPECT_TRUE(
matches("struct Y { operator int() const; }; int i = Y();", CallMethodX));
EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",
CallMethodX));
}
+TEST(ConversionDeclaration, IsExplicit) {
+ EXPECT_TRUE(matches("struct S { explicit operator int(); };",
+ cxxConversionDecl(isExplicit())));
+ EXPECT_TRUE(notMatches("struct S { operator int(); };",
+ cxxConversionDecl(isExplicit())));
+}
+
TEST(Callee, MatchesMemberExpressions) {
EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
callExpr(callee(memberExpr()))));
@@ -1442,6 +1556,13 @@ TEST(Function, MatchesFunctionDeclarations) {
notMatches("void f(int);"
"template <typename T> struct S { void g(T t) { f(t); } };",
CallFunctionF));
+
+ EXPECT_TRUE(matches("void f(...);", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("void f(int);", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("template <typename... Ts> void f(Ts...);",
+ functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatchesC("void f();", functionDecl(isVariadic())));
}
TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
@@ -1545,34 +1666,38 @@ TEST(QualType, hasLocalQualifiers) {
TEST(HasParameter, CallsInnerMatcher) {
EXPECT_TRUE(matches("class X { void x(int) {} };",
- methodDecl(hasParameter(0, varDecl()))));
+ cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- methodDecl(hasParameter(0, hasName("x")))));
+ cxxMethodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- methodDecl(hasParameter(42, varDecl()))));
+ cxxMethodDecl(hasParameter(42, varDecl()))));
}
TEST(HasType, MatchesParameterVariableTypesStrictly) {
- EXPECT_TRUE(matches("class X { void x(X x) {} };",
- methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
- EXPECT_TRUE(notMatches("class X { void x(const X &x) {} };",
- methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class X { void x(X x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(notMatches(
+ "class X { void x(const X &x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
- methodDecl(hasParameter(0,
- hasType(pointsTo(recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasParameter(
+ 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
- methodDecl(hasParameter(0,
- hasType(references(recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasParameter(
+ 0, hasType(references(recordDecl(hasName("X"))))))));
}
TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
- EXPECT_TRUE(matches("class Y {}; class X { void x(X x, Y y) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
- EXPECT_TRUE(matches("class Y {}; class X { void x(Y y, X x) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class Y {}; class X { void x(X x, Y y) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class Y {}; class X { void x(Y y, X x) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(Returns, MatchesReturnTypes) {
@@ -1599,6 +1724,15 @@ TEST(IsDeleted, MatchesDeletedFunctionDeclarations) {
functionDecl(hasName("Func"), isDeleted())));
}
+TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) {
+ EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow())));
+ EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow())));
+ EXPECT_TRUE(
+ notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
+ EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow())));
+ EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow())));
+}
+
TEST(isConstexpr, MatchesConstexprDeclarations) {
EXPECT_TRUE(matches("constexpr int foo = 42;",
varDecl(hasName("foo"), isConstexpr())));
@@ -1607,21 +1741,22 @@ TEST(isConstexpr, MatchesConstexprDeclarations) {
}
TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
- EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(notMatches(
+ "class Y {}; class X { void x(int) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(HasAnyParameter, DoesNotMatchThisPointer) {
EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
- methodDecl(hasAnyParameter(hasType(pointsTo(
- recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasAnyParameter(
+ hasType(pointsTo(recordDecl(hasName("X"))))))));
}
TEST(HasName, MatchesParameterVariableDeclarations) {
EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
- methodDecl(hasAnyParameter(hasName("x")))));
+ cxxMethodDecl(hasAnyParameter(hasName("x")))));
EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- methodDecl(hasAnyParameter(hasName("x")))));
+ cxxMethodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Matcher, MatchesClassTemplateSpecialization) {
@@ -1774,46 +1909,68 @@ TEST(Matcher, MatchesAccessSpecDecls) {
EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl()));
}
+TEST(Matcher, MatchesFinal) {
+ EXPECT_TRUE(matches("class X final {};", cxxRecordDecl(isFinal())));
+ EXPECT_TRUE(matches("class X { virtual void f() final; };",
+ cxxMethodDecl(isFinal())));
+ EXPECT_TRUE(notMatches("class X {};", cxxRecordDecl(isFinal())));
+ EXPECT_TRUE(
+ notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal())));
+}
+
TEST(Matcher, MatchesVirtualMethod) {
EXPECT_TRUE(matches("class X { virtual int f(); };",
- methodDecl(isVirtual(), hasName("::X::f"))));
- EXPECT_TRUE(notMatches("class X { int f(); };",
- methodDecl(isVirtual())));
+ cxxMethodDecl(isVirtual(), hasName("::X::f"))));
+ EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isVirtual())));
}
TEST(Matcher, MatchesPureMethod) {
EXPECT_TRUE(matches("class X { virtual int f() = 0; };",
- methodDecl(isPure(), hasName("::X::f"))));
- EXPECT_TRUE(notMatches("class X { int f(); };",
- methodDecl(isPure())));
+ cxxMethodDecl(isPure(), hasName("::X::f"))));
+ EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isPure())));
+}
+
+TEST(Matcher, MatchesCopyAssignmentOperator) {
+ EXPECT_TRUE(matches("class X { X &operator=(X); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(const X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(const volatile X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
}
TEST(Matcher, MatchesConstMethod) {
- EXPECT_TRUE(matches("struct A { void foo() const; };",
- methodDecl(isConst())));
- EXPECT_TRUE(notMatches("struct A { void foo(); };",
- methodDecl(isConst())));
+ EXPECT_TRUE(
+ matches("struct A { void foo() const; };", cxxMethodDecl(isConst())));
+ EXPECT_TRUE(
+ notMatches("struct A { void foo(); };", cxxMethodDecl(isConst())));
}
TEST(Matcher, MatchesOverridingMethod) {
EXPECT_TRUE(matches("class X { virtual int f(); }; "
"class Y : public X { int f(); };",
- methodDecl(isOverride(), hasName("::Y::f"))));
+ cxxMethodDecl(isOverride(), hasName("::Y::f"))));
EXPECT_TRUE(notMatches("class X { virtual int f(); }; "
- "class Y : public X { int f(); };",
- methodDecl(isOverride(), hasName("::X::f"))));
+ "class Y : public X { int f(); };",
+ cxxMethodDecl(isOverride(), hasName("::X::f"))));
EXPECT_TRUE(notMatches("class X { int f(); }; "
"class Y : public X { int f(); };",
- methodDecl(isOverride())));
+ cxxMethodDecl(isOverride())));
EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ",
- methodDecl(isOverride())));
+ cxxMethodDecl(isOverride())));
EXPECT_TRUE(
matches("template <typename Base> struct Y : Base { void f() override;};",
- methodDecl(isOverride(), hasName("::Y::f"))));
+ cxxMethodDecl(isOverride(), hasName("::Y::f"))));
}
TEST(Matcher, ConstructorCall) {
- StatementMatcher Constructor = constructExpr();
+ StatementMatcher Constructor = cxxConstructExpr();
EXPECT_TRUE(
matches("class X { public: X(); }; void x() { X x; }", Constructor));
@@ -1827,7 +1984,7 @@ TEST(Matcher, ConstructorCall) {
}
TEST(Matcher, ConstructorArgument) {
- StatementMatcher Constructor = constructExpr(
+ StatementMatcher Constructor = cxxConstructExpr(
hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
@@ -1843,7 +2000,7 @@ TEST(Matcher, ConstructorArgument) {
notMatches("class X { public: X(int); }; void x() { int z; X x(z); }",
Constructor));
- StatementMatcher WrongIndex = constructExpr(
+ StatementMatcher WrongIndex = cxxConstructExpr(
hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; X x(y); }",
@@ -1851,7 +2008,7 @@ TEST(Matcher, ConstructorArgument) {
}
TEST(Matcher, ConstructorArgumentCount) {
- StatementMatcher Constructor1Arg = constructExpr(argumentCountIs(1));
+ StatementMatcher Constructor1Arg = cxxConstructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { X x(0); }",
@@ -1868,7 +2025,8 @@ TEST(Matcher, ConstructorArgumentCount) {
}
TEST(Matcher, ConstructorListInitialization) {
- StatementMatcher ConstructorListInit = constructExpr(isListInitialization());
+ StatementMatcher ConstructorListInit =
+ cxxConstructExpr(isListInitialization());
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { X x{0}; }",
@@ -1880,13 +2038,13 @@ TEST(Matcher, ConstructorListInitialization) {
TEST(Matcher,ThisExpr) {
EXPECT_TRUE(
- matches("struct X { int a; int f () { return a; } };", thisExpr()));
+ matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));
EXPECT_TRUE(
- notMatches("struct X { int f () { int a; return a; } };", thisExpr()));
+ notMatches("struct X { int f () { int a; return a; } };", cxxThisExpr()));
}
TEST(Matcher, BindTemporaryExpression) {
- StatementMatcher TempExpression = bindTemporaryExpr();
+ StatementMatcher TempExpression = cxxBindTemporaryExpr();
std::string ClassString = "class string { public: string(); ~string(); }; ";
@@ -1953,46 +2111,76 @@ TEST(MaterializeTemporaryExpr, MatchesTemporary) {
TEST(ConstructorDeclaration, SimpleCase) {
EXPECT_TRUE(matches("class Foo { Foo(int i); };",
- constructorDecl(ofClass(hasName("Foo")))));
+ cxxConstructorDecl(ofClass(hasName("Foo")))));
EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
- constructorDecl(ofClass(hasName("Bar")))));
+ cxxConstructorDecl(ofClass(hasName("Bar")))));
}
TEST(ConstructorDeclaration, IsImplicit) {
// This one doesn't match because the constructor is not added by the
// compiler (it is not needed).
EXPECT_TRUE(notMatches("class Foo { };",
- constructorDecl(isImplicit())));
+ cxxConstructorDecl(isImplicit())));
// The compiler added the implicit default constructor.
EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
- constructorDecl(isImplicit())));
+ cxxConstructorDecl(isImplicit())));
EXPECT_TRUE(matches("class Foo { Foo(){} };",
- constructorDecl(unless(isImplicit()))));
+ cxxConstructorDecl(unless(isImplicit()))));
// The compiler added an implicit assignment operator.
EXPECT_TRUE(matches("struct A { int x; } a = {0}, b = a; void f() { a = b; }",
- methodDecl(isImplicit(), hasName("operator="))));
+ cxxMethodDecl(isImplicit(), hasName("operator="))));
+}
+
+TEST(ConstructorDeclaration, IsExplicit) {
+ EXPECT_TRUE(matches("struct S { explicit S(int); };",
+ cxxConstructorDecl(isExplicit())));
+ EXPECT_TRUE(notMatches("struct S { S(int); };",
+ cxxConstructorDecl(isExplicit())));
+}
+
+TEST(ConstructorDeclaration, Kinds) {
+ EXPECT_TRUE(matches("struct S { S(); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ cxxConstructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(matches("struct S { S(const S&); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ cxxConstructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(matches("struct S { S(S&&); };",
+ cxxConstructorDecl(isMoveConstructor())));
}
TEST(DestructorDeclaration, MatchesVirtualDestructor) {
EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
- destructorDecl(ofClass(hasName("Foo")))));
+ cxxDestructorDecl(ofClass(hasName("Foo")))));
}
TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {
EXPECT_TRUE(notMatches("class Foo {};",
- destructorDecl(ofClass(hasName("Foo")))));
+ cxxDestructorDecl(ofClass(hasName("Foo")))));
}
TEST(HasAnyConstructorInitializer, SimpleCase) {
- EXPECT_TRUE(notMatches(
- "class Foo { Foo() { } };",
- constructorDecl(hasAnyConstructorInitializer(anything()))));
- EXPECT_TRUE(matches(
- "class Foo {"
- " Foo() : foo_() { }"
- " int foo_;"
- "};",
- constructorDecl(hasAnyConstructorInitializer(anything()))));
+ EXPECT_TRUE(
+ notMatches("class Foo { Foo() { } };",
+ cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
+ EXPECT_TRUE(
+ matches("class Foo {"
+ " Foo() : foo_() { }"
+ " int foo_;"
+ "};",
+ cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
}
TEST(HasAnyConstructorInitializer, ForField) {
@@ -2003,11 +2191,11 @@ TEST(HasAnyConstructorInitializer, ForField) {
" Baz foo_;"
" Baz bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasType(recordDecl(hasName("Baz"))))))));
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasName("foo_"))))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasType(recordDecl(hasName("Bar"))))))));
}
@@ -2017,9 +2205,9 @@ TEST(HasAnyConstructorInitializer, WithInitializer) {
" Foo() : foo_(0) { }"
" int foo_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(0)))))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(1)))))));
}
@@ -2031,16 +2219,40 @@ TEST(HasAnyConstructorInitializer, IsWritten) {
" Bar foo_;"
" Bar bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("foo_")), isWritten())))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), isWritten())))));
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), unless(isWritten()))))));
}
+TEST(HasAnyConstructorInitializer, IsBaseInitializer) {
+ static const char Code[] =
+ "struct B {};"
+ "struct D : B {"
+ " int I;"
+ " D(int i) : I(i) {}"
+ "};"
+ "struct E : B {"
+ " E() : B() {}"
+ "};";
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("E")))));
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("D")))));
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
+ hasName("D")))));
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
+ hasName("E")))));
+}
+
TEST(Matcher, NewExpression) {
- StatementMatcher New = newExpr();
+ StatementMatcher New = cxxNewExpr();
EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));
EXPECT_TRUE(
@@ -2051,7 +2263,7 @@ TEST(Matcher, NewExpression) {
}
TEST(Matcher, NewExpressionArgument) {
- StatementMatcher New = constructExpr(
+ StatementMatcher New = cxxConstructExpr(
hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
@@ -2064,7 +2276,7 @@ TEST(Matcher, NewExpressionArgument) {
notMatches("class X { public: X(int); }; void x() { int z; new X(z); }",
New));
- StatementMatcher WrongIndex = constructExpr(
+ StatementMatcher WrongIndex = cxxConstructExpr(
hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; new X(y); }",
@@ -2072,7 +2284,7 @@ TEST(Matcher, NewExpressionArgument) {
}
TEST(Matcher, NewExpressionArgumentCount) {
- StatementMatcher New = constructExpr(argumentCountIs(1));
+ StatementMatcher New = cxxConstructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { new X(0); }", New));
@@ -2083,11 +2295,11 @@ TEST(Matcher, NewExpressionArgumentCount) {
TEST(Matcher, DeleteExpression) {
EXPECT_TRUE(matches("struct A {}; void f(A* a) { delete a; }",
- deleteExpr()));
+ cxxDeleteExpr()));
}
TEST(Matcher, DefaultArgument) {
- StatementMatcher Arg = defaultArgExpr();
+ StatementMatcher Arg = cxxDefaultArgExpr();
EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
EXPECT_TRUE(
@@ -2152,7 +2364,7 @@ TEST(Matcher, FloatLiterals) {
}
TEST(Matcher, NullPtrLiteral) {
- EXPECT_TRUE(matches("int* i = nullptr;", nullPtrLiteralExpr()));
+ EXPECT_TRUE(matches("int* i = nullptr;", cxxNullPtrLiteralExpr()));
}
TEST(Matcher, GNUNullExpr) {
@@ -2164,7 +2376,8 @@ TEST(Matcher, AsmStatement) {
}
TEST(Matcher, Conditions) {
- StatementMatcher Condition = ifStmt(hasCondition(boolLiteral(equals(true))));
+ StatementMatcher Condition =
+ ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));
EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));
@@ -2175,13 +2388,13 @@ TEST(Matcher, Conditions) {
TEST(IfStmt, ChildTraversalMatchers) {
EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
- ifStmt(hasThen(boolLiteral(equals(true))))));
+ ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
- ifStmt(hasThen(boolLiteral(equals(true))))));
+ ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
- ifStmt(hasElse(boolLiteral(equals(true))))));
+ ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
- ifStmt(hasElse(boolLiteral(equals(true))))));
+ ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
}
TEST(MatchBinaryOperator, HasOperatorName) {
@@ -2193,17 +2406,22 @@ TEST(MatchBinaryOperator, HasOperatorName) {
TEST(MatchBinaryOperator, HasLHSAndHasRHS) {
StatementMatcher OperatorTrueFalse =
- binaryOperator(hasLHS(boolLiteral(equals(true))),
- hasRHS(boolLiteral(equals(false))));
+ binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
+ hasRHS(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));
EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));
EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));
+
+ StatementMatcher OperatorIntPointer = arraySubscriptExpr(
+ hasLHS(hasType(isInteger())), hasRHS(hasType(pointsTo(qualType()))));
+ EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer));
+ EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer));
}
TEST(MatchBinaryOperator, HasEitherOperand) {
StatementMatcher HasOperand =
- binaryOperator(hasEitherOperand(boolLiteral(equals(false))));
+ binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));
EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));
@@ -2320,7 +2538,7 @@ TEST(MatchUnaryOperator, HasOperatorName) {
TEST(MatchUnaryOperator, HasUnaryOperand) {
StatementMatcher OperatorOnFalse =
- unaryOperator(hasUnaryOperand(boolLiteral(equals(false))));
+ unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));
EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));
@@ -2363,15 +2581,15 @@ TEST(Matcher, UnaryOperatorTypes) {
TEST(Matcher, ConditionalOperator) {
StatementMatcher Conditional = conditionalOperator(
- hasCondition(boolLiteral(equals(true))),
- hasTrueExpression(boolLiteral(equals(false))));
+ hasCondition(cxxBoolLiteral(equals(true))),
+ hasTrueExpression(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));
EXPECT_TRUE(notMatches("void x() { false ? false : true; }", Conditional));
EXPECT_TRUE(notMatches("void x() { true ? true : false; }", Conditional));
StatementMatcher ConditionalFalse = conditionalOperator(
- hasFalseExpression(boolLiteral(equals(false))));
+ hasFalseExpression(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));
EXPECT_TRUE(
@@ -2478,13 +2696,13 @@ TEST(Matcher, IsDefinition) {
EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
DeclarationMatcher DefinitionOfMethodA =
- methodDecl(hasName("a"), isDefinition());
+ cxxMethodDecl(hasName("a"), isDefinition());
EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
}
TEST(Matcher, OfClass) {
- StatementMatcher Constructor = constructExpr(hasDeclaration(methodDecl(
+ StatementMatcher Constructor = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
ofClass(hasName("X")))));
EXPECT_TRUE(
@@ -2502,7 +2720,7 @@ TEST(Matcher, VisitsTemplateInstantiations) {
"class A { public: void x(); };"
"template <typename T> class B { public: void y() { T t; t.x(); } };"
"void f() { B<A> b; b.y(); }",
- callExpr(callee(methodDecl(hasName("x"))))));
+ callExpr(callee(cxxMethodDecl(hasName("x"))))));
EXPECT_TRUE(matches(
"class A { public: void x(); };"
@@ -2513,8 +2731,8 @@ TEST(Matcher, VisitsTemplateInstantiations) {
"void f() {"
" C::B<A> b; b.y();"
"}",
- recordDecl(hasName("C"),
- hasDescendant(callExpr(callee(methodDecl(hasName("x"))))))));
+ recordDecl(hasName("C"), hasDescendant(callExpr(
+ callee(cxxMethodDecl(hasName("x"))))))));
}
TEST(Matcher, HandlesNullQualTypes) {
@@ -2607,10 +2825,10 @@ TEST(For, ForLoopInternals) {
TEST(For, ForRangeLoopInternals) {
EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
- forRangeStmt(hasLoopVariable(anything()))));
+ cxxForRangeStmt(hasLoopVariable(anything()))));
EXPECT_TRUE(matches(
"void f(){ int a[] {1, 2}; for (int i : a); }",
- forRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
+ cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
}
TEST(For, NegativeForLoopInternals) {
@@ -2650,7 +2868,7 @@ TEST(HasBody, FindsBodyOfForWhileDoLoops) {
EXPECT_TRUE(matches("void f() { do {} while(true); }",
doStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
- forRangeStmt(hasBody(compoundStmt()))));
+ cxxForRangeStmt(hasBody(compoundStmt()))));
}
TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
@@ -2771,16 +2989,16 @@ TEST(Member, MatchesMemberAllocationFunction) {
EXPECT_TRUE(matchesConditionally(
"namespace std { typedef typeof(sizeof(int)) size_t; }"
"class X { void *operator new(std::size_t); };",
- methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
+ cxxMethodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
EXPECT_TRUE(matches("class X { void operator delete(void*); };",
- methodDecl(ofClass(hasName("X")))));
+ cxxMethodDecl(ofClass(hasName("X")))));
// Fails in C++11 mode
EXPECT_TRUE(matchesConditionally(
"namespace std { typedef typeof(sizeof(int)) size_t; }"
"class X { void operator delete[](void*, std::size_t); };",
- methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
+ cxxMethodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
}
TEST(HasObjectExpression, DoesNotMatchMember) {
@@ -2822,6 +3040,15 @@ TEST(Field, MatchesField) {
EXPECT_TRUE(matches("class X { int m; };", fieldDecl(hasName("m"))));
}
+TEST(IsVolatileQualified, QualifiersMatch) {
+ EXPECT_TRUE(matches("volatile int i = 42;",
+ varDecl(hasType(isVolatileQualified()))));
+ EXPECT_TRUE(notMatches("volatile int *i;",
+ varDecl(hasType(isVolatileQualified()))));
+ EXPECT_TRUE(matches("typedef volatile int v_int; v_int i = 42;",
+ varDecl(hasType(isVolatileQualified()))));
+}
+
TEST(IsConstQualified, MatchesConstInt) {
EXPECT_TRUE(matches("const int i = 42;",
varDecl(hasType(isConstQualified()))));
@@ -2868,59 +3095,59 @@ TEST(CastExpression, DoesNotMatchNonCasts) {
TEST(ReinterpretCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
}
TEST(ReinterpretCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);", reinterpretCastExpr()));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
}
TEST(FunctionalCast, MatchesSimpleCase) {
std::string foo_class = "class Foo { public: Foo(const char*); };";
EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
}
TEST(FunctionalCast, DoesNotMatchOtherCasts) {
std::string FooClass = "class Foo { public: Foo(const char*); };";
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
}
TEST(DynamicCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- dynamicCastExpr()));
+ cxxDynamicCastExpr()));
}
TEST(StaticCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));",
- staticCastExpr()));
+ cxxStaticCastExpr()));
}
TEST(StaticCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);", staticCastExpr()));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
}
TEST(CStyleCast, MatchesSimpleCase) {
@@ -2939,7 +3166,7 @@ TEST(CStyleCast, DoesNotMatchOtherCasts) {
TEST(HasDestinationType, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
- staticCastExpr(hasDestinationType(
+ cxxStaticCastExpr(hasDestinationType(
pointsTo(TypeMatcher(anything()))))));
}
@@ -3142,7 +3369,7 @@ TEST(HasSourceExpression, MatchesImplicitCasts) {
EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
"void r() {string a_string; URL url = a_string; }",
implicitCastExpr(
- hasSourceExpression(constructExpr()))));
+ hasSourceExpression(cxxConstructExpr()))));
}
TEST(HasSourceExpression, MatchesExplicitCasts) {
@@ -3314,21 +3541,26 @@ TEST(SwitchCase, MatchesEachCase) {
TEST(ForEachConstructorInitializer, MatchesInitializers) {
EXPECT_TRUE(matches(
"struct X { X() : i(42), j(42) {} int i, j; };",
- constructorDecl(forEachConstructorInitializer(ctorInitializer()))));
+ cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
}
TEST(ExceptionHandling, SimpleCases) {
- EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt()));
- EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt()));
- EXPECT_TRUE(notMatches("void foo() try { } catch(int X) { }", throwExpr()));
+ EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxCatchStmt()));
+ EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxTryStmt()));
+ EXPECT_TRUE(
+ notMatches("void foo() try { } catch(int X) { }", cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw; } catch(int X) { }",
- throwExpr()));
+ cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw 5;} catch(int X) { }",
- throwExpr()));
+ cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw; } catch(...) { }",
- catchStmt(isCatchAll())));
+ cxxCatchStmt(isCatchAll())));
EXPECT_TRUE(notMatches("void foo() try { throw; } catch(int) { }",
- catchStmt(isCatchAll())));
+ cxxCatchStmt(isCatchAll())));
+ EXPECT_TRUE(matches("void foo() try {} catch(int X) { }",
+ varDecl(isExceptionVariable())));
+ EXPECT_TRUE(notMatches("void foo() try { int X; } catch (...) { }",
+ varDecl(isExceptionVariable())));
}
TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
@@ -3460,12 +3692,12 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class X { void f(); void g(); };",
- recordDecl(decl().bind("x"), hasMethod(hasName("g"))),
+ cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class X { X() : a(1), b(2) {} double a; int b; };",
recordDecl(decl().bind("x"),
- has(constructorDecl(
+ has(cxxConstructorDecl(
hasAnyConstructorInitializer(forField(hasName("b")))))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
@@ -3489,12 +3721,12 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A{}; class B{}; class C : B, A {};",
- recordDecl(decl().bind("x"), isDerivedFrom("::A")),
+ cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A{}; typedef A B; typedef A C; typedef A D;"
"class E : A {};",
- recordDecl(decl().bind("x"), isDerivedFrom("C")),
+ cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A { class B { void f() {} }; };",
@@ -3513,8 +3745,8 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A { A() : s(), i(42) {} const char *s; int i; };",
- constructorDecl(hasName("::A::A"), decl().bind("x"),
- forEachConstructorInitializer(forField(hasName("i")))),
+ cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
+ forEachConstructorInitializer(forField(hasName("i")))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
}
@@ -3588,11 +3820,11 @@ TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X {}; class A {}; X<A> x;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {}; X<A> x;",
- recordDecl(isTemplateInstantiation(), hasDescendant(
+ cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
@@ -3607,7 +3839,7 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {};"
"template class X<A>;",
- recordDecl(isTemplateInstantiation(), hasDescendant(
+ cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
@@ -3616,7 +3848,7 @@ TEST(IsTemplateInstantiation,
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template <typename T> class X<T*> {}; class A {}; X<A*> x;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation,
@@ -3627,7 +3859,7 @@ TEST(IsTemplateInstantiation,
" template <typename U> class Y { U u; };"
" Y<A> y;"
"};",
- recordDecl(hasName("::X::Y"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
@@ -3640,31 +3872,31 @@ TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
" template <typename U> class Y { U u; };"
" Y<T> y;"
"}; X<A> x;",
- recordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
+ cxxRecordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
}
TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {}; class A {};"
"template <> class X<A> {}; X<A> x;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
EXPECT_TRUE(notMatches(
"class A {}; class Y { A a; };",
- recordDecl(isTemplateInstantiation())));
+ cxxRecordDecl(isTemplateInstantiation())));
}
TEST(IsInstantiated, MatchesInstantiation) {
EXPECT_TRUE(
matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
- recordDecl(isInstantiated())));
+ cxxRecordDecl(isInstantiated())));
}
TEST(IsInstantiated, NotMatchesDefinition) {
EXPECT_TRUE(notMatches("template<typename T> class A { T i; };",
- recordDecl(isInstantiated())));
+ cxxRecordDecl(isInstantiated())));
}
TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) {
@@ -3716,7 +3948,7 @@ TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {};",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t);",
functionDecl(isExplicitTemplateSpecialization())));
@@ -3727,7 +3959,7 @@ TEST(IsExplicitTemplateSpecialization,
EXPECT_TRUE(notMatches(
"template <typename T> class X {};"
"template class X<int>; extern template class X<long>;",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t) {}"
"template void f(int t); extern template void f(long t);",
@@ -3738,7 +3970,7 @@ TEST(IsExplicitTemplateSpecialization,
DoesNotMatchImplicitTemplateInstantiations) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {}; X<int> x;",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t); void g() { f(10); }",
functionDecl(isExplicitTemplateSpecialization())));
@@ -3749,7 +3981,7 @@ TEST(IsExplicitTemplateSpecialization,
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template<> class X<int> {};",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(matches(
"template <typename T> void f(T t) {}"
"template<> void f(int t) {}",
@@ -3831,7 +4063,7 @@ TEST(HasAncestor, MatchesInTemplateInstantiations) {
TEST(HasAncestor, MatchesInImplicitCode) {
EXPECT_TRUE(matches(
"struct X {}; struct A { A() {} X x; };",
- constructorDecl(
+ cxxConstructorDecl(
hasAnyConstructorInitializer(withInitializer(expr(
hasAncestor(recordDecl(hasName("A")))))))));
}
@@ -3854,8 +4086,9 @@ TEST(HasAncestor, MatchesAllAncestors) {
"void t() { C<int>::f(); }",
integerLiteral(
equals(42),
- allOf(hasAncestor(recordDecl(isTemplateInstantiation())),
- hasAncestor(recordDecl(unless(isTemplateInstantiation())))))));
+ allOf(
+ hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
+ hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
}
TEST(HasParent, MatchesAllParents) {
@@ -3865,23 +4098,23 @@ TEST(HasParent, MatchesAllParents) {
integerLiteral(
equals(42),
hasParent(compoundStmt(hasParent(functionDecl(
- hasParent(recordDecl(isTemplateInstantiation())))))))));
- EXPECT_TRUE(matches(
- "template <typename T> struct C { static void f() { 42; } };"
- "void t() { C<int>::f(); }",
- integerLiteral(
- equals(42),
- hasParent(compoundStmt(hasParent(functionDecl(
- hasParent(recordDecl(unless(isTemplateInstantiation()))))))))));
+ hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
+ EXPECT_TRUE(
+ matches("template <typename T> struct C { static void f() { 42; } };"
+ "void t() { C<int>::f(); }",
+ integerLiteral(
+ equals(42),
+ hasParent(compoundStmt(hasParent(functionDecl(hasParent(
+ cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
EXPECT_TRUE(matches(
"template <typename T> struct C { static void f() { 42; } };"
"void t() { C<int>::f(); }",
integerLiteral(equals(42),
- hasParent(compoundStmt(allOf(
- hasParent(functionDecl(
- hasParent(recordDecl(isTemplateInstantiation())))),
- hasParent(functionDecl(hasParent(recordDecl(
- unless(isTemplateInstantiation())))))))))));
+ hasParent(compoundStmt(
+ allOf(hasParent(functionDecl(hasParent(
+ cxxRecordDecl(isTemplateInstantiation())))),
+ hasParent(functionDecl(hasParent(cxxRecordDecl(
+ unless(isTemplateInstantiation())))))))))));
EXPECT_TRUE(
notMatches("template <typename T> struct C { static void f() {} };"
"void t() { C<int>::f(); }",
@@ -3913,9 +4146,16 @@ TEST(TypeMatching, MatchesTypes) {
EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
}
+TEST(TypeMatching, MatchesBool) {
+ EXPECT_TRUE(matches("struct S { bool func(); };",
+ cxxMethodDecl(returns(booleanType()))));
+ EXPECT_TRUE(notMatches("struct S { void func(); };",
+ cxxMethodDecl(returns(booleanType()))));
+}
+
TEST(TypeMatching, MatchesVoid) {
- EXPECT_TRUE(
- matches("struct S { void func(); };", methodDecl(returns(voidType()))));
+ EXPECT_TRUE(matches("struct S { void func(); };",
+ cxxMethodDecl(returns(voidType()))));
}
TEST(TypeMatching, MatchesArrayTypes) {
@@ -3952,6 +4192,11 @@ TEST(TypeMatching, MatchesArrayTypes) {
EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
}
+TEST(TypeMatching, DecayedType) {
+ EXPECT_TRUE(matches("void f(int i[]);", valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))));
+ EXPECT_TRUE(notMatches("int i[7];", decayedType()));
+}
+
TEST(TypeMatching, MatchesComplexTypes) {
EXPECT_TRUE(matches("_Complex float f;", complexType()));
EXPECT_TRUE(matches(
@@ -4247,6 +4492,18 @@ TEST(ElaboratedTypeNarrowing, namesType) {
elaboratedType(elaboratedType(namesType(typedefType())))));
}
+TEST(TypeMatching, MatchesSubstTemplateTypeParmType) {
+ const std::string code = "template <typename T>"
+ "int F() {"
+ " return 1 + T();"
+ "}"
+ "int i = F<int>();";
+ EXPECT_FALSE(matches(code, binaryOperator(hasLHS(
+ expr(hasType(substTemplateTypeParmType()))))));
+ EXPECT_TRUE(matches(code, binaryOperator(hasRHS(
+ expr(hasType(substTemplateTypeParmType()))))));
+}
+
TEST(NNS, MatchesNestedNameSpecifiers) {
EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
nestedNameSpecifier()));
@@ -4254,6 +4511,8 @@ TEST(NNS, MatchesNestedNameSpecifiers) {
nestedNameSpecifier()));
EXPECT_TRUE(matches("struct A { void f(); }; void A::f() {}",
nestedNameSpecifier()));
+ EXPECT_TRUE(matches("namespace a { namespace b {} } namespace ab = a::b;",
+ nestedNameSpecifier()));
EXPECT_TRUE(matches(
"struct A { static void f() {} }; void g() { A::f(); }",
@@ -4268,6 +4527,16 @@ TEST(NullStatement, SimpleCases) {
EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));
}
+TEST(NS, Anonymous) {
+ EXPECT_TRUE(notMatches("namespace N {}", namespaceDecl(isAnonymous())));
+ EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous())));
+}
+
+TEST(NS, Alias) {
+ EXPECT_TRUE(matches("namespace test {} namespace alias = ::test;",
+ namespaceAliasDecl(hasName("alias"))));
+}
+
TEST(NNS, MatchesTypes) {
NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
specifiesType(hasDeclaration(recordDecl(hasName("A")))));
@@ -4480,6 +4749,16 @@ public:
decl(has(decl(equalsNode(TypedNode)))).bind(""))),
*Node, Context)) != nullptr;
}
+ bool verify(const BoundNodes &Nodes, ASTContext &Context, const Type *Node) {
+ // Use the original typed pointer to verify we can pass pointers to subtypes
+ // to equalsNode.
+ const T *TypedNode = cast<T>(Node);
+ const auto *Dec = Nodes.getNodeAs<FieldDecl>("decl");
+ return selectFirst<T>(
+ "", match(fieldDecl(hasParent(decl(has(fieldDecl(
+ hasType(type(equalsNode(TypedNode)).bind(""))))))),
+ *Dec, Context)) != nullptr;
+ }
};
TEST(IsEqualTo, MatchesNodesByIdentity) {
@@ -4489,6 +4768,10 @@ TEST(IsEqualTo, MatchesNodesByIdentity) {
EXPECT_TRUE(matchAndVerifyResultTrue(
"void f() { if (true) if(true) {} }", ifStmt().bind(""),
new VerifyAncestorHasChildIsEqual<IfStmt>()));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class X { class Y {} y; };",
+ fieldDecl(hasName("y"), hasType(type().bind(""))).bind("decl"),
+ new VerifyAncestorHasChildIsEqual<Type>()));
}
TEST(MatchFinder, CheckProfiling) {
@@ -4656,12 +4939,12 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
"void f(StringRef v) {"
" v.data();"
"}",
- memberCallExpr(
- callee(methodDecl(hasName("data"))),
- on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
- .bind("var")))),
- unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
- callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("data"))),
+ on(declRefExpr(to(
+ varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+ callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
.bind("data"),
new VerifyIdIsBoundTo<Expr>("data", 1)));
@@ -4672,12 +4955,12 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
" v.data();"
" v.size();"
"}",
- memberCallExpr(
- callee(methodDecl(hasName("data"))),
- on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
- .bind("var")))),
- unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
- callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("data"))),
+ on(declRefExpr(to(
+ varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+ callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
.bind("data")));
}
@@ -4687,6 +4970,13 @@ TEST(TypeDefDeclMatcher, Match) {
typedefDecl(hasName("typedefDeclTest"))));
}
+TEST(IsInlineMatcher, IsInline) {
+ EXPECT_TRUE(matches("void g(); inline void f();",
+ functionDecl(isInline(), hasName("f"))));
+ EXPECT_TRUE(matches("namespace n { inline namespace m {} }",
+ namespaceDecl(isInline(), hasName("m"))));
+}
+
// FIXME: Figure out how to specify paths so the following tests pass on Windows.
#ifndef LLVM_ON_WIN32
@@ -4774,6 +5064,9 @@ TEST(ObjCMessageExprMatcher, SimpleExprs) {
objcMessageExpr(hasSelector("contents"), hasUnarySelector())));
EXPECT_TRUE(matchesObjC(
Objc1String,
+ objcMessageExpr(hasSelector("contents"), numSelectorArgs(0))));
+ EXPECT_TRUE(matchesObjC(
+ Objc1String,
objcMessageExpr(matchesSelector("uppercase*"),
argumentCountIs(0)
)));
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 403a305db2440..68824e61ac693 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -120,6 +120,19 @@ testing::AssertionResult matchesObjC(const std::string &Code,
}
template <typename T>
+testing::AssertionResult matchesC(const std::string &Code, const T &AMatcher) {
+ return matchesConditionally(Code, AMatcher, true, "", FileContentMappings(),
+ "input.c");
+}
+
+template <typename T>
+testing::AssertionResult notMatchesC(const std::string &Code,
+ const T &AMatcher) {
+ return matchesConditionally(Code, AMatcher, false, "", FileContentMappings(),
+ "input.c");
+}
+
+template <typename T>
testing::AssertionResult notMatchesObjC(const std::string &Code,
const T &AMatcher) {
return matchesConditionally(
@@ -165,6 +178,7 @@ testing::AssertionResult matchesConditionallyWithCuda(
Args.push_back("-xcuda");
Args.push_back("-fno-ms-extensions");
Args.push_back("--cuda-host-only");
+ Args.push_back("-nocudainc");
Args.push_back(CompileArg);
if (!runToolOnCodeWithArgs(Factory->create(),
CudaHeader + Code, Args)) {
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index 45b0910ab0a2d..0de6242a67b08 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -50,7 +50,7 @@ public:
}
VariantMatcher actOnMatcherExpression(MatcherCtor Ctor,
- const SourceRange &NameRange,
+ SourceRange NameRange,
StringRef BindID,
ArrayRef<ParserValue> Args,
Diagnostics *Error) override {
@@ -102,7 +102,7 @@ TEST(ParserTest, ParseString) {
EXPECT_EQ("1:1: Error parsing string token: <\"Baz>", Sema.Errors[2]);
}
-bool matchesRange(const SourceRange &Range, unsigned StartLine,
+bool matchesRange(SourceRange Range, unsigned StartLine,
unsigned EndLine, unsigned StartColumn, unsigned EndColumn) {
EXPECT_EQ(StartLine, Range.Start.Line);
EXPECT_EQ(EndLine, Range.End.Line);
@@ -301,12 +301,12 @@ TEST(ParserTest, CompletionNamedValues) {
EXPECT_EQ("String nameX", Comps[0].MatcherDecl);
// Can complete if there are names in the expression.
- Code = "methodDecl(hasName(nameX), ";
+ Code = "cxxMethodDecl(hasName(nameX), ";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
EXPECT_LT(0u, Comps.size());
// Can complete names and registry together.
- Code = "methodDecl(hasP";
+ Code = "cxxMethodDecl(hasP";
Comps = Parser::completeExpression(Code, Code.size(), nullptr, &NamedValues);
ASSERT_EQ(3u, Comps.size());
EXPECT_EQ("aramA", Comps[0].TypedText);
@@ -318,8 +318,10 @@ TEST(ParserTest, CompletionNamedValues) {
Comps[1].MatcherDecl);
EXPECT_EQ("arent(", Comps[2].TypedText);
- EXPECT_EQ("Matcher<Decl> hasParent(Matcher<Decl|Stmt>)",
- Comps[2].MatcherDecl);
+ EXPECT_EQ(
+ "Matcher<Decl> "
+ "hasParent(Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...>)",
+ Comps[2].MatcherDecl);
}
} // end anonymous namespace
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index a6b0a1b41d6b3..8e97566f69202 100644
--- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -129,7 +129,7 @@ TEST_F(RegistryTest, CanConstructNoArgs) {
Matcher<Stmt> IsArrowValue = constructMatcher(
"memberExpr", constructMatcher("isArrow")).getTypedMatcher<Stmt>();
Matcher<Stmt> BoolValue =
- constructMatcher("boolLiteral").getTypedMatcher<Stmt>();
+ constructMatcher("cxxBoolLiteral").getTypedMatcher<Stmt>();
const std::string ClassSnippet = "struct Foo { int x; };\n"
"Foo *foo = new Foo;\n"
@@ -195,7 +195,7 @@ TEST_F(RegistryTest, OverloadedMatchers) {
"callExpr",
constructMatcher(
"callee",
- constructMatcher("methodDecl",
+ constructMatcher("cxxMethodDecl",
constructMatcher("hasName", StringRef("x")))))
.getTypedMatcher<Stmt>();
@@ -255,11 +255,11 @@ TEST_F(RegistryTest, PolymorphicMatchers) {
EXPECT_FALSE(matches("void Foo(){};", RecordDecl));
Matcher<Stmt> ConstructExpr = constructMatcher(
- "constructExpr",
+ "cxxConstructExpr",
constructMatcher(
"hasDeclaration",
constructMatcher(
- "methodDecl",
+ "cxxMethodDecl",
constructMatcher(
"ofClass", constructMatcher("hasName", StringRef("Foo"))))))
.getTypedMatcher<Stmt>();
@@ -300,7 +300,7 @@ TEST_F(RegistryTest, TypeTraversal) {
TEST_F(RegistryTest, CXXCtorInitializer) {
Matcher<Decl> CtorDecl = constructMatcher(
- "constructorDecl",
+ "cxxConstructorDecl",
constructMatcher(
"hasAnyConstructorInitializer",
constructMatcher("forField",
@@ -416,9 +416,10 @@ TEST_F(RegistryTest, Errors) {
"(Actual = String)",
Error->toString());
Error.reset(new Diagnostics());
- EXPECT_TRUE(constructMatcher("recordDecl", constructMatcher("recordDecl"),
- constructMatcher("parameterCountIs", 3),
- Error.get()).isNull());
+ EXPECT_TRUE(
+ constructMatcher("cxxRecordDecl", constructMatcher("cxxRecordDecl"),
+ constructMatcher("parameterCountIs", 3), Error.get())
+ .isNull());
EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
"(Actual = Matcher<FunctionDecl>)",
Error->toString());
@@ -432,7 +433,7 @@ TEST_F(RegistryTest, Errors) {
Error->toString());
Error.reset(new Diagnostics());
EXPECT_TRUE(constructMatcher(
- "recordDecl",
+ "cxxRecordDecl",
constructMatcher("allOf",
constructMatcher("isDerivedFrom", StringRef("FOO")),
constructMatcher("isArrow")),
@@ -447,15 +448,17 @@ TEST_F(RegistryTest, Completion) {
CompVector Comps = getCompletions();
// Overloaded
EXPECT_TRUE(hasCompletion(
- Comps, "hasParent(", "Matcher<Decl|Stmt> hasParent(Matcher<Decl|Stmt>)"));
+ Comps, "hasParent(",
+ "Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...> "
+ "hasParent(Matcher<TemplateArgument|NestedNameSpecifierLoc|Decl|...>)"));
// Variadic.
EXPECT_TRUE(hasCompletion(Comps, "whileStmt(",
"Matcher<Stmt> whileStmt(Matcher<WhileStmt>...)"));
// Polymorphic.
EXPECT_TRUE(hasCompletion(
Comps, "hasDescendant(",
- "Matcher<NestedNameSpecifier|NestedNameSpecifierLoc|QualType|...> "
- "hasDescendant(Matcher<CXXCtorInitializer|NestedNameSpecifier|"
+ "Matcher<TemplateArgument|NestedNameSpecifier|NestedNameSpecifierLoc|...>"
+ " hasDescendant(Matcher<TemplateArgument|NestedNameSpecifier|"
"NestedNameSpecifierLoc|...>)"));
CompVector WhileComps = getCompletions("whileStmt", 0);
@@ -463,7 +466,9 @@ TEST_F(RegistryTest, Completion) {
EXPECT_TRUE(hasCompletion(WhileComps, "hasBody(",
"Matcher<WhileStmt> hasBody(Matcher<Stmt>)"));
EXPECT_TRUE(hasCompletion(WhileComps, "hasParent(",
- "Matcher<Stmt> hasParent(Matcher<Decl|Stmt>)"));
+ "Matcher<Stmt> "
+ "hasParent(Matcher<TemplateArgument|"
+ "NestedNameSpecifierLoc|Decl|...>)"));
EXPECT_TRUE(
hasCompletion(WhileComps, "allOf(", "Matcher<T> allOf(Matcher<T>...)"));
diff --git a/unittests/Basic/SourceManagerTest.cpp b/unittests/Basic/SourceManagerTest.cpp
index 494c27a2f1cdf..5a1a393fbf02a 100644
--- a/unittests/Basic/SourceManagerTest.cpp
+++ b/unittests/Basic/SourceManagerTest.cpp
@@ -66,7 +66,7 @@ class VoidModuleLoader : public ModuleLoader {
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
{ return nullptr; }
bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
+ { return 0; }
};
TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
diff --git a/unittests/Basic/VirtualFileSystemTest.cpp b/unittests/Basic/VirtualFileSystemTest.cpp
index 71d2d2b60c04c..ac07035d3e1f2 100644
--- a/unittests/Basic/VirtualFileSystemTest.cpp
+++ b/unittests/Basic/VirtualFileSystemTest.cpp
@@ -14,11 +14,24 @@
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
#include <map>
+
using namespace clang;
using namespace llvm;
using llvm::sys::fs::UniqueID;
namespace {
+struct DummyFile : public vfs::File {
+ vfs::Status S;
+ explicit DummyFile(vfs::Status S) : S(S) {}
+ llvm::ErrorOr<vfs::Status> status() override { return S; }
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ llvm_unreachable("unimplemented");
+ }
+ virtual std::error_code close() override { return std::error_code(); }
+};
+
class DummyFileSystem : public vfs::FileSystem {
int FSID; // used to produce UniqueIDs
int FileID; // used to produce UniqueIDs
@@ -41,7 +54,16 @@ public:
}
ErrorOr<std::unique_ptr<vfs::File>>
openFileForRead(const Twine &Path) override {
- llvm_unreachable("unimplemented");
+ auto S = status(Path);
+ if (S)
+ return std::unique_ptr<vfs::File>(new DummyFile{*S});
+ return S.getError();
+ }
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return std::string();
+ }
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ return std::error_code();
}
struct DirIterImpl : public clang::vfs::detail::DirIterImpl {
@@ -92,20 +114,20 @@ public:
}
void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
- 0, 0, 1024, sys::fs::file_type::regular_file, Perms);
+ vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
+ 1024, sys::fs::file_type::regular_file, Perms);
addEntry(Path, S);
}
void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
- vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
- 0, 0, 0, sys::fs::file_type::directory_file, Perms);
+ vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
+ 0, sys::fs::file_type::directory_file, Perms);
addEntry(Path, S);
}
void addSymlink(StringRef Path) {
- vfs::Status S(Path, Path, UniqueID(FSID, FileID++), sys::TimeValue::now(),
- 0, 0, 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
+ vfs::Status S(Path, UniqueID(FSID, FileID++), sys::TimeValue::now(), 0, 0,
+ 0, sys::fs::file_type::symlink_file, sys::fs::all_all);
addEntry(Path, S);
}
};
@@ -279,7 +301,7 @@ struct ScopedDir {
}
operator StringRef() { return Path.str(); }
};
-}
+} // end anonymous namespace
TEST(VirtualFileSystemTest, BasicRealFSIteration) {
ScopedDir TestDirectory("virtual-file-system-test", /*Unique*/true);
@@ -515,6 +537,128 @@ TEST(VirtualFileSystemTest, HiddenInIteration) {
}
}
+class InMemoryFileSystemTest : public ::testing::Test {
+protected:
+ clang::vfs::InMemoryFileSystem FS;
+ clang::vfs::InMemoryFileSystem NormalizedFS;
+
+ InMemoryFileSystemTest()
+ : FS(/*UseNormalizedPaths=*/false),
+ NormalizedFS(/*UseNormalizedPaths=*/true) {}
+};
+
+TEST_F(InMemoryFileSystemTest, IsEmpty) {
+ auto Stat = FS.status("/a");
+ ASSERT_EQ(Stat.getError(),errc::no_such_file_or_directory) << FS.toString();
+ Stat = FS.status("/");
+ ASSERT_EQ(Stat.getError(), errc::no_such_file_or_directory) << FS.toString();
+}
+
+TEST_F(InMemoryFileSystemTest, WindowsPath) {
+ FS.addFile("c:/windows/system128/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
+ auto Stat = FS.status("c:");
+#if !defined(_WIN32)
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+#endif
+ Stat = FS.status("c:/windows/system128/foo.cpp");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+ FS.addFile("d:/windows/foo.cpp", 0, MemoryBuffer::getMemBuffer(""));
+ Stat = FS.status("d:/windows/foo.cpp");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+}
+
+TEST_F(InMemoryFileSystemTest, OverlayFile) {
+ FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+ NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+ auto Stat = FS.status("/");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+ Stat = FS.status("/.");
+ ASSERT_FALSE(Stat);
+ Stat = NormalizedFS.status("/.");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << FS.toString();
+ Stat = FS.status("/a");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+ ASSERT_EQ("/a", Stat->getName());
+}
+
+TEST_F(InMemoryFileSystemTest, OverlayFileNoOwn) {
+ auto Buf = MemoryBuffer::getMemBuffer("a");
+ FS.addFileNoOwn("/a", 0, Buf.get());
+ auto Stat = FS.status("/a");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+ ASSERT_EQ("/a", Stat->getName());
+}
+
+TEST_F(InMemoryFileSystemTest, OpenFileForRead) {
+ FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+ FS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
+ FS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
+ NormalizedFS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a"));
+ NormalizedFS.addFile("././c", 0, MemoryBuffer::getMemBuffer("c"));
+ NormalizedFS.addFile("./d/../d", 0, MemoryBuffer::getMemBuffer("d"));
+ auto File = FS.openFileForRead("/a");
+ ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+ File = FS.openFileForRead("/a"); // Open again.
+ ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+ File = NormalizedFS.openFileForRead("/././a"); // Open again.
+ ASSERT_EQ("a", (*(*File)->getBuffer("ignored"))->getBuffer());
+ File = FS.openFileForRead("/");
+ ASSERT_EQ(File.getError(), errc::invalid_argument) << FS.toString();
+ File = FS.openFileForRead("/b");
+ ASSERT_EQ(File.getError(), errc::no_such_file_or_directory) << FS.toString();
+ File = FS.openFileForRead("./c");
+ ASSERT_FALSE(File);
+ File = FS.openFileForRead("e/../d");
+ ASSERT_FALSE(File);
+ File = NormalizedFS.openFileForRead("./c");
+ ASSERT_EQ("c", (*(*File)->getBuffer("ignored"))->getBuffer());
+ File = NormalizedFS.openFileForRead("e/../d");
+ ASSERT_EQ("d", (*(*File)->getBuffer("ignored"))->getBuffer());
+}
+
+TEST_F(InMemoryFileSystemTest, DuplicatedFile) {
+ ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
+ ASSERT_FALSE(FS.addFile("/a/b", 0, MemoryBuffer::getMemBuffer("a")));
+ ASSERT_TRUE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("a")));
+ ASSERT_FALSE(FS.addFile("/a", 0, MemoryBuffer::getMemBuffer("b")));
+}
+
+TEST_F(InMemoryFileSystemTest, DirectoryIteration) {
+ FS.addFile("/a", 0, MemoryBuffer::getMemBuffer(""));
+ FS.addFile("/b/c", 0, MemoryBuffer::getMemBuffer(""));
+
+ std::error_code EC;
+ vfs::directory_iterator I = FS.dir_begin("/", EC);
+ ASSERT_FALSE(EC);
+ ASSERT_EQ("/a", I->getName());
+ I.increment(EC);
+ ASSERT_FALSE(EC);
+ ASSERT_EQ("/b", I->getName());
+ I.increment(EC);
+ ASSERT_FALSE(EC);
+ ASSERT_EQ(vfs::directory_iterator(), I);
+
+ I = FS.dir_begin("/b", EC);
+ ASSERT_FALSE(EC);
+ ASSERT_EQ("/b/c", I->getName());
+ I.increment(EC);
+ ASSERT_FALSE(EC);
+ ASSERT_EQ(vfs::directory_iterator(), I);
+}
+
+TEST_F(InMemoryFileSystemTest, WorkingDirectory) {
+ FS.setCurrentWorkingDirectory("/b");
+ FS.addFile("c", 0, MemoryBuffer::getMemBuffer(""));
+
+ auto Stat = FS.status("/b/c");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+ ASSERT_EQ("c", Stat->getName());
+ ASSERT_EQ("/b", *FS.getCurrentWorkingDirectory());
+
+ Stat = FS.status("c");
+ ASSERT_FALSE(Stat.getError()) << Stat.getError() << "\n" << FS.toString();
+}
+
// NOTE: in the tests below, we use '//root/' as our root directory, since it is
// a legal *absolute* path on Windows as well as *nix.
class VFSFromYAMLTest : public ::testing::Test {
@@ -589,10 +733,20 @@ TEST_F(VFSFromYAMLTest, MappedFiles) {
ErrorOr<vfs::Status> S = O->status("//root/file1");
ASSERT_FALSE(S.getError());
EXPECT_EQ("//root/foo/bar/a", S->getName());
+ EXPECT_TRUE(S->IsVFSMapped);
ErrorOr<vfs::Status> SLower = O->status("//root/foo/bar/a");
EXPECT_EQ("//root/foo/bar/a", SLower->getName());
EXPECT_TRUE(S->equivalent(*SLower));
+ EXPECT_FALSE(SLower->IsVFSMapped);
+
+ // file after opening
+ auto OpenedF = O->openFileForRead("//root/file1");
+ ASSERT_FALSE(OpenedF.getError());
+ auto OpenedS = (*OpenedF)->status();
+ ASSERT_FALSE(OpenedS.getError());
+ EXPECT_EQ("//root/foo/bar/a", OpenedS->getName());
+ EXPECT_TRUE(OpenedS->IsVFSMapped);
// directory
S = O->status("//root/");
@@ -906,7 +1060,7 @@ TEST_F(VFSFromYAMLTest, DirectoryIteration) {
"]\n"
"}",
Lower);
- ASSERT_TRUE(FS.get() != NULL);
+ ASSERT_TRUE(FS.get() != nullptr);
IntrusiveRefCntPtr<vfs::OverlayFileSystem> O(
new vfs::OverlayFileSystem(Lower));
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 6636d82db74d5..b85ec7e6dfa09 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -25,6 +25,6 @@ add_subdirectory(Sema)
add_subdirectory(CodeGen)
# FIXME: libclang unit tests are disabled on Windows due
# to failures, mostly in libclang.VirtualFileOverlay_*.
-if(NOT WIN32)
+if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)
add_subdirectory(libclang)
endif()
diff --git a/unittests/CodeGen/BufferSourceTest.cpp b/unittests/CodeGen/BufferSourceTest.cpp
index e80e83bd28870..85df768aa1b44 100644
--- a/unittests/CodeGen/BufferSourceTest.cpp
+++ b/unittests/CodeGen/BufferSourceTest.cpp
@@ -67,7 +67,7 @@ TEST(BufferSourceTest, EmitCXXGlobalInitFunc) {
compiler.getCodeGenOpts(),
llvm::getGlobalContext())));
- compiler.createSema(clang::TU_Prefix,NULL);
+ compiler.createSema(clang::TU_Prefix, nullptr);
clang::SourceManager &sm = compiler.getSourceManager();
sm.setMainFileID(sm.createFileID(
@@ -76,4 +76,4 @@ TEST(BufferSourceTest, EmitCXXGlobalInitFunc) {
clang::ParseAST(compiler.getSema(), false, false);
}
-}
+} // end anonymous namespace
diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt
index 8cc963b33a21b..2df1eb24fd44e 100644
--- a/unittests/Driver/CMakeLists.txt
+++ b/unittests/Driver/CMakeLists.txt
@@ -3,9 +3,11 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_unittest(ClangDriverTests
+ ToolChainTest.cpp
MultilibTest.cpp
)
target_link_libraries(ClangDriverTests
clangDriver
+ clangBasic
)
diff --git a/unittests/Driver/ToolChainTest.cpp b/unittests/Driver/ToolChainTest.cpp
new file mode 100644
index 0000000000000..ef21e2d17c6c8
--- /dev/null
+++ b/unittests/Driver/ToolChainTest.cpp
@@ -0,0 +1,120 @@
+//===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for ToolChains.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/ToolChain.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace clang;
+using namespace clang::driver;
+
+namespace {
+
+TEST(ToolChainTest, VFSGCCInstallation) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags,
+ InMemoryFileSystem);
+
+ const char *EmptyFiles[] = {
+ "foo.cpp",
+ "/bin/clang",
+ "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",
+ "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o",
+ "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o",
+ "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o",
+ "/usr/lib/arm-linux-gnueabi/crt1.o",
+ "/usr/lib/arm-linux-gnueabi/crti.o",
+ "/usr/lib/arm-linux-gnueabi/crtn.o",
+ "/usr/lib/arm-linux-gnueabihf/crt1.o",
+ "/usr/lib/arm-linux-gnueabihf/crti.o",
+ "/usr/lib/arm-linux-gnueabihf/crtn.o",
+ "/usr/include/arm-linux-gnueabi/.keep",
+ "/usr/include/arm-linux-gnueabihf/.keep",
+ "/lib/arm-linux-gnueabi/.keep",
+ "/lib/arm-linux-gnueabihf/.keep"};
+
+ for (const char *Path : EmptyFiles)
+ InMemoryFileSystem->addFile(Path, 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+ {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"}));
+
+ std::string S;
+ {
+ llvm::raw_string_ostream OS(S);
+ C->getDefaultToolChain().printVerboseInfo(OS);
+ }
+#if LLVM_ON_WIN32
+ std::replace(S.begin(), S.end(), '\\', '/');
+#endif
+ EXPECT_EQ(
+ "Found candidate GCC installation: "
+ "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"
+ "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"
+ "Candidate multilib: .;@m32\n"
+ "Selected multilib: .;@m32\n",
+ S);
+}
+
+TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
+ IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ struct TestDiagnosticConsumer : public DiagnosticConsumer {};
+ DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
+ InMemoryFileSystem);
+
+ const char *EmptyFiles[] = {
+ "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",
+ "/home/test/include/arm-linux-gnueabi/.keep"};
+
+ for (const char *Path : EmptyFiles)
+ InMemoryFileSystem->addFile(Path, 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
+
+ std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
+ {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"}));
+
+ std::string S;
+ {
+ llvm::raw_string_ostream OS(S);
+ C->getDefaultToolChain().printVerboseInfo(OS);
+ }
+#if LLVM_ON_WIN32
+ std::replace(S.begin(), S.end(), '\\', '/');
+#endif
+ EXPECT_EQ("Found candidate GCC installation: "
+ "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1\n"
+ "Selected GCC installation: "
+ "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
+ "Candidate multilib: .;@m32\n"
+ "Selected multilib: .;@m32\n",
+ S);
+}
+
+} // end anonymous namespace
diff --git a/unittests/Format/CMakeLists.txt b/unittests/Format/CMakeLists.txt
index 6d48cf871335c..01af435fffced 100644
--- a/unittests/Format/CMakeLists.txt
+++ b/unittests/Format/CMakeLists.txt
@@ -8,6 +8,7 @@ add_clang_unittest(FormatTests
FormatTestJS.cpp
FormatTestProto.cpp
FormatTestSelective.cpp
+ SortIncludesTest.cpp
)
target_link_libraries(FormatTests
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index d61dc7f662c2f..6a0506d89732b 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -313,7 +313,7 @@ TEST_F(FormatTest, FormatIfWithoutCompoundStatement) {
" f();\n"
"}",
AllowsMergedIf);
- verifyFormat("if (a) {/* Never merge this */\n"
+ verifyFormat("if (a) { /* Never merge this */\n"
" f();\n"
"}",
AllowsMergedIf);
@@ -756,6 +756,9 @@ TEST_F(FormatTest, ShortCaseLabels) {
"case 7:\n"
" // comment\n"
" return;\n"
+ "case 8:\n"
+ " x = 8; // comment\n"
+ " break;\n"
"default: y = 1; break;\n"
"}",
Style);
@@ -1194,6 +1197,13 @@ TEST_F(FormatTest, AlignsBlockComments) {
"comment */"));
}
+TEST_F(FormatTest, CommentReflowingCanBeTurnedOff) {
+ FormatStyle Style = getLLVMStyleWithColumns(20);
+ Style.ReflowComments = false;
+ verifyFormat("// aaaaaaaaa aaaaaaaaaa aaaaaaaaaa", Style);
+ verifyFormat("/* aaaaaaaaa aaaaaaaaaa aaaaaaaaaa */", Style);
+}
+
TEST_F(FormatTest, CorrectlyHandlesLengthOfBlockComments) {
EXPECT_EQ("double *x; /* aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */",
@@ -1864,11 +1874,21 @@ TEST_F(FormatTest, UnderstandsAccessSpecifiers) {
"};");
verifyFormat("class A {\n"
"public slots:\n"
- " void f() {}\n"
+ " void f1() {}\n"
"public Q_SLOTS:\n"
- " void f() {}\n"
+ " void f2() {}\n"
+ "protected slots:\n"
+ " void f3() {}\n"
+ "protected Q_SLOTS:\n"
+ " void f4() {}\n"
+ "private slots:\n"
+ " void f5() {}\n"
+ "private Q_SLOTS:\n"
+ " void f6() {}\n"
"signals:\n"
- " void g();\n"
+ " void g1();\n"
+ "Q_SIGNALS:\n"
+ " void g2();\n"
"};");
// Don't interpret 'signals' the wrong way.
@@ -2189,6 +2209,13 @@ TEST_F(FormatTest, FormatsNamespaces) {
"} // my_namespace\n"
"#endif // HEADER_GUARD"));
+ EXPECT_EQ("namespace A::B {\n"
+ "class C {};\n"
+ "}",
+ format("namespace A::B {\n"
+ "class C {};\n"
+ "}"));
+
FormatStyle Style = getLLVMStyle();
Style.NamespaceIndentation = FormatStyle::NI_All;
EXPECT_EQ("namespace out {\n"
@@ -2329,13 +2356,16 @@ TEST_F(FormatTest, IncompleteTryCatchBlocks) {
TEST_F(FormatTest, FormatTryCatchBraceStyles) {
FormatStyle Style = getLLVMStyle();
- Style.BreakBeforeBraces = FormatStyle::BS_Attach;
- verifyFormat("try {\n"
- " // something\n"
- "} catch (...) {\n"
- " // something\n"
- "}",
- Style);
+ for (auto BraceStyle : {FormatStyle::BS_Attach, FormatStyle::BS_Mozilla,
+ FormatStyle::BS_WebKit}) {
+ Style.BreakBeforeBraces = BraceStyle;
+ verifyFormat("try {\n"
+ " // something\n"
+ "} catch (...) {\n"
+ " // something\n"
+ "}",
+ Style);
+ }
Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
verifyFormat("try {\n"
" // something\n"
@@ -2378,6 +2408,15 @@ TEST_F(FormatTest, FormatTryCatchBraceStyles) {
" // something\n"
" }",
Style);
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.BeforeCatch = true;
+ verifyFormat("try {\n"
+ " // something\n"
+ "}\n"
+ "catch (...) {\n"
+ " // something\n"
+ "}",
+ Style);
}
TEST_F(FormatTest, FormatObjCTryCatch) {
@@ -2905,6 +2944,8 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) {
" EXCLUSIVE_LOCK_FUNCTION(mu_);\n"
"};",
getLLVMStyleWithColumns(40)));
+
+ verifyFormat("MACRO(>)");
}
TEST_F(FormatTest, LayoutMacroDefinitionsStatementsSpanningBlocks) {
@@ -3073,10 +3114,12 @@ TEST_F(FormatTest, LayoutBlockInsideParens) {
" int i;\n"
" int j;\n"
"});");
- verifyFormat("functionCall({\n"
- " int i;\n"
- " int j;\n"
- "}, aaaa, bbbb, cccc);");
+ verifyFormat("functionCall(\n"
+ " {\n"
+ " int i;\n"
+ " int j;\n"
+ " },\n"
+ " aaaa, bbbb, cccc);");
verifyFormat("functionA(functionB({\n"
" int i;\n"
" int j;\n"
@@ -3183,9 +3226,11 @@ TEST_F(FormatTest, LayoutNestedBlocks) {
"});");
FormatStyle Style = getGoogleStyle();
Style.ColumnLimit = 45;
- verifyFormat("Debug(aaaaa, {\n"
- " if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n"
- "}, a);",
+ verifyFormat("Debug(aaaaa,\n"
+ " {\n"
+ " if (aaaaaaaaaaaaaaaaaaaaaaaa) return;\n"
+ " },\n"
+ " a);",
Style);
verifyFormat("SomeFunction({MACRO({ return output; }), b});");
@@ -3296,7 +3341,7 @@ TEST_F(FormatTest, LineBreakingInBinaryExpressions) {
verifyFormat("aaaaaa = aaaaaaa(aaaaaaa, // break\n"
" aaaaaa) >>\n"
" bbbbbb;");
- verifyFormat("Whitespaces.addUntouchableComment(\n"
+ verifyFormat("aa = Whitespaces.addUntouchableComment(\n"
" SourceMgr.getSpellingColumnNumber(\n"
" TheLine.Last->FormatTok.Tok.getLocation()) -\n"
" 1);");
@@ -3484,7 +3529,7 @@ TEST_F(FormatTest, NoOperandAlignment) {
" * cccccccccccccccccccccccccccccccccccc;",
Style);
- Style.AlignAfterOpenBracket = false;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
verifyFormat("return (a > b\n"
" // comment1\n"
" // comment2\n"
@@ -3512,6 +3557,10 @@ TEST_F(FormatTest, ConstructorInitializers) {
" : Inttializer(FitsOnTheLine) {}",
getLLVMStyleWithColumns(43));
+ verifyFormat("template <typename T>\n"
+ "Constructor() : Initializer(FitsOnTheLine) {}",
+ getLLVMStyleWithColumns(45));
+
verifyFormat(
"SomeClass::Constructor()\n"
" : aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}");
@@ -3524,6 +3573,9 @@ TEST_F(FormatTest, ConstructorInitializers) {
"SomeClass::Constructor()\n"
" : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
" aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}");
+ verifyFormat("Constructor(aaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " : aaaaaaaaaa(aaaaaa) {}");
verifyFormat("Constructor()\n"
" : aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
@@ -3581,6 +3633,11 @@ TEST_F(FormatTest, ConstructorInitializers) {
" : aaaaa(aaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaaa) {}",
OnePerLine);
+ OnePerLine.ColumnLimit = 60;
+ verifyFormat("Constructor()\n"
+ " : aaaaaaaaaaaaaaaaaaaa(a),\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbb(b) {}",
+ OnePerLine);
EXPECT_EQ("Constructor()\n"
" : // Comment forcing unwanted break.\n"
@@ -3893,6 +3950,8 @@ TEST_F(FormatTest, BreaksFunctionDeclarationsWithTrailingTokens) {
TEST_F(FormatTest, FunctionAnnotations) {
verifyFormat("DEPRECATED(\"Use NewClass::NewFunction instead.\")\n"
+ "int OldFunction(const string &parameter) {}");
+ verifyFormat("DEPRECATED(\"Use NewClass::NewFunction instead.\")\n"
"string OldFunction(const string &parameter) {}");
verifyFormat("template <typename T>\n"
"DEPRECATED(\"Use NewClass::NewFunction instead.\")\n"
@@ -4038,7 +4097,8 @@ TEST_F(FormatTest, FormatsOneParameterPerLineIfNecessary) {
verifyFormat("std::vector<aaaaaaaaaaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaaaaaaaaa> aaaaaaaaaaaaaaaaaa;",
+ " aaaaaaaaaaaaaaaaaaaaaaa>\n"
+ " aaaaaaaaaaaaaaaaaa;",
NoBinPacking);
verifyFormat("a(\"a\"\n"
" \"a\",\n"
@@ -4097,10 +4157,14 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
verifyFormat("return aaaaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa() <\n"
" aaaaaaaaaaaaaaa->aaaaa().aaaaaaaaaaaaa().aaaaaa();");
verifyFormat(
- "aaaaaaa->aaaaaaa->aaaaaaaaaaaaaaaa(\n"
+ "aaaaaaa->aaaaaaa->aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
" ->aaaaaaaa(aaaaaaaaaaaaaaa);");
verifyFormat(
+ "aaaaaaa->aaaaaaa\n"
+ " ->aaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " ->aaaaaaaa(aaaaaaaaaaaaaaa);");
+ verifyFormat(
"aaaaaaaaaaaaaaaaaaa()->aaaaaa(bbbbb)->aaaaaaaaaaaaaaaaaaa( // break\n"
" aaaaaaaaaaaaaa);");
verifyFormat(
@@ -4164,6 +4228,12 @@ TEST_F(FormatTest, FormatsBuilderPattern) {
// Prefer not to break after empty parentheses.
verifyFormat("FirstToken->WhitespaceRange.getBegin().getLocWithOffset(\n"
" First->LastNewlineOffset);");
+
+ // Prefer not to create "hanging" indents.
+ verifyFormat(
+ "return !soooooooooooooome_map\n"
+ " .insert(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)\n"
+ " .second;");
}
TEST_F(FormatTest, BreaksAccordingToOperatorPrecedence) {
@@ -4279,7 +4349,7 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) {
"SomeLongVariableName->someFunction(foooooooo(aaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaa));");
FormatStyle Style = getLLVMStyle();
- Style.AlignAfterOpenBracket = false;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
" aaaaaaaaaaa aaaaaaaa, aaaaaaaaa aaaaaaa) {}",
Style);
@@ -4301,6 +4371,26 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) {
"SomeLongVariableName->someFunction(foooooooo(aaaaaaaaaaaaaaa,\n"
" aaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa));",
Style);
+
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ Style.BinPackArguments = false;
+ Style.BinPackParameters = false;
+ verifyFormat("void aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
+ " aaaaaaaaaaa aaaaaaaa,\n"
+ " aaaaaaaaa aaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}",
+ Style);
+ verifyFormat("SomeLongVariableName->someVeryLongFunctionName(\n"
+ " aaaaaaaaaaa aaaaaaaaa,\n"
+ " aaaaaaaaaaa aaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);",
+ Style);
+ verifyFormat("SomeLongVariableName->someFunction(\n"
+ " foooooooo(\n"
+ " aaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa));",
+ Style);
}
TEST_F(FormatTest, ParenthesesAndOperandAlignment) {
@@ -4308,17 +4398,17 @@ TEST_F(FormatTest, ParenthesesAndOperandAlignment) {
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
- Style.AlignAfterOpenBracket = true;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
Style.AlignOperands = false;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
- Style.AlignAfterOpenBracket = false;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Style.AlignOperands = true;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
Style);
- Style.AlignAfterOpenBracket = false;
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
Style.AlignOperands = false;
verifyFormat("int a = f(aaaaaaaaaaaaaaaaaaaaaa &&\n"
" bbbbbbbbbbbbbbbbbbbbbb);",
@@ -4642,28 +4732,82 @@ TEST_F(FormatTest, AlignsStringLiterals) {
" \"c\";");
}
-TEST_F(FormatTest, DefinitionReturnTypeBreakingStyle) {
+TEST_F(FormatTest, ReturnTypeBreakingStyle) {
FormatStyle Style = getLLVMStyle();
- Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_TopLevel;
- verifyFormat("class C {\n"
+ // No declarations or definitions should be moved to own line.
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
+ verifyFormat("class A {\n"
" int f() { return 1; }\n"
+ " int g();\n"
+ "};\n"
+ "int f() { return 1; }\n"
+ "int g();\n",
+ Style);
+
+ // All declarations and definitions should have the return type moved to its
+ // own
+ // line.
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All;
+ verifyFormat("class E {\n"
+ " int\n"
+ " f() {\n"
+ " return 1;\n"
+ " }\n"
+ " int\n"
+ " g();\n"
"};\n"
"int\n"
"f() {\n"
" return 1;\n"
- "}",
+ "}\n"
+ "int\n"
+ "g();\n",
Style);
- Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
+
+ // Top-level definitions, and no kinds of declarations should have the
+ // return type moved to its own line.
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevelDefinitions;
+ verifyFormat("class B {\n"
+ " int f() { return 1; }\n"
+ " int g();\n"
+ "};\n"
+ "int\n"
+ "f() {\n"
+ " return 1;\n"
+ "}\n"
+ "int g();\n",
+ Style);
+
+ // Top-level definitions and declarations should have the return type moved
+ // to its own line.
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
verifyFormat("class C {\n"
+ " int f() { return 1; }\n"
+ " int g();\n"
+ "};\n"
+ "int\n"
+ "f() {\n"
+ " return 1;\n"
+ "}\n"
+ "int\n"
+ "g();\n",
+ Style);
+
+ // All definitions should have the return type moved to its own line, but no
+ // kinds of declarations.
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
+ verifyFormat("class D {\n"
" int\n"
" f() {\n"
" return 1;\n"
" }\n"
+ " int g();\n"
"};\n"
"int\n"
"f() {\n"
" return 1;\n"
- "}",
+ "}\n"
+ "int g();\n",
Style);
verifyFormat("const char *\n"
"f(void) {\n" // Break here.
@@ -4678,6 +4822,32 @@ TEST_F(FormatTest, DefinitionReturnTypeBreakingStyle) {
"}\n"
"template <class T> T *f(T &c);\n", // No break here.
Style);
+ verifyFormat("class C {\n"
+ " int\n"
+ " operator+() {\n"
+ " return 1;\n"
+ " }\n"
+ " int\n"
+ " operator()() {\n"
+ " return 1;\n"
+ " }\n"
+ "};\n",
+ Style);
+ verifyFormat("void\n"
+ "A::operator()() {}\n"
+ "void\n"
+ "A::operator>>() {}\n"
+ "void\n"
+ "A::operator+() {}\n",
+ Style);
+ verifyFormat("void *operator new(std::size_t s);", // No break here.
+ Style);
+ verifyFormat("void *\n"
+ "operator new(std::size_t s) {}",
+ Style);
+ verifyFormat("void *\n"
+ "operator delete[](void *ptr) {}",
+ Style);
Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
verifyFormat("const char *\n"
"f(void)\n" // Break here.
@@ -5135,6 +5305,8 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) {
EXPECT_EQ("A<A<A<A>>> a;", format("A<A<A<A>> > a;", getGoogleStyle()));
EXPECT_EQ("A<::A<int>> a;", format("A< ::A<int>> a;", getGoogleStyle()));
EXPECT_EQ("A<::A<int>> a;", format("A<::A<int> > a;", getGoogleStyle()));
+ EXPECT_EQ("auto x = [] { A<A<A<A>>> a; };",
+ format("auto x=[]{A<A<A<A> >> a;};", getGoogleStyle()));
verifyFormat("A<A>> a;", getChromiumStyle(FormatStyle::LK_Cpp));
@@ -5280,36 +5452,44 @@ TEST_F(FormatTest, UnderstandsOverloadedOperators) {
verifyGoogleFormat("operator ::A();");
verifyFormat("using A::operator+;");
+ verifyFormat("inline A operator^(const A &lhs, const A &rhs) {}\n"
+ "int i;");
}
TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
- verifyFormat("Deleted &operator=(const Deleted &)& = default;");
- verifyFormat("Deleted &operator=(const Deleted &)&& = delete;");
- verifyFormat("SomeType MemberFunction(const Deleted &)& = delete;");
- verifyFormat("SomeType MemberFunction(const Deleted &)&& = delete;");
- verifyFormat("Deleted &operator=(const Deleted &)&;");
- verifyFormat("Deleted &operator=(const Deleted &)&&;");
- verifyFormat("SomeType MemberFunction(const Deleted &)&;");
- verifyFormat("SomeType MemberFunction(const Deleted &)&&;");
+ verifyFormat("Deleted &operator=(const Deleted &) & = default;");
+ verifyFormat("Deleted &operator=(const Deleted &) && = delete;");
+ verifyFormat("SomeType MemberFunction(const Deleted &) & = delete;");
+ verifyFormat("SomeType MemberFunction(const Deleted &) && = delete;");
+ verifyFormat("Deleted &operator=(const Deleted &) &;");
+ verifyFormat("Deleted &operator=(const Deleted &) &&;");
+ verifyFormat("SomeType MemberFunction(const Deleted &) &;");
+ verifyFormat("SomeType MemberFunction(const Deleted &) &&;");
+ verifyFormat("SomeType MemberFunction(const Deleted &) && {}");
+ verifyFormat("SomeType MemberFunction(const Deleted &) && final {}");
+ verifyFormat("SomeType MemberFunction(const Deleted &) && override {}");
- verifyGoogleFormat("Deleted& operator=(const Deleted&)& = default;");
- verifyGoogleFormat("SomeType MemberFunction(const Deleted&)& = delete;");
- verifyGoogleFormat("Deleted& operator=(const Deleted&)&;");
- verifyGoogleFormat("SomeType MemberFunction(const Deleted&)&;");
+ FormatStyle AlignLeft = getLLVMStyle();
+ AlignLeft.PointerAlignment = FormatStyle::PAS_Left;
+ verifyFormat("Deleted& operator=(const Deleted&) & = default;", AlignLeft);
+ verifyFormat("SomeType MemberFunction(const Deleted&) & = delete;",
+ AlignLeft);
+ verifyFormat("Deleted& operator=(const Deleted&) &;", AlignLeft);
+ verifyFormat("SomeType MemberFunction(const Deleted&) &;", AlignLeft);
FormatStyle Spaces = getLLVMStyle();
Spaces.SpacesInCStyleCastParentheses = true;
- verifyFormat("Deleted &operator=(const Deleted &)& = default;", Spaces);
- verifyFormat("SomeType MemberFunction(const Deleted &)& = delete;", Spaces);
- verifyFormat("Deleted &operator=(const Deleted &)&;", Spaces);
- verifyFormat("SomeType MemberFunction(const Deleted &)&;", Spaces);
+ verifyFormat("Deleted &operator=(const Deleted &) & = default;", Spaces);
+ verifyFormat("SomeType MemberFunction(const Deleted &) & = delete;", Spaces);
+ verifyFormat("Deleted &operator=(const Deleted &) &;", Spaces);
+ verifyFormat("SomeType MemberFunction(const Deleted &) &;", Spaces);
Spaces.SpacesInCStyleCastParentheses = false;
Spaces.SpacesInParentheses = true;
- verifyFormat("Deleted &operator=( const Deleted & )& = default;", Spaces);
- verifyFormat("SomeType MemberFunction( const Deleted & )& = delete;", Spaces);
- verifyFormat("Deleted &operator=( const Deleted & )&;", Spaces);
- verifyFormat("SomeType MemberFunction( const Deleted & )&;", Spaces);
+ verifyFormat("Deleted &operator=( const Deleted & ) & = default;", Spaces);
+ verifyFormat("SomeType MemberFunction( const Deleted & ) & = delete;", Spaces);
+ verifyFormat("Deleted &operator=( const Deleted & ) &;", Spaces);
+ verifyFormat("SomeType MemberFunction( const Deleted & ) &;", Spaces);
}
TEST_F(FormatTest, UnderstandsNewAndDelete) {
@@ -5370,6 +5550,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyIndependentOfContext("return (int **&)a;");
verifyIndependentOfContext("f((*PointerToArray)[10]);");
verifyFormat("void f(Type (*parameter)[10]) {}");
+ verifyFormat("void f(Type (&parameter)[10]) {}");
verifyGoogleFormat("return sizeof(int**);");
verifyIndependentOfContext("Type **A = static_cast<Type **>(P);");
verifyGoogleFormat("Type** A = static_cast<Type**>(P);");
@@ -5377,6 +5558,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
verifyFormat("auto PointerBinding = [](const char *S) {};");
verifyFormat("typedef typeof(int(int, int)) *MyFunc;");
verifyFormat("[](const decltype(*a) &value) {}");
+ verifyFormat("decltype(a * b) F();");
verifyFormat("#define MACRO() [](A *a) { return 1; }");
verifyIndependentOfContext("typedef void (*f)(int *a);");
verifyIndependentOfContext("int i{a * b};");
@@ -5430,6 +5612,8 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
FormatStyle Left = getLLVMStyle();
Left.PointerAlignment = FormatStyle::PAS_Left;
verifyFormat("x = *a(x) = *a(y);", Left);
+ verifyFormat("for (;; * = b) {\n}", Left);
+ verifyFormat("return *this += 1;", Left);
verifyIndependentOfContext("a = *(x + y);");
verifyIndependentOfContext("a = &(x + y);");
@@ -5513,6 +5697,7 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) {
// verifyIndependentOfContext("MACRO(A *a);");
verifyFormat("DatumHandle const *operator->() const { return input_; }");
+ verifyFormat("return options != nullptr && operator==(*options);");
EXPECT_EQ("#define OP(x) \\\n"
" ostream &operator<<(ostream &s, const A &a) { \\\n"
@@ -5558,7 +5743,7 @@ TEST_F(FormatTest, UnderstandsAttributes) {
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa __attribute__((unused))\n"
"aaaaaaaaaaaaaaaaaaaaaaa(int i);");
FormatStyle AfterType = getLLVMStyle();
- AfterType.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
+ AfterType.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
verifyFormat("__attribute__((nodebug)) void\n"
"foo() {}\n",
AfterType);
@@ -5596,6 +5781,15 @@ TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) {
"int * a;\n"
"int * a;",
getGoogleStyle()));
+ EXPECT_EQ("auto x = [] {\n"
+ " int *a;\n"
+ " int *a;\n"
+ " int *a;\n"
+ "};",
+ format("auto x=[]{int *a;\n"
+ "int * a;\n"
+ "int * a;};",
+ getGoogleStyle()));
}
TEST_F(FormatTest, UnderstandsRvalueReferences) {
@@ -5700,6 +5894,8 @@ TEST_F(FormatTest, FormatsCasts) {
verifyFormat("virtual void foo(int *a, char *) const;");
verifyFormat("int a = sizeof(int *) + b;");
verifyFormat("int a = alignof(int *) + b;", getGoogleStyle());
+ verifyFormat("bool b = f(g<int>) && c;");
+ verifyFormat("typedef void (*f)(int i) func;");
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa *foo = (aaaaaaaaaaaaaaaaa *)\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;");
@@ -5732,6 +5928,7 @@ TEST_F(FormatTest, FormatsFunctionTypes) {
verifyFormat("#define DEREF_AND_CALL_F(x) f(*x)");
verifyFormat("some_var = function(*some_pointer_var)[0];");
verifyFormat("void f() { function(*some_pointer_var)[0] = 10; }");
+ verifyFormat("int x = f(&h)();");
}
TEST_F(FormatTest, FormatsPointersToArrayTypes) {
@@ -5848,6 +6045,8 @@ TEST_F(FormatTest, BreaksLongDeclarations) {
TEST_F(FormatTest, FormatsArrays) {
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaa[aaaaaaaaaaaaaaaaaaaaaaaaa]\n"
" [bbbbbbbbbbbbbbbbbbbbbbbbb] = c;");
+ verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaa[aaaaaaaaaaa(aaaaaaaaaaaa)]\n"
+ " [bbbbbbbbbbb(bbbbbbbbbbbb)] = c;");
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
" [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb] = ccccccccccc;");
verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
@@ -6098,6 +6297,7 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) {
" void f() { int i{2}; }\n"
" };\n"
"};");
+ verifyFormat("#define A {a, a},");
// In combination with BinPackArguments = false.
FormatStyle NoBinPacking = getLLVMStyle();
@@ -6307,6 +6507,11 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
" 1111111111, 2222222222, 33333333333, 4444444444, //\n"
" 111111111, 222222222, 3333333333, 444444444, //\n"
" 11111111, 22222222, 333333333, 44444444};");
+ // Trailing comment in the last line.
+ verifyFormat("int aaaaa[] = {\n"
+ " 1, 2, 3, // comment\n"
+ " 4, 5, 6 // comment\n"
+ "};");
// With nested lists, we should either format one item per line or all nested
// lists one on line.
@@ -6331,6 +6536,12 @@ TEST_F(FormatTest, FormatsBracedListsInColumnLayout) {
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb};");
verifyNoCrash("a<,");
+
+ // No braced initializer here.
+ verifyFormat("void f() {\n"
+ " struct Dummy {};\n"
+ " f(v);\n"
+ "}");
}
TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) {
@@ -6509,6 +6720,8 @@ TEST_F(FormatTest, DoNotInterfereWithErrorAndWarning) {
TEST_F(FormatTest, FormatHashIfExpressions) {
verifyFormat("#if AAAA && BBBB");
+ verifyFormat("#if (AAAA && BBBB)");
+ verifyFormat("#elif (AAAA && BBBB)");
// FIXME: Come up with a better indentation for #elif.
verifyFormat(
"#if !defined(AAAAAAA) && (defined CCCCCC || defined DDDDDD) && \\\n"
@@ -7074,6 +7287,22 @@ TEST_F(FormatTest, FormatObjCMethodDeclarations) {
" y:(id<yyyyyyyyyyyyyyyyyyyy>)y\n"
" NS_DESIGNATED_INITIALIZER;",
getLLVMStyleWithColumns(60));
+
+ // Continuation indent width should win over aligning colons if the function
+ // name is long.
+ FormatStyle continuationStyle = getGoogleStyle();
+ continuationStyle.ColumnLimit = 40;
+ continuationStyle.IndentWrappedFunctionNames = true;
+ verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
+ " dontAlignNamef:(NSRect)theRect {\n"
+ "}",
+ continuationStyle);
+
+ // Make sure we don't break aligning for short parameter names.
+ verifyFormat("- (void)shortf:(GTMFoo *)theFoo\n"
+ " aShortf:(NSRect)theRect {\n"
+ "}",
+ continuationStyle);
}
TEST_F(FormatTest, FormatObjCMethodExpr) {
@@ -7238,8 +7467,8 @@ TEST_F(FormatTest, FormatObjCMethodExpr) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa];");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaa[aaaaaaaaaaaaaaaaaaaaa]\n"
" aaaaaaaaaaaaaaaaaaaaaa];");
- verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
- " .aaaaaaaa];", // FIXME: Indentation seems off.
+ verifyFormat("[call aaaaaaaa.aaaaaa.aaaaaaaa.aaaaaaaa.aaaaaaaa\n"
+ " .aaaaaaaa.aaaaaaaa];", // FIXME: Indentation seems off.
getLLVMStyleWithColumns(60));
verifyFormat(
@@ -7345,6 +7574,19 @@ TEST_F(FormatTest, ObjCSnippets) {
"@import baz;");
}
+TEST_F(FormatTest, ObjCForIn) {
+ verifyFormat("- (void)test {\n"
+ " for (NSString *n in arrayOfStrings) {\n"
+ " foo(n);\n"
+ " }\n"
+ "}");
+ verifyFormat("- (void)test {\n"
+ " for (NSString *n in (__bridge NSArray *)arrayOfStrings) {\n"
+ " foo(n);\n"
+ " }\n"
+ "}");
+}
+
TEST_F(FormatTest, ObjCLiterals) {
verifyFormat("@\"String\"");
verifyFormat("@1");
@@ -7417,6 +7659,13 @@ TEST_F(FormatTest, ObjCDictLiterals) {
" bbbbbbbbbbbbbbbbbb : bbbbb,\n"
" cccccccccccccccc : ccccccccccccccc\n"
" }];");
+
+ // Ensure that casts before the key are kept on the same line as the key.
+ verifyFormat(
+ "NSDictionary *d = @{\n"
+ " (aaaaaaaa id)aaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " (aaaaaaaa id)aaaaaaaaaaaaaa : (aaaaaaaa id)aaaaaaaaaaaaaa,\n"
+ "};");
}
TEST_F(FormatTest, ObjCArrayLiterals) {
@@ -7625,6 +7874,13 @@ TEST_F(FormatTest, BreaksStringLiterals) {
format("#define A \"some text other\";", AlignLeft));
}
+TEST_F(FormatTest, FullyRemoveEmptyLines) {
+ FormatStyle NoEmptyLines = getLLVMStyleWithColumns(80);
+ NoEmptyLines.MaxEmptyLinesToKeep = 0;
+ EXPECT_EQ("int i = a(b());",
+ format("int i=a(\n\n b(\n\n\n )\n\n);", NoEmptyLines));
+}
+
TEST_F(FormatTest, BreaksStringLiteralsWithTabs) {
EXPECT_EQ(
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
@@ -8028,11 +8284,13 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
"};",
Tab);
verifyFormat("{\n"
- "\tQ({\n"
- "\t\tint a;\n"
- "\t\tsomeFunction(aaaaaaaa,\n"
- "\t\t bbbbbbb);\n"
- "\t}, p);\n"
+ "\tQ(\n"
+ "\t {\n"
+ "\t\t int a;\n"
+ "\t\t someFunction(aaaaaaaa,\n"
+ "\t\t bbbbbbb);\n"
+ "\t },\n"
+ "\t p);\n"
"}",
Tab);
EXPECT_EQ("{\n"
@@ -8210,6 +8468,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
verifyFormat("static_assert(sizeof(char) == 1, \"Impossible!\");", NoSpace);
verifyFormat("int f() throw(Deprecated);", NoSpace);
verifyFormat("typedef void (*cb)(int);", NoSpace);
+ verifyFormat("T A::operator()();", NoSpace);
+ verifyFormat("X A::operator++(T);", NoSpace);
FormatStyle Space = getLLVMStyle();
Space.SpaceBeforeParens = FormatStyle::SBPO_Always;
@@ -8255,6 +8515,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
verifyFormat("static_assert (sizeof (char) == 1, \"Impossible!\");", Space);
verifyFormat("int f () throw (Deprecated);", Space);
verifyFormat("typedef void (*cb) (int);", Space);
+ verifyFormat("T A::operator() ();", Space);
+ verifyFormat("X A::operator++ (T);", Space);
}
TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
@@ -8264,6 +8526,8 @@ TEST_F(FormatTest, ConfigurableSpacesInParentheses) {
verifyFormat("call( x, y, z );", Spaces);
verifyFormat("call();", Spaces);
verifyFormat("std::function<void( int, int )> callback;", Spaces);
+ verifyFormat("void inFunction() { std::function<void( int, int )> fct; }",
+ Spaces);
verifyFormat("while ( (bool)1 )\n"
" continue;",
Spaces);
@@ -8439,6 +8703,10 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
"int oneTwoThree = 123;\n"
"int oneTwo = 12;",
Alignment);
+ verifyFormat("int oneTwoThree = 123;\n"
+ "int oneTwo = 12;\n"
+ "method();\n",
+ Alignment);
verifyFormat("int oneTwoThree = 123; // comment\n"
"int oneTwo = 12; // comment",
Alignment);
@@ -8502,7 +8770,7 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
Alignment);
verifyFormat("class C {\n"
"public:\n"
- " int i = 1;\n"
+ " int i = 1;\n"
" virtual void f() = 0;\n"
"};",
Alignment);
@@ -8531,6 +8799,19 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
" someLooooooooooooooooongFunction();\n"
"int j = 2;",
Alignment);
+
+ verifyFormat("auto lambda = []() {\n"
+ " auto i = 0;\n"
+ " return 0;\n"
+ "};\n"
+ "int i = 0;\n"
+ "auto v = type{\n"
+ " i = 1, //\n"
+ " (i = 2), //\n"
+ " i = 3 //\n"
+ "};",
+ Alignment);
+
// FIXME: Should align all three assignments
verifyFormat(
"int i = 1;\n"
@@ -8538,6 +8819,260 @@ TEST_F(FormatTest, AlignConsecutiveAssignments) {
" loooooooooooooooooooooongParameterB);\n"
"int j = 2;",
Alignment);
+
+ verifyFormat("template <typename T, typename T_0 = very_long_type_name_0,\n"
+ " typename B = very_long_type_name_1,\n"
+ " typename T_2 = very_long_type_name_2>\n"
+ "auto foo() {}\n",
+ Alignment);
+ verifyFormat("int a, b = 1;\n"
+ "int c = 2;\n"
+ "int dd = 3;\n",
+ Alignment);
+ verifyFormat("int aa = ((1 > 2) ? 3 : 4);\n"
+ "float b[1][] = {{3.f}};\n",
+ Alignment);
+}
+
+TEST_F(FormatTest, AlignConsecutiveDeclarations) {
+ FormatStyle Alignment = getLLVMStyle();
+ Alignment.AlignConsecutiveDeclarations = false;
+ verifyFormat("float const a = 5;\n"
+ "int oneTwoThree = 123;",
+ Alignment);
+ verifyFormat("int a = 5;\n"
+ "float const oneTwoThree = 123;",
+ Alignment);
+
+ Alignment.AlignConsecutiveDeclarations = true;
+ verifyFormat("float const a = 5;\n"
+ "int oneTwoThree = 123;",
+ Alignment);
+ verifyFormat("int a = method();\n"
+ "float const oneTwoThree = 133;",
+ Alignment);
+ verifyFormat("int i = 1, j = 10;\n"
+ "something = 2000;",
+ Alignment);
+ verifyFormat("something = 2000;\n"
+ "int i = 1, j = 10;\n",
+ Alignment);
+ verifyFormat("float something = 2000;\n"
+ "double another = 911;\n"
+ "int i = 1, j = 10;\n"
+ "const int *oneMore = 1;\n"
+ "unsigned i = 2;",
+ Alignment);
+ verifyFormat("float a = 5;\n"
+ "int one = 1;\n"
+ "method();\n"
+ "const double oneTwoThree = 123;\n"
+ "const unsigned int oneTwo = 12;",
+ Alignment);
+ verifyFormat("int oneTwoThree{0}; // comment\n"
+ "unsigned oneTwo; // comment",
+ Alignment);
+ EXPECT_EQ("float const a = 5;\n"
+ "\n"
+ "int oneTwoThree = 123;",
+ format("float const a = 5;\n"
+ "\n"
+ "int oneTwoThree= 123;",
+ Alignment));
+ EXPECT_EQ("float a = 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "unsigned oneTwoThree = 123;",
+ format("float a = 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "unsigned oneTwoThree = 123;",
+ Alignment));
+ EXPECT_EQ("float a = 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "unsigned oneTwoThree = 123;\n"
+ "int oneTwo = 12;",
+ format("float a = 5;\n"
+ "int one = 1;\n"
+ "\n"
+ "unsigned oneTwoThree = 123;\n"
+ "int oneTwo = 12;",
+ Alignment));
+ Alignment.AlignConsecutiveAssignments = true;
+ verifyFormat("float something = 2000;\n"
+ "double another = 911;\n"
+ "int i = 1, j = 10;\n"
+ "const int *oneMore = 1;\n"
+ "unsigned i = 2;",
+ Alignment);
+ verifyFormat("int oneTwoThree = {0}; // comment\n"
+ "unsigned oneTwo = 0; // comment",
+ Alignment);
+ EXPECT_EQ("void SomeFunction(int parameter = 0) {\n"
+ " int const i = 1;\n"
+ " int * j = 2;\n"
+ " int big = 10000;\n"
+ "\n"
+ " unsigned oneTwoThree = 123;\n"
+ " int oneTwo = 12;\n"
+ " method();\n"
+ " float k = 2;\n"
+ " int ll = 10000;\n"
+ "}",
+ format("void SomeFunction(int parameter= 0) {\n"
+ " int const i= 1;\n"
+ " int *j=2;\n"
+ " int big = 10000;\n"
+ "\n"
+ "unsigned oneTwoThree =123;\n"
+ "int oneTwo = 12;\n"
+ " method();\n"
+ "float k= 2;\n"
+ "int ll=10000;\n"
+ "}",
+ Alignment));
+ Alignment.AlignConsecutiveAssignments = false;
+ Alignment.AlignEscapedNewlinesLeft = true;
+ verifyFormat("#define A \\\n"
+ " int aaaa = 12; \\\n"
+ " float b = 23; \\\n"
+ " const int ccc = 234; \\\n"
+ " unsigned dddddddddd = 2345;",
+ Alignment);
+ Alignment.AlignEscapedNewlinesLeft = false;
+ Alignment.ColumnLimit = 30;
+ verifyFormat("#define A \\\n"
+ " int aaaa = 12; \\\n"
+ " float b = 23; \\\n"
+ " const int ccc = 234; \\\n"
+ " int dddddddddd = 2345;",
+ Alignment);
+ Alignment.ColumnLimit = 80;
+ verifyFormat("void SomeFunction(int parameter = 1, int i = 2, int j = 3, int "
+ "k = 4, int l = 5,\n"
+ " int m = 6) {\n"
+ " const int j = 10;\n"
+ " otherThing = 1;\n"
+ "}",
+ Alignment);
+ verifyFormat("void SomeFunction(int parameter = 0) {\n"
+ " int const i = 1;\n"
+ " int * j = 2;\n"
+ " int big = 10000;\n"
+ "}",
+ Alignment);
+ verifyFormat("class C {\n"
+ "public:\n"
+ " int i = 1;\n"
+ " virtual void f() = 0;\n"
+ "};",
+ Alignment);
+ verifyFormat("float i = 1;\n"
+ "if (SomeType t = getSomething()) {\n"
+ "}\n"
+ "const unsigned j = 2;\n"
+ "int big = 10000;",
+ Alignment);
+ verifyFormat("float j = 7;\n"
+ "for (int k = 0; k < N; ++k) {\n"
+ "}\n"
+ "unsigned j = 2;\n"
+ "int big = 10000;\n"
+ "}",
+ Alignment);
+ Alignment.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
+ verifyFormat("float i = 1;\n"
+ "LooooooooooongType loooooooooooooooooooooongVariable\n"
+ " = someLooooooooooooooooongFunction();\n"
+ "int j = 2;",
+ Alignment);
+ Alignment.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
+ verifyFormat("int i = 1;\n"
+ "LooooooooooongType loooooooooooooooooooooongVariable =\n"
+ " someLooooooooooooooooongFunction();\n"
+ "int j = 2;",
+ Alignment);
+
+ Alignment.AlignConsecutiveAssignments = true;
+ verifyFormat("auto lambda = []() {\n"
+ " auto ii = 0;\n"
+ " float j = 0;\n"
+ " return 0;\n"
+ "};\n"
+ "int i = 0;\n"
+ "float i2 = 0;\n"
+ "auto v = type{\n"
+ " i = 1, //\n"
+ " (i = 2), //\n"
+ " i = 3 //\n"
+ "};",
+ Alignment);
+ Alignment.AlignConsecutiveAssignments = false;
+
+ // FIXME: Should align all three declarations
+ verifyFormat(
+ "int i = 1;\n"
+ "SomeType a = SomeFunction(looooooooooooooooooooooongParameterA,\n"
+ " loooooooooooooooooooooongParameterB);\n"
+ "int j = 2;",
+ Alignment);
+
+ // Test interactions with ColumnLimit and AlignConsecutiveAssignments:
+ // We expect declarations and assignments to align, as long as it doesn't
+ // exceed the column limit, starting a new alignemnt sequence whenever it
+ // happens.
+ Alignment.AlignConsecutiveAssignments = true;
+ Alignment.ColumnLimit = 30;
+ verifyFormat("float ii = 1;\n"
+ "unsigned j = 2;\n"
+ "int someVerylongVariable = 1;\n"
+ "AnotherLongType ll = 123456;\n"
+ "VeryVeryLongType k = 2;\n"
+ "int myvar = 1;",
+ Alignment);
+ Alignment.ColumnLimit = 80;
+ Alignment.AlignConsecutiveAssignments = false;
+
+ verifyFormat(
+ "template <typename LongTemplate, typename VeryLongTemplateTypeName,\n"
+ " typename LongType, typename B>\n"
+ "auto foo() {}\n",
+ Alignment);
+ verifyFormat("float a, b = 1;\n"
+ "int c = 2;\n"
+ "int dd = 3;\n",
+ Alignment);
+ verifyFormat("int aa = ((1 > 2) ? 3 : 4);\n"
+ "float b[1][] = {{3.f}};\n",
+ Alignment);
+ Alignment.AlignConsecutiveAssignments = true;
+ verifyFormat("float a, b = 1;\n"
+ "int c = 2;\n"
+ "int dd = 3;\n",
+ Alignment);
+ verifyFormat("int aa = ((1 > 2) ? 3 : 4);\n"
+ "float b[1][] = {{3.f}};\n",
+ Alignment);
+ Alignment.AlignConsecutiveAssignments = false;
+
+ Alignment.ColumnLimit = 30;
+ Alignment.BinPackParameters = false;
+ verifyFormat("void foo(float a,\n"
+ " float b,\n"
+ " int c,\n"
+ " uint32_t *d) {\n"
+ " int * e = 0;\n"
+ " float f = 0;\n"
+ " double g = 0;\n"
+ "}\n"
+ "void bar(ino_t a,\n"
+ " int b,\n"
+ " uint32_t *c,\n"
+ " bool d) {}\n",
+ Alignment);
+ Alignment.BinPackParameters = true;
+ Alignment.ColumnLimit = 80;
}
TEST_F(FormatTest, LinuxBraceBreaking) {
@@ -8552,6 +9087,8 @@ TEST_F(FormatTest, LinuxBraceBreaking) {
" if (true) {\n"
" a();\n"
" b();\n"
+ " } else {\n"
+ " a();\n"
" }\n"
" }\n"
" void g() { return; }\n"
@@ -8994,6 +9531,45 @@ TEST_F(FormatTest, GNUBraceBreaking) {
"#endif",
GNUBraceStyle);
}
+
+TEST_F(FormatTest, WebKitBraceBreaking) {
+ FormatStyle WebKitBraceStyle = getLLVMStyle();
+ WebKitBraceStyle.BreakBeforeBraces = FormatStyle::BS_WebKit;
+ verifyFormat("namespace a {\n"
+ "class A {\n"
+ " void f()\n"
+ " {\n"
+ " if (true) {\n"
+ " a();\n"
+ " b();\n"
+ " }\n"
+ " }\n"
+ " void g() { return; }\n"
+ "};\n"
+ "enum E {\n"
+ " A,\n"
+ " // foo\n"
+ " B,\n"
+ " C\n"
+ "};\n"
+ "struct B {\n"
+ " int x;\n"
+ "};\n"
+ "}\n",
+ WebKitBraceStyle);
+ verifyFormat("struct S {\n"
+ " int Type;\n"
+ " union {\n"
+ " int x;\n"
+ " double y;\n"
+ " } Value;\n"
+ " class C {\n"
+ " MyFavoriteType Value;\n"
+ " } Class;\n"
+ "};\n",
+ WebKitBraceStyle);
+}
+
TEST_F(FormatTest, CatchExceptionReferenceBinding) {
verifyFormat("void f() {\n"
" try {\n"
@@ -9119,6 +9695,20 @@ TEST_F(FormatTest, GetsCorrectBasedOnStyle) {
#define CHECK_PARSE_BOOL(FIELD) CHECK_PARSE_BOOL_FIELD(FIELD, #FIELD)
+#define CHECK_PARSE_NESTED_BOOL_FIELD(STRUCT, FIELD, CONFIG_NAME) \
+ Style.STRUCT.FIELD = false; \
+ EXPECT_EQ(0, \
+ parseConfiguration(#STRUCT ":\n " CONFIG_NAME ": true", &Style) \
+ .value()); \
+ EXPECT_TRUE(Style.STRUCT.FIELD); \
+ EXPECT_EQ(0, \
+ parseConfiguration(#STRUCT ":\n " CONFIG_NAME ": false", &Style) \
+ .value()); \
+ EXPECT_FALSE(Style.STRUCT.FIELD);
+
+#define CHECK_PARSE_NESTED_BOOL(STRUCT, FIELD) \
+ CHECK_PARSE_NESTED_BOOL_FIELD(STRUCT, FIELD, #FIELD)
+
#define CHECK_PARSE(TEXT, FIELD, VALUE) \
EXPECT_NE(VALUE, Style.FIELD); \
EXPECT_EQ(0, parseConfiguration(TEXT, &Style).value()); \
@@ -9127,30 +9717,33 @@ TEST_F(FormatTest, GetsCorrectBasedOnStyle) {
TEST_F(FormatTest, ParsesConfigurationBools) {
FormatStyle Style = {};
Style.Language = FormatStyle::LK_Cpp;
- CHECK_PARSE_BOOL(AlignAfterOpenBracket);
CHECK_PARSE_BOOL(AlignEscapedNewlinesLeft);
CHECK_PARSE_BOOL(AlignOperands);
CHECK_PARSE_BOOL(AlignTrailingComments);
CHECK_PARSE_BOOL(AlignConsecutiveAssignments);
+ CHECK_PARSE_BOOL(AlignConsecutiveDeclarations);
CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine);
CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine);
CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);
CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine);
CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine);
CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations);
- CHECK_PARSE_BOOL(BinPackParameters);
CHECK_PARSE_BOOL(BinPackArguments);
+ CHECK_PARSE_BOOL(BinPackParameters);
CHECK_PARSE_BOOL(BreakBeforeTernaryOperators);
CHECK_PARSE_BOOL(BreakConstructorInitializersBeforeComma);
CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
CHECK_PARSE_BOOL(DerivePointerAlignment);
CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding");
+ CHECK_PARSE_BOOL(DisableFormat);
CHECK_PARSE_BOOL(IndentCaseLabels);
CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks);
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
+ CHECK_PARSE_BOOL(ReflowComments);
+ CHECK_PARSE_BOOL(SortIncludes);
CHECK_PARSE_BOOL(SpacesInParentheses);
CHECK_PARSE_BOOL(SpacesInSquareBrackets);
CHECK_PARSE_BOOL(SpacesInAngles);
@@ -9159,6 +9752,18 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses);
CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
+
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterFunction);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterNamespace);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterObjCDeclaration);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterStruct);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterUnion);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);
}
#undef CHECK_PARSE_BOOL
@@ -9217,6 +9822,19 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("BreakBeforeBinaryOperators: true", BreakBeforeBinaryOperators,
FormatStyle::BOS_All);
+ Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
+ CHECK_PARSE("AlignAfterOpenBracket: Align", AlignAfterOpenBracket,
+ FormatStyle::BAS_Align);
+ CHECK_PARSE("AlignAfterOpenBracket: DontAlign", AlignAfterOpenBracket,
+ FormatStyle::BAS_DontAlign);
+ CHECK_PARSE("AlignAfterOpenBracket: AlwaysBreak", AlignAfterOpenBracket,
+ FormatStyle::BAS_AlwaysBreak);
+ // For backward compatibility:
+ CHECK_PARSE("AlignAfterOpenBracket: false", AlignAfterOpenBracket,
+ FormatStyle::BAS_DontAlign);
+ CHECK_PARSE("AlignAfterOpenBracket: true", AlignAfterOpenBracket,
+ FormatStyle::BAS_Align);
+
Style.UseTab = FormatStyle::UT_ForIndentation;
CHECK_PARSE("UseTab: Never", UseTab, FormatStyle::UT_Never);
CHECK_PARSE("UseTab: ForIndentation", UseTab, FormatStyle::UT_ForIndentation);
@@ -9270,6 +9888,23 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("BreakBeforeBraces: Allman", BreakBeforeBraces,
FormatStyle::BS_Allman);
CHECK_PARSE("BreakBeforeBraces: GNU", BreakBeforeBraces, FormatStyle::BS_GNU);
+ CHECK_PARSE("BreakBeforeBraces: WebKit", BreakBeforeBraces,
+ FormatStyle::BS_WebKit);
+ CHECK_PARSE("BreakBeforeBraces: Custom", BreakBeforeBraces,
+ FormatStyle::BS_Custom);
+
+ Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All;
+ CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType,
+ FormatStyle::RTBS_None);
+ CHECK_PARSE("AlwaysBreakAfterReturnType: All", AlwaysBreakAfterReturnType,
+ FormatStyle::RTBS_All);
+ CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevel",
+ AlwaysBreakAfterReturnType, FormatStyle::RTBS_TopLevel);
+ CHECK_PARSE("AlwaysBreakAfterReturnType: AllDefinitions",
+ AlwaysBreakAfterReturnType, FormatStyle::RTBS_AllDefinitions);
+ CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevelDefinitions",
+ AlwaysBreakAfterReturnType,
+ FormatStyle::RTBS_TopLevelDefinitions);
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None",
@@ -9288,6 +9923,8 @@ TEST_F(FormatTest, ParsesConfiguration) {
CHECK_PARSE("NamespaceIndentation: All", NamespaceIndentation,
FormatStyle::NI_All);
+ // FIXME: This is required because parsing a configuration simply overwrites
+ // the first N elements of the list instead of resetting it.
Style.ForEachMacros.clear();
std::vector<std::string> BoostForeach;
BoostForeach.push_back("BOOST_FOREACH");
@@ -9297,6 +9934,16 @@ TEST_F(FormatTest, ParsesConfiguration) {
BoostAndQForeach.push_back("Q_FOREACH");
CHECK_PARSE("ForEachMacros: [BOOST_FOREACH, Q_FOREACH]", ForEachMacros,
BoostAndQForeach);
+
+ Style.IncludeCategories.clear();
+ std::vector<FormatStyle::IncludeCategory> ExpectedCategories = {{"abc/.*", 2},
+ {".*", 1}};
+ CHECK_PARSE("IncludeCategories:\n"
+ " - Regex: abc/.*\n"
+ " Priority: 2\n"
+ " - Regex: .*\n"
+ " Priority: 1",
+ IncludeCategories, ExpectedCategories);
}
TEST_F(FormatTest, ParsesConfigurationWithLanguages) {
@@ -9497,6 +10144,11 @@ TEST_F(FormatTest, SplitsUTF8Strings) {
"\"八九十\tqq\"",
format("\"一\t二 \t三 四 五\t六 \t七 八九十\tqq\"",
getLLVMStyleWithColumns(11)));
+
+ // UTF8 character in an escape sequence.
+ EXPECT_EQ("\"aaaaaa\"\n"
+ "\"\\\xC2\x8D\"",
+ format("\"aaaaaa\\\xC2\x8D\"", getLLVMStyleWithColumns(10)));
}
TEST_F(FormatTest, HandlesDoubleWidthCharsInMultiLineStrings) {
@@ -9875,6 +10527,9 @@ TEST_F(FormatTest, FormatsLambdas) {
verifyFormat("SomeFunction({[&] {\n"
" // comment\n"
"}});");
+ verifyFormat("virtual aaaaaaaaaaaaaaaa(std::function<bool()> bbbbbbbbbbbb =\n"
+ " [&]() { return true; },\n"
+ " aaaaa aaaaaaaaa);");
// Lambdas with return types.
verifyFormat("int c = []() -> int { return 2; }();\n");
@@ -9885,6 +10540,7 @@ TEST_F(FormatTest, FormatsLambdas) {
verifyGoogleFormat("auto a = [&b, c](D* d) -> pair<D*, D*> {};");
verifyGoogleFormat("auto a = [&b, c](D* d) -> D& {};");
verifyGoogleFormat("auto a = [&b, c](D* d) -> const D* {};");
+ verifyFormat("[a, a]() -> a<1> {};");
verifyFormat("auto aaaaaaaa = [](int i, // break for some reason\n"
" int j) -> int {\n"
" return ffffffffffffffffffffffffffffffffffffffffffff(i * j);\n"
@@ -10191,6 +10847,9 @@ TEST_F(FormatTest, SpacesInAngles) {
verifyFormat("f< int, float >();", Spaces);
verifyFormat("template <> g() {}", Spaces);
verifyFormat("template < std::vector< int > > f() {}", Spaces);
+ verifyFormat("std::function< void(int, int) > fct;", Spaces);
+ verifyFormat("void inFunction() { std::function< void(int, int) > fct; }",
+ Spaces);
Spaces.Standard = FormatStyle::LS_Cpp03;
Spaces.SpacesInAngles = true;
@@ -10362,6 +11021,12 @@ TEST_F(FormatTest, DoNotCrashOnInvalidInput) {
verifyNoCrash("#define a\\\n /**/}");
}
+TEST_F(FormatTest, FormatsTableGenCode) {
+ FormatStyle Style = getLLVMStyle();
+ Style.Language = FormatStyle::LK_TableGen;
+ verifyFormat("include \"a.td\"\ninclude \"b.td\"", Style);
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp
index d068d35d7d393..cba2ce3370c9e 100644
--- a/unittests/Format/FormatTestJS.cpp
+++ b/unittests/Format/FormatTestJS.cpp
@@ -49,7 +49,8 @@ protected:
static void verifyFormat(
llvm::StringRef Code,
const FormatStyle &Style = getGoogleStyle(FormatStyle::LK_JavaScript)) {
- EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
+ std::string result = format(test::messUp(Code), Style);
+ EXPECT_EQ(Code.str(), result) << "Formatted:\n" << result;
}
};
@@ -79,8 +80,8 @@ TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) {
" q();",
getGoogleJSStyleWithColumns(20));
verifyFormat("var x = aaaaaaaaaa ?\n"
- " bbbbbb :\n"
- " ccc;",
+ " bbbbbb :\n"
+ " ccc;",
getGoogleJSStyleWithColumns(20));
verifyFormat("var b = a.map((x) => x + 1);");
@@ -99,9 +100,31 @@ TEST_F(FormatTestJS, LiteralOperatorsCanBeKeywords) {
verifyFormat("not.and.or.not_eq = 1;");
}
+TEST_F(FormatTestJS, ReservedWords) {
+ // JavaScript reserved words (aka keywords) are only illegal when used as
+ // Identifiers, but are legal as IdentifierNames.
+ verifyFormat("x.class.struct = 1;");
+ verifyFormat("x.case = 1;");
+ verifyFormat("x.interface = 1;");
+ verifyFormat("x = {\n"
+ " a: 12,\n"
+ " interface: 1,\n"
+ " switch: 1,\n"
+ "};");
+ verifyFormat("var struct = 2;");
+ verifyFormat("var union = 2;");
+}
+
+TEST_F(FormatTestJS, CppKeywords) {
+ // Make sure we don't mess stuff up because of C++ keywords.
+ verifyFormat("return operator && (aa);");
+}
+
TEST_F(FormatTestJS, ES6DestructuringAssignment) {
verifyFormat("var [a, b, c] = [1, 2, 3];");
+ verifyFormat("let [a, b, c] = [1, 2, 3];");
verifyFormat("var {a, b} = {a: 1, b: 2};");
+ verifyFormat("let {a, b} = {a: 1, b: 2};");
}
TEST_F(FormatTestJS, ContainerLiterals) {
@@ -236,6 +259,8 @@ TEST_F(FormatTestJS, GoogModules) {
getGoogleJSStyleWithColumns(40));
verifyFormat("var long = goog.require('this.is.really.absurdly.long');",
getGoogleJSStyleWithColumns(40));
+ verifyFormat("goog.setTestOnly('this.is.really.absurdly.long');",
+ getGoogleJSStyleWithColumns(40));
// These should be wrapped normally.
verifyFormat(
@@ -263,31 +288,43 @@ TEST_F(FormatTestJS, ArrayLiterals) {
" bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
" ccccccccccccccccccccccccccc\n"
"];");
- verifyFormat("var someVariable = SomeFuntion([\n"
+ verifyFormat("var someVariable = SomeFunction([\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
" ccccccccccccccccccccccccccc\n"
"]);");
- verifyFormat("var someVariable = SomeFuntion([\n"
+ verifyFormat("var someVariable = SomeFunction([\n"
" [aaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbb],\n"
"]);",
getGoogleJSStyleWithColumns(51));
- verifyFormat("var someVariable = SomeFuntion(aaaa, [\n"
+ verifyFormat("var someVariable = SomeFunction(aaaa, [\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
" ccccccccccccccccccccccccccc\n"
"]);");
- verifyFormat("var someVariable = SomeFuntion(aaaa,\n"
- " [\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
- " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
- " ccccccccccccccccccccccccccc\n"
- " ],\n"
- " aaaa);");
+ verifyFormat("var someVariable = SomeFunction(\n"
+ " aaaa,\n"
+ " [\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbb,\n"
+ " ccccccccccccccccccccccccccc\n"
+ " ],\n"
+ " aaaa);");
verifyFormat("someFunction([], {a: a});");
}
+TEST_F(FormatTestJS, ColumnLayoutForArrayLiterals) {
+ verifyFormat("var array = [\n"
+ " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
+ " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
+ "];");
+ verifyFormat("var array = someFunction([\n"
+ " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
+ " a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,\n"
+ "]);");
+}
+
TEST_F(FormatTestJS, FunctionLiterals) {
verifyFormat("doFoo(function() {});");
verifyFormat("doFoo(function() { return 1; });");
@@ -305,14 +342,11 @@ TEST_F(FormatTestJS, FunctionLiterals) {
" style: {direction: ''}\n"
" }\n"
"};");
- EXPECT_EQ("abc = xyz ?\n"
- " function() {\n"
- " return 1;\n"
- " } :\n"
- " function() {\n"
- " return -1;\n"
- " };",
- format("abc=xyz?function(){return 1;}:function(){return -1;};"));
+ verifyFormat("abc = xyz ? function() {\n"
+ " return 1;\n"
+ "} : function() {\n"
+ " return -1;\n"
+ "};");
verifyFormat("var closure = goog.bind(\n"
" function() { // comment\n"
@@ -364,17 +398,13 @@ TEST_F(FormatTestJS, FunctionLiterals) {
" someFunction();\n"
" }, this), aaaaaaaaaaaaaaaaa);");
- // FIXME: This is not ideal yet.
- verifyFormat("someFunction(goog.bind(\n"
- " function() {\n"
- " doSomething();\n"
- " doSomething();\n"
- " },\n"
- " this),\n"
- " goog.bind(function() {\n"
- " doSomething();\n"
- " doSomething();\n"
- " }, this));");
+ verifyFormat("someFunction(goog.bind(function() {\n"
+ " doSomething();\n"
+ " doSomething();\n"
+ "}, this), goog.bind(function() {\n"
+ " doSomething();\n"
+ " doSomething();\n"
+ "}, this));");
// FIXME: This is bad, we should be wrapping before "function() {".
verifyFormat("someFunction(function() {\n"
@@ -434,6 +464,12 @@ TEST_F(FormatTestJS, InliningFunctionLiterals) {
" }\n"
"}",
Style);
+
+ Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
+ verifyFormat("var func = function() {\n"
+ " return 1;\n"
+ "};",
+ Style);
}
TEST_F(FormatTestJS, MultipleFunctionLiterals) {
@@ -457,16 +493,16 @@ TEST_F(FormatTestJS, MultipleFunctionLiterals) {
" doFoo();\n"
" doBaz();\n"
" });\n");
- // FIXME: Here, we should probably break right after the "(" for consistency.
- verifyFormat("promise.then([],\n"
- " function success() {\n"
- " doFoo();\n"
- " doBar();\n"
- " },\n"
- " function error() {\n"
- " doFoo();\n"
- " doBaz();\n"
- " });\n");
+ verifyFormat("promise.then(\n"
+ " [],\n"
+ " function success() {\n"
+ " doFoo();\n"
+ " doBar();\n"
+ " },\n"
+ " function error() {\n"
+ " doFoo();\n"
+ " doBaz();\n"
+ " });\n");
verifyFormat("getSomeLongPromise()\n"
" .then(function(value) { body(); })\n"
@@ -508,13 +544,13 @@ TEST_F(FormatTestJS, ArrowFunctions) {
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
"};");
- verifyFormat(
- "var a = a.aaaaaaa((a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
- " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
- verifyFormat(
- "var a = a.aaaaaaa((a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
- " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
- " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
+ verifyFormat("var a = a.aaaaaaa(\n"
+ " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
+ verifyFormat("var a = a.aaaaaaa(\n"
+ " (a: a) => aaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) ?\n"
+ " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb) :\n"
+ " aaaaaaaaaaaaaaaaaaaaa(bbbbbbb));");
// FIXME: This is bad, we should be wrapping before "() => {".
verifyFormat("someFunction(() => {\n"
@@ -531,6 +567,11 @@ TEST_F(FormatTestJS, ReturnStatements) {
"}");
}
+TEST_F(FormatTestJS, ForLoops) {
+ verifyFormat("for (var i in [2, 3]) {\n"
+ "}");
+}
+
TEST_F(FormatTestJS, AutomaticSemicolonInsertion) {
// The following statements must not wrap, as otherwise the program meaning
// would change due to automatic semicolon insertion.
@@ -564,7 +605,7 @@ TEST_F(FormatTestJS, TryCatch) {
TEST_F(FormatTestJS, StringLiteralConcatenation) {
verifyFormat("var literal = 'hello ' +\n"
- " 'world';");
+ " 'world';");
}
TEST_F(FormatTestJS, RegexLiteralClassification) {
@@ -585,6 +626,13 @@ TEST_F(FormatTestJS, RegexLiteralClassification) {
// Not regex literals.
verifyFormat("var a = a / 2 + b / 3;");
+ verifyFormat("var a = a++ / 2;");
+ // Prefix unary can operate on regex literals, not that it makes sense.
+ verifyFormat("var a = ++/a/;");
+
+ // This is a known issue, regular expressions are incorrectly detected if
+ // directly following a closing parenthesis.
+ verifyFormat("if (foo) / bar /.exec(baz);");
}
TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
@@ -602,9 +650,18 @@ TEST_F(FormatTestJS, RegexLiteralSpecialCharacters) {
verifyFormat("var regex = /x|y/;");
verifyFormat("var regex = /a{2}/;");
verifyFormat("var regex = /a{1,3}/;");
+
verifyFormat("var regex = /[abc]/;");
verifyFormat("var regex = /[^abc]/;");
verifyFormat("var regex = /[\\b]/;");
+ verifyFormat("var regex = /[/]/;");
+ verifyFormat("var regex = /[\\/]/;");
+ verifyFormat("var regex = /\\[/;");
+ verifyFormat("var regex = /\\\\[/]/;");
+ verifyFormat("var regex = /}[\"]/;");
+ verifyFormat("var regex = /}[/\"]/;");
+ verifyFormat("var regex = /}[\"/]/;");
+
verifyFormat("var regex = /\\b/;");
verifyFormat("var regex = /\\B/;");
verifyFormat("var regex = /\\d/;");
@@ -705,12 +762,18 @@ TEST_F(FormatTestJS, ClassDeclarations) {
TEST_F(FormatTestJS, InterfaceDeclarations) {
verifyFormat("interface I {\n"
" x: string;\n"
+ " enum: string[];\n"
"}\n"
"var y;");
// Ensure that state is reset after parsing the interface.
verifyFormat("interface a {}\n"
"export function b() {}\n"
"var x;");
+
+ // Arrays of object type literals.
+ verifyFormat("interface I {\n"
+ " o: {}[];\n"
+ "}");
}
TEST_F(FormatTestJS, EnumDeclarations) {
@@ -818,7 +881,7 @@ TEST_F(FormatTestJS, TemplateStrings) {
getGoogleJSStyleWithColumns(35)); // Barely fits.
EXPECT_EQ("var x = `hello\n"
" ${world}` >=\n"
- " some();",
+ " some();",
format("var x =\n"
" `hello\n"
" ${world}` >= some();",
@@ -843,7 +906,7 @@ TEST_F(FormatTestJS, TemplateStrings) {
// are first token in line.
verifyFormat(
"var a = aaaaaaaaaaaaaaaaaaaaaaaaaaaa ||\n"
- " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
+ " `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;");
// Two template strings.
verifyFormat("var x = `hello` == `hello`;");
@@ -893,11 +956,20 @@ TEST_F(FormatTestJS, TypeArguments) {
verifyFormat("function f(): List<any> {}");
verifyFormat("function aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa():\n"
" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb {}");
- verifyFormat("function aaaaaaaaaa(aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaa,\n"
- " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaa):\n"
+ verifyFormat("function aaaaaaaaaa(\n"
+ " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa,\n"
+ " aaaaaaaaaaaaaaaa: aaaaaaaaaaaaaaaaaaa):\n"
" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {}");
}
+TEST_F(FormatTestJS, UserDefinedTypeGuards) {
+ verifyFormat(
+ "function foo(check: Object):\n"
+ " check is {foo: string, bar: string, baz: string, foobar: string} {\n"
+ " return 'bar' in check;\n"
+ "}\n");
+}
+
TEST_F(FormatTestJS, OptionalTypes) {
verifyFormat("function x(a?: b, c?, d?) {}");
verifyFormat("class X {\n"
@@ -920,5 +992,23 @@ TEST_F(FormatTestJS, IndexSignature) {
verifyFormat("var x: {[k: string]: v};");
}
+TEST_F(FormatTestJS, WrapAfterParen) {
+ verifyFormat("xxxxxxxxxxx(\n"
+ " aaa, aaa);",
+ getGoogleJSStyleWithColumns(20));
+ verifyFormat("xxxxxxxxxxx(\n"
+ " aaa, aaa, aaa,\n"
+ " aaa, aaa, aaa);",
+ getGoogleJSStyleWithColumns(20));
+ verifyFormat("xxxxxxxxxxx(\n"
+ " aaaaaaaaaaaaaaaaaaaaaaaa,\n"
+ " function(x) {\n"
+ " y(); //\n"
+ " });",
+ getGoogleJSStyleWithColumns(40));
+ verifyFormat("while (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) {\n}");
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/FormatTestJava.cpp b/unittests/Format/FormatTestJava.cpp
index 8e590879f6e24..8fadfc09b3ed7 100644
--- a/unittests/Format/FormatTestJava.cpp
+++ b/unittests/Format/FormatTestJava.cpp
@@ -276,6 +276,10 @@ TEST_F(FormatTestJava, Annotations) {
verifyFormat("void SomeFunction(@org.llvm.Nullable String something) {}");
verifyFormat("@Partial @Mock DataLoader loader;");
+ verifyFormat("@Partial\n"
+ "@Mock\n"
+ "DataLoader loader;",
+ getChromiumStyle(FormatStyle::LK_Java));
verifyFormat("@SuppressWarnings(value = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\")\n"
"public static int iiiiiiiiiiiiiiiiiiiiiiii;");
@@ -393,6 +397,10 @@ TEST_F(FormatTestJava, SynchronizedKeyword) {
"}");
}
+TEST_F(FormatTestJava, AssertKeyword) {
+ verifyFormat("assert a && b;");
+}
+
TEST_F(FormatTestJava, PackageDeclarations) {
verifyFormat("package some.really.loooooooooooooooooooooong.package;",
getStyleWithColumns(50));
@@ -418,6 +426,7 @@ TEST_F(FormatTestJava, CppKeywords) {
verifyFormat("public void union(Type a, Type b);");
verifyFormat("public void struct(Object o);");
verifyFormat("public void delete(Object o);");
+ verifyFormat("return operator && (aa);");
}
TEST_F(FormatTestJava, NeverAlignAfterReturn) {
diff --git a/unittests/Format/FormatTestProto.cpp b/unittests/Format/FormatTestProto.cpp
index 74f7005b219fb..cd2c0c8aa461d 100644
--- a/unittests/Format/FormatTestProto.cpp
+++ b/unittests/Format/FormatTestProto.cpp
@@ -73,6 +73,12 @@ TEST_F(FormatTestProto, FormatsEnums) {
" TYPE_A = 1;\n"
" TYPE_B = 2;\n"
"};");
+ verifyFormat("enum Type {\n"
+ " UNKNOWN = 0 [(some_options) = {\n"
+ " a: aa,\n"
+ " b: bb\n"
+ " }];\n"
+ "};");
}
TEST_F(FormatTestProto, UnderstandsReturns) {
@@ -156,5 +162,10 @@ TEST_F(FormatTestProto, FormatsService) {
"};");
}
+TEST_F(FormatTestProto, ExtendingMessage) {
+ verifyFormat("extend .foo.Bar {\n"
+ "}");
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Format/FormatTestSelective.cpp b/unittests/Format/FormatTestSelective.cpp
index 8d2cb5a2fcbd9..d53d1c0429211 100644
--- a/unittests/Format/FormatTestSelective.cpp
+++ b/unittests/Format/FormatTestSelective.cpp
@@ -45,8 +45,14 @@ TEST_F(FormatTestSelective, RemovesTrailingWhitespaceOfFormattedLine) {
}
TEST_F(FormatTestSelective, FormatsCorrectRegionForLeadingWhitespace) {
- EXPECT_EQ("int b;\nint a;", format("int b;\n int a;", 7, 0));
- EXPECT_EQ("int b;\n int a;", format("int b;\n int a;", 6, 0));
+ EXPECT_EQ("{int b;\n"
+ " int a;\n"
+ "}",
+ format("{int b;\n int a;}", 8, 0));
+ EXPECT_EQ("{\n"
+ " int b;\n"
+ " int a;}",
+ format("{int b;\n int a;}", 7, 0));
Style.ColumnLimit = 12;
EXPECT_EQ("#define A \\\n"
@@ -84,11 +90,11 @@ TEST_F(FormatTestSelective, ReformatsMovedLines) {
"template <typename T> T *getFETokenInfo() const {\n"
" return static_cast<T *>(FETokenInfo);\n"
"}\n"
- " int a; // <- Should not be formatted",
+ "int a; // <- Should not be formatted",
format(
"template<typename T>\n"
"T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }\n"
- " int a; // <- Should not be formatted",
+ "int a; // <- Should not be formatted",
9, 5));
}
@@ -142,12 +148,12 @@ TEST_F(FormatTestSelective, FormatsCommentsLocally) {
" // is\n"
" // a\n"
"\n"
- " // This is unrelated",
+ "//This is unrelated",
format("int a; // This\n"
" // is\n"
" // a\n"
"\n"
- " // This is unrelated",
+ "//This is unrelated",
0, 0));
EXPECT_EQ("int a;\n"
"// This is\n"
@@ -267,6 +273,27 @@ TEST_F(FormatTestSelective, IndividualStatementsOfNestedBlocks) {
0, 0));
}
+TEST_F(FormatTestSelective, WrongIndent) {
+ EXPECT_EQ("namespace {\n"
+ "int i;\n"
+ "int j;\n"
+ "}",
+ format("namespace {\n"
+ " int i;\n" // Format here.
+ " int j;\n"
+ "}",
+ 15, 0));
+ EXPECT_EQ("namespace {\n"
+ " int i;\n"
+ " int j;\n"
+ "}",
+ format("namespace {\n"
+ " int i;\n"
+ " int j;\n" // Format here.
+ "}",
+ 24, 0));
+}
+
TEST_F(FormatTestSelective, AlwaysFormatsEntireMacroDefinitions) {
Style.AlignEscapedNewlinesLeft = true;
EXPECT_EQ("int i;\n"
@@ -310,13 +337,17 @@ TEST_F(FormatTestSelective, ReformatRegionAdjustsIndent) {
EXPECT_EQ("{\n"
"{\n"
" a;\n"
- "b;\n"
+ " b;\n"
+ " c;\n"
+ " d;\n"
"}\n"
"}",
format("{\n"
"{\n"
" a;\n"
- "b;\n"
+ " b;\n"
+ " c;\n"
+ " d;\n"
"}\n"
"}",
9, 2));
@@ -436,6 +467,27 @@ TEST_F(FormatTestSelective, UnderstandsTabs) {
21, 0));
}
+TEST_F(FormatTestSelective, StopFormattingWhenLeavingScope) {
+ EXPECT_EQ(
+ "void f() {\n"
+ " if (a) {\n"
+ " g();\n"
+ " h();\n"
+ "}\n"
+ "\n"
+ "void g() {\n"
+ "}",
+ format("void f() {\n"
+ " if (a) {\n" // Assume this was added without the closing brace.
+ " g();\n"
+ " h();\n"
+ "}\n"
+ "\n"
+ "void g() {\n" // Make sure not to format this.
+ "}",
+ 15, 0));
+}
+
} // end namespace
} // end namespace format
} // end namespace clang
diff --git a/unittests/Format/SortIncludesTest.cpp b/unittests/Format/SortIncludesTest.cpp
new file mode 100644
index 0000000000000..dbe11749572bb
--- /dev/null
+++ b/unittests/Format/SortIncludesTest.cpp
@@ -0,0 +1,255 @@
+//===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatTestUtils.h"
+#include "clang/Format/Format.h"
+#include "llvm/Support/Debug.h"
+#include "gtest/gtest.h"
+
+#define DEBUG_TYPE "format-test"
+
+namespace clang {
+namespace format {
+namespace {
+
+class SortIncludesTest : public ::testing::Test {
+protected:
+ std::string sort(llvm::StringRef Code, StringRef FileName = "input.cpp") {
+ std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+ std::string Sorted =
+ applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
+ return applyAllReplacements(Sorted,
+ reformat(Style, Sorted, Ranges, FileName));
+ }
+
+ unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
+ std::vector<tooling::Range> Ranges(1, tooling::Range(0, Code.size()));
+ sortIncludes(Style, Code, Ranges, "input.cpp", &Cursor);
+ return Cursor;
+ }
+
+ FormatStyle Style = getLLVMStyle();
+
+};
+
+TEST_F(SortIncludesTest, BasicSorting) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, SupportClangFormatOff) {
+ EXPECT_EQ("#include <a>\n"
+ "#include <b>\n"
+ "#include <c>\n"
+ "// clang-format off\n"
+ "#include <b>\n"
+ "#include <a>\n"
+ "#include <c>\n"
+ "// clang-format on\n",
+ sort("#include <b>\n"
+ "#include <a>\n"
+ "#include <c>\n"
+ "// clang-format off\n"
+ "#include <b>\n"
+ "#include <a>\n"
+ "#include <c>\n"
+ "// clang-format on\n"));
+}
+
+TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
+ Style.SortIncludes = false;
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, MixIncludeAndImport) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#import \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#import \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, FixTrailingComments) {
+ EXPECT_EQ("#include \"a.h\" // comment\n"
+ "#include \"bb.h\" // comment\n"
+ "#include \"ccc.h\"\n",
+ sort("#include \"a.h\" // comment\n"
+ "#include \"ccc.h\"\n"
+ "#include \"bb.h\" // comment\n"));
+}
+
+TEST_F(SortIncludesTest, LeadingWhitespace) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort(" #include \"a.h\"\n"
+ " #include \"c.h\"\n"
+ " #include \"b.h\"\n"));
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("# include \"a.h\"\n"
+ "# include \"c.h\"\n"
+ "# include \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, GreaterInComment) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\" // >\n"
+ "#include \"c.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\" // >\n"));
+}
+
+TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "\n"
+ "#include \"b.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "\n"
+ "#include \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include <b.h>\n"
+ "#include <d.h>\n",
+ sort("#include <d.h>\n"
+ "#include <b.h>\n"
+ "#include \"c.h\"\n"
+ "#include \"a.h\"\n"));
+
+ Style = getGoogleStyle(FormatStyle::LK_Cpp);
+ EXPECT_EQ("#include <b.h>\n"
+ "#include <d.h>\n"
+ "#include \"a.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include <d.h>\n"
+ "#include <b.h>\n"
+ "#include \"c.h\"\n"
+ "#include \"a.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"a.h\"\n"
+ "#include \\\n"
+ "\"c.h\"\n"
+ "#include \"b.h\"\n"));
+}
+
+TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
+ EXPECT_EQ("#include \"llvm/a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"llvm/a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ "a.cc"));
+ EXPECT_EQ("#include \"llvm/a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"llvm/a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ "a_main.cc"));
+ EXPECT_EQ("#include \"llvm/input.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n",
+ sort("#include \"llvm/input.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ "input.mm"));
+
+ // Don't do this in headers.
+ EXPECT_EQ("#include \"b.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"llvm/a.h\"\n",
+ sort("#include \"llvm/a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ "a.h"));
+
+ // Only do this in the first #include block.
+ EXPECT_EQ("#include <a>\n"
+ "\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"llvm/a.h\"\n",
+ sort("#include <a>\n"
+ "\n"
+ "#include \"llvm/a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"b.h\"\n",
+ "a.cc"));
+
+ // Only recognize the first #include with a matching basename as main include.
+ EXPECT_EQ("#include \"a.h\"\n"
+ "#include \"b.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"llvm/a.h\"\n",
+ sort("#include \"b.h\"\n"
+ "#include \"a.h\"\n"
+ "#include \"c.h\"\n"
+ "#include \"llvm/a.h\"\n",
+ "a.cc"));
+}
+
+TEST_F(SortIncludesTest, NegativePriorities) {
+ Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
+ EXPECT_EQ("#include \"important_os_header.h\"\n"
+ "#include \"c_main.h\"\n"
+ "#include \"a_other.h\"\n",
+ sort("#include \"c_main.h\"\n"
+ "#include \"a_other.h\"\n"
+ "#include \"important_os_header.h\"\n",
+ "c_main.cc"));
+
+ // check stable when re-run
+ EXPECT_EQ("#include \"important_os_header.h\"\n"
+ "#include \"c_main.h\"\n"
+ "#include \"a_other.h\"\n",
+ sort("#include \"important_os_header.h\"\n"
+ "#include \"c_main.h\"\n"
+ "#include \"a_other.h\"\n",
+ "c_main.cc"));
+}
+
+TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
+ std::string Code = "#include <ccc>\n" // Start of line: 0
+ "#include <bbbbbb>\n" // Start of line: 15
+ "#include <a>\n"; // Start of line: 33
+ EXPECT_EQ(31u, newCursor(Code, 0));
+ EXPECT_EQ(13u, newCursor(Code, 15));
+ EXPECT_EQ(0u, newCursor(Code, 33));
+
+ EXPECT_EQ(41u, newCursor(Code, 10));
+ EXPECT_EQ(23u, newCursor(Code, 25));
+ EXPECT_EQ(10u, newCursor(Code, 43));
+}
+
+} // end namespace
+} // end namespace format
+} // end namespace clang
diff --git a/unittests/Lex/LexerTest.cpp b/unittests/Lex/LexerTest.cpp
index b5a39b303d001..42f8eb5a5c7f8 100644
--- a/unittests/Lex/LexerTest.cpp
+++ b/unittests/Lex/LexerTest.cpp
@@ -42,7 +42,7 @@ class VoidModuleLoader : public ModuleLoader {
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
{ return nullptr; }
bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
+ { return 0; }
};
// The test fixture.
diff --git a/unittests/Lex/PPCallbacksTest.cpp b/unittests/Lex/PPCallbacksTest.cpp
index 94812fc93de97..cbce5c6e16769 100644
--- a/unittests/Lex/PPCallbacksTest.cpp
+++ b/unittests/Lex/PPCallbacksTest.cpp
@@ -47,7 +47,7 @@ class VoidModuleLoader : public ModuleLoader {
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
{ return nullptr; }
bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
+ { return 0; }
};
// Stub to collect data from InclusionDirective callbacks.
@@ -88,7 +88,7 @@ public:
unsigned State;
} CallbackParameters;
- PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {};
+ PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {}
void PragmaOpenCLExtension(clang::SourceLocation NameLoc,
const clang::IdentifierInfo *Name,
@@ -98,7 +98,7 @@ public:
this->Name = Name->getName();
this->StateLoc = StateLoc;
this->State = State;
- };
+ }
SourceLocation NameLoc;
SmallString<16> Name;
@@ -110,15 +110,16 @@ public:
class PPCallbacksTest : public ::testing::Test {
protected:
PPCallbacksTest()
- : FileMgr(FileMgrOpts), DiagID(new DiagnosticIDs()),
- DiagOpts(new DiagnosticOptions()),
+ : InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ FileMgr(FileSystemOptions(), InMemoryFileSystem),
+ DiagID(new DiagnosticIDs()), DiagOpts(new DiagnosticOptions()),
Diags(DiagID, DiagOpts.get(), new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) {
TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
}
- FileSystemOptions FileMgrOpts;
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
FileManager FileMgr;
IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@@ -133,7 +134,8 @@ protected:
void AddFakeHeader(HeaderSearch& HeaderInfo, const char* HeaderPath,
bool IsSystemHeader) {
// Tell FileMgr about header.
- FileMgr.getVirtualFile(HeaderPath, 0, 0);
+ InMemoryFileSystem->addFile(HeaderPath, 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
// Add header's parent path to search path.
StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);
diff --git a/unittests/Lex/PPConditionalDirectiveRecordTest.cpp b/unittests/Lex/PPConditionalDirectiveRecordTest.cpp
index d2e3640501057..9345fc2390266 100644
--- a/unittests/Lex/PPConditionalDirectiveRecordTest.cpp
+++ b/unittests/Lex/PPConditionalDirectiveRecordTest.cpp
@@ -66,7 +66,7 @@ class VoidModuleLoader : public ModuleLoader {
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
{ return nullptr; }
bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
- { return 0; };
+ { return 0; }
};
TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) {
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt
index 469e6a956b2db..33b2046ae9288 100644
--- a/unittests/Tooling/CMakeLists.txt
+++ b/unittests/Tooling/CMakeLists.txt
@@ -1,10 +1,12 @@
set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
Support
)
add_clang_unittest(ToolingTests
CommentHandlerTest.cpp
CompilationDatabaseTest.cpp
+ LookupTest.cpp
ToolingTest.cpp
RecursiveASTVisitorTest.cpp
RecursiveASTVisitorTestCallVisitor.cpp
diff --git a/unittests/Tooling/CommentHandlerTest.cpp b/unittests/Tooling/CommentHandlerTest.cpp
index da5604524cdaa..b42b28b9c9486 100644
--- a/unittests/Tooling/CommentHandlerTest.cpp
+++ b/unittests/Tooling/CommentHandlerTest.cpp
@@ -97,6 +97,10 @@ public:
: Current(Comments.begin()), End(Comments.end()), PP(PP)
{ }
+ CommentVerifier(CommentVerifier &&C) : Current(C.Current), End(C.End), PP(C.PP) {
+ C.Current = C.End;
+ }
+
~CommentVerifier() {
if (Current != End) {
EXPECT_TRUE(Current == End) << "Unexpected comment \""
diff --git a/unittests/Tooling/CompilationDatabaseTest.cpp b/unittests/Tooling/CompilationDatabaseTest.cpp
index 3e5a589caf171..380d86fc5660d 100644
--- a/unittests/Tooling/CompilationDatabaseTest.cpp
+++ b/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -36,8 +36,14 @@ TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) {
expectFailure("[{[]:\"\"}]", "Incorrectly typed entry");
expectFailure("[{}]", "Empty entry");
expectFailure("[{\"directory\":\"\",\"command\":\"\"}]", "Missing file");
- expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command");
+ expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command or arguments");
expectFailure("[{\"command\":\"\",\"file\":\"\"}]", "Missing directory");
+ expectFailure("[{\"directory\":\"\",\"arguments\":[]}]", "Missing file");
+ expectFailure("[{\"arguments\":\"\",\"file\":\"\"}]", "Missing directory");
+ expectFailure("[{\"directory\":\"\",\"arguments\":\"\",\"file\":\"\"}]", "Arguments not array");
+ expectFailure("[{\"directory\":\"\",\"command\":[],\"file\":\"\"}]", "Command not string");
+ expectFailure("[{\"directory\":\"\",\"arguments\":[[]],\"file\":\"\"}]",
+ "Arguments contain non-string");
}
static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
@@ -92,8 +98,8 @@ TEST(JSONCompilationDatabase, GetAllCompileCommands) {
StringRef FileName1("file1");
StringRef Command1("command1");
StringRef Directory2("//net/dir2");
- StringRef FileName2("file1");
- StringRef Command2("command1");
+ StringRef FileName2("file2");
+ StringRef Command2("command2");
std::vector<CompileCommand> Commands = getAllCompileCommands(
("[{\"directory\":\"" + Directory1 + "\"," +
@@ -105,11 +111,32 @@ TEST(JSONCompilationDatabase, GetAllCompileCommands) {
ErrorMessage);
EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
EXPECT_EQ(Directory1, Commands[0].Directory) << ErrorMessage;
+ EXPECT_EQ(FileName1, Commands[0].Filename) << ErrorMessage;
ASSERT_EQ(1u, Commands[0].CommandLine.size());
EXPECT_EQ(Command1, Commands[0].CommandLine[0]) << ErrorMessage;
EXPECT_EQ(Directory2, Commands[1].Directory) << ErrorMessage;
+ EXPECT_EQ(FileName2, Commands[1].Filename) << ErrorMessage;
ASSERT_EQ(1u, Commands[1].CommandLine.size());
EXPECT_EQ(Command2, Commands[1].CommandLine[0]) << ErrorMessage;
+
+ // Check that order is preserved.
+ Commands = getAllCompileCommands(
+ ("[{\"directory\":\"" + Directory2 + "\"," +
+ "\"command\":\"" + Command2 + "\","
+ "\"file\":\"" + FileName2 + "\"},"
+ " {\"directory\":\"" + Directory1 + "\"," +
+ "\"command\":\"" + Command1 + "\","
+ "\"file\":\"" + FileName1 + "\"}]").str(),
+ ErrorMessage);
+ EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
+ EXPECT_EQ(Directory2, Commands[0].Directory) << ErrorMessage;
+ EXPECT_EQ(FileName2, Commands[0].Filename) << ErrorMessage;
+ ASSERT_EQ(1u, Commands[0].CommandLine.size());
+ EXPECT_EQ(Command2, Commands[0].CommandLine[0]) << ErrorMessage;
+ EXPECT_EQ(Directory1, Commands[1].Directory) << ErrorMessage;
+ EXPECT_EQ(FileName1, Commands[1].Filename) << ErrorMessage;
+ ASSERT_EQ(1u, Commands[1].CommandLine.size());
+ EXPECT_EQ(Command1, Commands[1].CommandLine[0]) << ErrorMessage;
}
static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
@@ -126,6 +153,25 @@ static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
return Commands[0];
}
+TEST(JSONCompilationDatabase, ArgumentsPreferredOverCommand) {
+ StringRef Directory("//net/dir");
+ StringRef FileName("//net/dir/filename");
+ StringRef Command("command");
+ StringRef Arguments = "arguments";
+ Twine ArgumentsAccumulate;
+ std::string ErrorMessage;
+ CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+ FileName,
+ ("[{\"directory\":\"" + Directory + "\","
+ "\"arguments\":[\"" + Arguments + "\"],"
+ "\"command\":\"" + Command + "\","
+ "\"file\":\"" + FileName + "\"}]").str(),
+ ErrorMessage);
+ EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+ EXPECT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
+ EXPECT_EQ(Arguments, FoundCommand.CommandLine[0]) << ErrorMessage;
+}
+
struct FakeComparator : public PathComparator {
~FakeComparator() override {}
bool equivalent(StringRef FileA, StringRef FileB) const override {
@@ -402,14 +448,16 @@ TEST(FixedCompilationDatabase, ReturnsFixedCommandLine) {
CommandLine.push_back("one");
CommandLine.push_back("two");
FixedCompilationDatabase Database(".", CommandLine);
+ StringRef FileName("source");
std::vector<CompileCommand> Result =
- Database.getCompileCommands("source");
+ Database.getCompileCommands(FileName);
ASSERT_EQ(1ul, Result.size());
std::vector<std::string> ExpectedCommandLine(1, "clang-tool");
ExpectedCommandLine.insert(ExpectedCommandLine.end(),
CommandLine.begin(), CommandLine.end());
ExpectedCommandLine.push_back("source");
EXPECT_EQ(".", Result[0].Directory);
+ EXPECT_EQ(FileName, Result[0].Filename);
EXPECT_EQ(ExpectedCommandLine, Result[0].CommandLine);
}
diff --git a/unittests/Tooling/LookupTest.cpp b/unittests/Tooling/LookupTest.cpp
new file mode 100644
index 0000000000000..d847a298fff23
--- /dev/null
+++ b/unittests/Tooling/LookupTest.cpp
@@ -0,0 +1,108 @@
+//===- unittest/Tooling/LookupTest.cpp ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include "clang/Tooling/Core/Lookup.h"
+using namespace clang;
+
+namespace {
+struct GetDeclsVisitor : TestVisitor<GetDeclsVisitor> {
+ std::function<void(CallExpr *)> OnCall;
+ SmallVector<Decl *, 4> DeclStack;
+
+ bool VisitCallExpr(CallExpr *Expr) {
+ OnCall(Expr);
+ return true;
+ }
+
+ bool TraverseDecl(Decl *D) {
+ DeclStack.push_back(D);
+ bool Ret = TestVisitor::TraverseDecl(D);
+ DeclStack.pop_back();
+ return Ret;
+ }
+};
+
+TEST(LookupTest, replaceNestedName) {
+ GetDeclsVisitor Visitor;
+
+ auto replaceCallExpr = [&](const CallExpr *Expr,
+ StringRef ReplacementString) {
+ const auto *Callee = cast<DeclRefExpr>(Expr->getCallee()->IgnoreImplicit());
+ const ValueDecl *FD = Callee->getDecl();
+ return tooling::replaceNestedName(
+ Callee->getQualifier(), Visitor.DeclStack.back()->getDeclContext(), FD,
+ ReplacementString);
+ };
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace a { void f() { foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace a { void f() { foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace b { void f() { a::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\n"
+ "namespace b { namespace a { void foo(); }\n"
+ "void f() { a::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("c::bar", replaceCallExpr(Expr, "::a::c::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+ "void f() { b::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { namespace b { void foo(); }\n"
+ "void f() { b::foo(); } }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("void foo(); void f() { foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("::bar", replaceCallExpr(Expr, "::bar"));
+ };
+ Visitor.runOver("void foo(); void f() { ::foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { void foo(); }\nvoid f() { a::foo(); }\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("a::bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver("namespace a { int foo(); }\nauto f = a::foo();\n");
+
+ Visitor.OnCall = [&](CallExpr *Expr) {
+ EXPECT_EQ("bar", replaceCallExpr(Expr, "::a::bar"));
+ };
+ Visitor.runOver(
+ "namespace a { int foo(); }\nusing a::foo;\nauto f = foo();\n");
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RefactoringCallbacksTest.cpp b/unittests/Tooling/RefactoringCallbacksTest.cpp
index c2b331c70afc6..ad8aa8f98febc 100644
--- a/unittests/Tooling/RefactoringCallbacksTest.cpp
+++ b/unittests/Tooling/RefactoringCallbacksTest.cpp
@@ -71,7 +71,7 @@ TEST(RefactoringCallbacksTest, ReplacesStmtWithStmt) {
ReplaceStmtWithStmt Callback("always-false", "should-be");
expectRewritten(Code, Expected,
id("always-false", conditionalOperator(
- hasCondition(boolLiteral(equals(false))),
+ hasCondition(cxxBoolLiteral(equals(false))),
hasFalseExpression(id("should-be", expr())))),
Callback);
}
@@ -92,7 +92,7 @@ TEST(RefactoringCallbacksTest, RemovesEntireIfOnEmptyElse) {
std::string Expected = "void f() { }";
ReplaceIfStmtWithItsBody Callback("id", false);
expectRewritten(Code, Expected,
- id("id", ifStmt(hasCondition(boolLiteral(equals(false))))),
+ id("id", ifStmt(hasCondition(cxxBoolLiteral(equals(false))))),
Callback);
}
diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp
index 6c2c16b484d7e..ff11aeae117ab 100644
--- a/unittests/Tooling/RefactoringTest.cpp
+++ b/unittests/Tooling/RefactoringTest.cpp
@@ -176,8 +176,8 @@ TEST(ShiftedCodePositionTest, FindsNewCodePosition) {
EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 5)); // int | i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); // int |i;
+ EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
+ EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
}
@@ -195,8 +195,8 @@ TEST(ShiftedCodePositionTest, VectorFindsNewCodePositionWithInserts) {
EXPECT_EQ(1u, shiftedCodePosition(Replaces, 2)); // i|t i;
EXPECT_EQ(2u, shiftedCodePosition(Replaces, 3)); // in| i;
EXPECT_EQ(3u, shiftedCodePosition(Replaces, 4)); // int| i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 5)); // int | i;
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 6)); // int |i;
+ EXPECT_EQ(3u, shiftedCodePosition(Replaces, 5)); // int | i;
+ EXPECT_EQ(3u, shiftedCodePosition(Replaces, 6)); // int |i;
EXPECT_EQ(4u, shiftedCodePosition(Replaces, 7)); // int |;
EXPECT_EQ(5u, shiftedCodePosition(Replaces, 8)); // int i|
}
@@ -205,8 +205,17 @@ TEST(ShiftedCodePositionTest, FindsNewCodePositionWithInserts) {
Replacements Replaces;
Replaces.insert(Replacement("", 4, 0, "\"\n\""));
// Assume '"12345678"' is turned into '"1234"\n"5678"'.
- EXPECT_EQ(4u, shiftedCodePosition(Replaces, 4)); // "123|5678"
- EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "1234|678"
+ EXPECT_EQ(3u, shiftedCodePosition(Replaces, 3)); // "123|5678"
+ EXPECT_EQ(7u, shiftedCodePosition(Replaces, 4)); // "1234|678"
+ EXPECT_EQ(8u, shiftedCodePosition(Replaces, 5)); // "12345|78"
+}
+
+TEST(ShiftedCodePositionTest, FindsNewCodePositionInReplacedText) {
+ Replacements Replaces;
+ // Replace the first four characters with "abcd".
+ Replaces.insert(Replacement("", 0, 4, "abcd"));
+ for (unsigned i = 0; i < 3; ++i)
+ EXPECT_EQ(i, shiftedCodePosition(Replaces, i));
}
class FlushRewrittenFilesTest : public ::testing::Test {
@@ -489,5 +498,98 @@ TEST(DeduplicateTest, detectsConflicts) {
}
}
+class MergeReplacementsTest : public ::testing::Test {
+protected:
+ void mergeAndTestRewrite(StringRef Code, StringRef Intermediate,
+ StringRef Result, const Replacements &First,
+ const Replacements &Second) {
+ // These are mainly to verify the test itself and make it easier to read.
+ std::string AfterFirst = applyAllReplacements(Code, First);
+ std::string InSequenceRewrite = applyAllReplacements(AfterFirst, Second);
+ EXPECT_EQ(Intermediate, AfterFirst);
+ EXPECT_EQ(Result, InSequenceRewrite);
+
+ tooling::Replacements Merged = mergeReplacements(First, Second);
+ std::string MergedRewrite = applyAllReplacements(Code, Merged);
+ EXPECT_EQ(InSequenceRewrite, MergedRewrite);
+ if (InSequenceRewrite != MergedRewrite)
+ for (tooling::Replacement M : Merged)
+ llvm::errs() << M.getOffset() << " " << M.getLength() << " "
+ << M.getReplacementText() << "\n";
+ }
+ void mergeAndTestRewrite(StringRef Code, const Replacements &First,
+ const Replacements &Second) {
+ std::string InSequenceRewrite =
+ applyAllReplacements(applyAllReplacements(Code, First), Second);
+ tooling::Replacements Merged = mergeReplacements(First, Second);
+ std::string MergedRewrite = applyAllReplacements(Code, Merged);
+ EXPECT_EQ(InSequenceRewrite, MergedRewrite);
+ if (InSequenceRewrite != MergedRewrite)
+ for (tooling::Replacement M : Merged)
+ llvm::errs() << M.getOffset() << " " << M.getLength() << " "
+ << M.getReplacementText() << "\n";
+ }
+};
+
+TEST_F(MergeReplacementsTest, Offsets) {
+ mergeAndTestRewrite("aaa", "aabab", "cacabab",
+ {{"", 2, 0, "b"}, {"", 3, 0, "b"}},
+ {{"", 0, 0, "c"}, {"", 1, 0, "c"}});
+ mergeAndTestRewrite("aaa", "babaa", "babacac",
+ {{"", 0, 0, "b"}, {"", 1, 0, "b"}},
+ {{"", 4, 0, "c"}, {"", 5, 0, "c"}});
+ mergeAndTestRewrite("aaaa", "aaa", "aac", {{"", 1, 1, ""}},
+ {{"", 2, 1, "c"}});
+
+ mergeAndTestRewrite("aa", "bbabba", "bbabcba",
+ {{"", 0, 0, "bb"}, {"", 1, 0, "bb"}}, {{"", 4, 0, "c"}});
+}
+
+TEST_F(MergeReplacementsTest, Concatenations) {
+ // Basic concatenations. It is important to merge these into a single
+ // replacement to ensure the correct order.
+ EXPECT_EQ((Replacements{{"", 0, 0, "ab"}}),
+ mergeReplacements({{"", 0, 0, "a"}}, {{"", 1, 0, "b"}}));
+ EXPECT_EQ((Replacements{{"", 0, 0, "ba"}}),
+ mergeReplacements({{"", 0, 0, "a"}}, {{"", 0, 0, "b"}}));
+ mergeAndTestRewrite("", "a", "ab", {{"", 0, 0, "a"}}, {{"", 1, 0, "b"}});
+ mergeAndTestRewrite("", "a", "ba", {{"", 0, 0, "a"}}, {{"", 0, 0, "b"}});
+}
+
+TEST_F(MergeReplacementsTest, NotChangingLengths) {
+ mergeAndTestRewrite("aaaa", "abba", "acca", {{"", 1, 2, "bb"}},
+ {{"", 1, 2, "cc"}});
+ mergeAndTestRewrite("aaaa", "abba", "abcc", {{"", 1, 2, "bb"}},
+ {{"", 2, 2, "cc"}});
+ mergeAndTestRewrite("aaaa", "abba", "ccba", {{"", 1, 2, "bb"}},
+ {{"", 0, 2, "cc"}});
+ mergeAndTestRewrite("aaaaaa", "abbdda", "abccda",
+ {{"", 1, 2, "bb"}, {"", 3, 2, "dd"}}, {{"", 2, 2, "cc"}});
+}
+
+TEST_F(MergeReplacementsTest, OverlappingRanges) {
+ mergeAndTestRewrite("aaa", "bbd", "bcbcd",
+ {{"", 0, 1, "bb"}, {"", 1, 2, "d"}},
+ {{"", 1, 0, "c"}, {"", 2, 0, "c"}});
+
+ mergeAndTestRewrite("aaaa", "aabbaa", "acccca", {{"", 2, 0, "bb"}},
+ {{"", 1, 4, "cccc"}});
+ mergeAndTestRewrite("aaaa", "aababa", "acccca",
+ {{"", 2, 0, "b"}, {"", 3, 0, "b"}}, {{"", 1, 4, "cccc"}});
+ mergeAndTestRewrite("aaaaaa", "abbbba", "abba", {{"", 1, 4, "bbbb"}},
+ {{"", 2, 2, ""}});
+ mergeAndTestRewrite("aaaa", "aa", "cc", {{"", 1, 1, ""}, {"", 2, 1, ""}},
+ {{"", 0, 2, "cc"}});
+ mergeAndTestRewrite("aa", "abbba", "abcbcba", {{"", 1, 0, "bbb"}},
+ {{"", 2, 0, "c"}, {"", 3, 0, "c"}});
+
+ mergeAndTestRewrite("aaa", "abbab", "ccdd",
+ {{"", 0, 1, ""}, {"", 2, 0, "bb"}, {"", 3, 0, "b"}},
+ {{"", 0, 2, "cc"}, {"", 2, 3, "dd"}});
+ mergeAndTestRewrite("aa", "babbab", "ccdd",
+ {{"", 0, 0, "b"}, {"", 1, 0, "bb"}, {"", 2, 0, "b"}},
+ {{"", 0, 3, "cc"}, {"", 3, 3, "dd"}});
+}
+
} // end namespace tooling
} // end namespace clang
diff --git a/unittests/Tooling/RewriterTestContext.h b/unittests/Tooling/RewriterTestContext.h
index 112efac52ebca..eee7ea1873b80 100644
--- a/unittests/Tooling/RewriterTestContext.h
+++ b/unittests/Tooling/RewriterTestContext.h
@@ -34,15 +34,20 @@ namespace clang {
/// methods, which help with writing tests that change files.
class RewriterTestContext {
public:
- RewriterTestContext()
- : DiagOpts(new DiagnosticOptions()),
- Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
- &*DiagOpts),
- DiagnosticPrinter(llvm::outs(), &*DiagOpts),
- Files((FileSystemOptions())),
- Sources(Diagnostics, Files),
- Rewrite(Sources, Options) {
+ RewriterTestContext()
+ : DiagOpts(new DiagnosticOptions()),
+ Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
+ &*DiagOpts),
+ DiagnosticPrinter(llvm::outs(), &*DiagOpts),
+ InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+ Files(FileSystemOptions(), OverlayFileSystem),
+ Sources(Diagnostics, Files), Rewrite(Sources, Options) {
Diagnostics.setClient(&DiagnosticPrinter, false);
+ // FIXME: To make these tests truly in-memory, we need to overlay the
+ // builtin headers.
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
}
~RewriterTestContext() {}
@@ -50,9 +55,9 @@ class RewriterTestContext {
FileID createInMemoryFile(StringRef Name, StringRef Content) {
std::unique_ptr<llvm::MemoryBuffer> Source =
llvm::MemoryBuffer::getMemBuffer(Content);
- const FileEntry *Entry =
- Files.getVirtualFile(Name, Source->getBufferSize(), 0);
- Sources.overrideFileContents(Entry, std::move(Source));
+ InMemoryFileSystem->addFile(Name, 0, std::move(Source));
+
+ const FileEntry *Entry = Files.getFile(Name);
assert(Entry != nullptr);
return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User);
}
@@ -109,6 +114,8 @@ class RewriterTestContext {
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
DiagnosticsEngine Diagnostics;
TextDiagnosticPrinter DiagnosticPrinter;
+ IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
+ IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem;
FileManager Files;
SourceManager Sources;
LangOptions Options;
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index 4b14ebb2c300d..c4b174f183da8 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -18,6 +18,8 @@
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TargetRegistry.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
@@ -147,8 +149,13 @@ TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
}
TEST(ToolInvocation, TestMapVirtualFile) {
- IntrusiveRefCntPtr<clang::FileManager> Files(
- new clang::FileManager(clang::FileSystemOptions()));
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
std::vector<std::string> Args;
Args.push_back("tool-executable");
Args.push_back("-Idef");
@@ -156,8 +163,10 @@ TEST(ToolInvocation, TestMapVirtualFile) {
Args.push_back("test.cpp");
clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
Files.get());
- Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
- Invocation.mapVirtualFile("def/abc", "\n");
+ InMemoryFileSystem->addFile(
+ "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
+ InMemoryFileSystem->addFile("def/abc", 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
EXPECT_TRUE(Invocation.run());
}
@@ -166,8 +175,13 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) {
// mapped module.map is found on the include path. In the future, expand this
// test to run a full modules enabled compilation, so we make sure we can
// rerun modules compilations with a virtual file system.
- IntrusiveRefCntPtr<clang::FileManager> Files(
- new clang::FileManager(clang::FileSystemOptions()));
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
std::vector<std::string> Args;
Args.push_back("tool-executable");
Args.push_back("-Idef");
@@ -175,11 +189,14 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) {
Args.push_back("test.cpp");
clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
Files.get());
- Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
- Invocation.mapVirtualFile("def/abc", "\n");
+ InMemoryFileSystem->addFile(
+ "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
+ InMemoryFileSystem->addFile("def/abc", 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
// Add a module.map file in the include directory of our header, so we trigger
// the module.map header search logic.
- Invocation.mapVirtualFile("def/module.map", "\n");
+ InMemoryFileSystem->addFile("def/module.map", 0,
+ llvm::MemoryBuffer::getMemBuffer("\n"));
EXPECT_TRUE(Invocation.run());
}
@@ -271,7 +288,7 @@ TEST(ClangToolTest, ArgumentAdjusters) {
bool Found = false;
bool Ran = false;
ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
- [&Found, &Ran](const CommandLineArguments &Args) {
+ [&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
Ran = true;
if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
Found = true;
@@ -291,6 +308,86 @@ TEST(ClangToolTest, ArgumentAdjusters) {
EXPECT_FALSE(Found);
}
+namespace {
+/// Find a target name such that looking for it in TargetRegistry by that name
+/// returns the same target. We expect that there is at least one target
+/// configured with this property.
+std::string getAnyTarget() {
+ llvm::InitializeAllTargets();
+ for (const auto &Target : llvm::TargetRegistry::targets()) {
+ std::string Error;
+ StringRef TargetName(Target.getName());
+ if (TargetName == "x86-64")
+ TargetName = "x86_64";
+ if (llvm::TargetRegistry::lookupTarget(TargetName, Error) == &Target) {
+ return TargetName;
+ }
+ }
+ return "";
+}
+}
+
+TEST(addTargetAndModeForProgramName, AddsTargetAndMode) {
+ std::string Target = getAnyTarget();
+ ASSERT_FALSE(Target.empty());
+
+ std::vector<std::string> Args = {"clang", "-foo"};
+ addTargetAndModeForProgramName(Args, "");
+ EXPECT_EQ((std::vector<std::string>{"clang", "-foo"}), Args);
+ addTargetAndModeForProgramName(Args, Target + "-g++");
+ EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
+ "--driver-mode=g++", "-foo"}),
+ Args);
+}
+
+TEST(addTargetAndModeForProgramName, PathIgnored) {
+ std::string Target = getAnyTarget();
+ ASSERT_FALSE(Target.empty());
+
+ SmallString<32> ToolPath;
+ llvm::sys::path::append(ToolPath, "foo", "bar", Target + "-g++");
+
+ std::vector<std::string> Args = {"clang", "-foo"};
+ addTargetAndModeForProgramName(Args, ToolPath);
+ EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
+ "--driver-mode=g++", "-foo"}),
+ Args);
+}
+
+TEST(addTargetAndModeForProgramName, IgnoresExistingTarget) {
+ std::string Target = getAnyTarget();
+ ASSERT_FALSE(Target.empty());
+
+ std::vector<std::string> Args = {"clang", "-foo", "-target", "something"};
+ addTargetAndModeForProgramName(Args, Target + "-g++");
+ EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
+ "-target", "something"}),
+ Args);
+
+ std::vector<std::string> ArgsAlt = {"clang", "-foo", "-target=something"};
+ addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
+ EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
+ "-target=something"}),
+ ArgsAlt);
+}
+
+TEST(addTargetAndModeForProgramName, IgnoresExistingMode) {
+ std::string Target = getAnyTarget();
+ ASSERT_FALSE(Target.empty());
+
+ std::vector<std::string> Args = {"clang", "-foo", "--driver-mode=abc"};
+ addTargetAndModeForProgramName(Args, Target + "-g++");
+ EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
+ "--driver-mode=abc"}),
+ Args);
+
+ std::vector<std::string> ArgsAlt = {"clang", "-foo", "--driver-mode", "abc"};
+ addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
+ EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
+ "--driver-mode", "abc"}),
+ ArgsAlt);
+}
+
#ifndef LLVM_ON_WIN32
TEST(ClangToolTest, BuildASTs) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
diff --git a/unittests/libclang/LibclangTest.cpp b/unittests/libclang/LibclangTest.cpp
index becebf076d61c..e190dec89a87b 100644
--- a/unittests/libclang/LibclangTest.cpp
+++ b/unittests/libclang/LibclangTest.cpp
@@ -379,8 +379,10 @@ public:
Filename = Path.str();
Files.insert(Filename);
}
+ llvm::sys::fs::create_directories(llvm::sys::path::parent_path(Filename));
std::ofstream OS(Filename);
OS << Contents;
+ assert(OS.good());
}
void DisplayDiagnostics() {
unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
@@ -465,3 +467,30 @@ TEST_F(LibclangReparseTest, ReparseWithModule) {
ASSERT_TRUE(ReparseTU(0, nullptr /* No unsaved files. */));
EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
}
+
+TEST_F(LibclangReparseTest, clang_parseTranslationUnit2FullArgv) {
+ // Provide a fake GCC 99.9.9 standard library that always overrides any local
+ // GCC installation.
+ std::string EmptyFiles[] = {"lib/gcc/arm-linux-gnueabi/99.9.9/crtbegin.o",
+ "include/arm-linux-gnueabi/.keep",
+ "include/c++/99.9.9/vector"};
+
+ for (auto &Name : EmptyFiles)
+ WriteFile(Name, "\n");
+
+ std::string Filename = "test.cc";
+ WriteFile(Filename, "#include <vector>\n");
+
+ std::string Clang = "bin/clang";
+ WriteFile(Clang, "");
+
+ const char *Argv[] = {Clang.c_str(), "-target", "arm-linux-gnueabi",
+ "--gcc-toolchain="};
+
+ EXPECT_EQ(CXError_Success,
+ clang_parseTranslationUnit2FullArgv(Index, Filename.c_str(), Argv,
+ sizeof(Argv) / sizeof(Argv[0]),
+ nullptr, 0, TUFlags, &ClangTU));
+ EXPECT_EQ(0U, clang_getNumDiagnostics(ClangTU));
+ DisplayDiagnostics();
+}