r333166 - [ASTImporter] Add unit tests for structural equivalence
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Thu May 24 01:41:07 PDT 2018
Author: martong
Date: Thu May 24 01:41:07 2018
New Revision: 333166
URL: http://llvm.org/viewvc/llvm-project?rev=333166&view=rev
Log:
[ASTImporter] Add unit tests for structural equivalence
Summary:
This patch add new tests for structural equivalence. For that a new
common header is created which holds the test related language specific
types and functions.
Reviewers: a.sidorin, xazax.hun, szepet
Subscribers: rnkovacs, dkrupp, cfe-commits
Differential Revision: https://reviews.llvm.org/D46867
Added:
cfe/trunk/unittests/AST/Language.cpp
cfe/trunk/unittests/AST/Language.h
cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp
Modified:
cfe/trunk/unittests/AST/ASTImporterTest.cpp
cfe/trunk/unittests/AST/CMakeLists.txt
cfe/trunk/unittests/AST/MatchVerifier.h
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=333166&r1=333165&r2=333166&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Thu May 24 01:41:07 2018
@@ -19,6 +19,7 @@
#include "clang/Tooling/Tooling.h"
#include "DeclMatcher.h"
+#include "Language.h"
#include "gtest/gtest.h"
#include "llvm/ADT/StringMap.h"
@@ -29,50 +30,6 @@ using internal::Matcher;
using internal::BindableMatcher;
using llvm::StringMap;
-typedef std::vector<std::string> ArgVector;
-typedef std::vector<ArgVector> RunOptions;
-
-static bool isCXX(Language Lang) {
- return Lang == Lang_CXX || Lang == Lang_CXX11;
-}
-
-static ArgVector getBasicRunOptionsForLanguage(Language Lang) {
- ArgVector BasicArgs;
- // Test with basic arguments.
- switch (Lang) {
- case Lang_C:
- BasicArgs = {"-x", "c", "-std=c99"};
- break;
- case Lang_C89:
- BasicArgs = {"-x", "c", "-std=c89"};
- break;
- case Lang_CXX:
- BasicArgs = {"-std=c++98", "-frtti"};
- break;
- case Lang_CXX11:
- BasicArgs = {"-std=c++11", "-frtti"};
- break;
- case Lang_OpenCL:
- case Lang_OBJCXX:
- llvm_unreachable("Not implemented yet!");
- }
- return BasicArgs;
-}
-
-static RunOptions getRunOptionsForLanguage(Language Lang) {
- ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang);
-
- // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
- // default behaviour.
- if (isCXX(Lang)) {
- ArgVector ArgsForDelayedTemplateParse = BasicArgs;
- ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
- return {BasicArgs, ArgsForDelayedTemplateParse};
- }
-
- return {BasicArgs};
-}
-
// Creates a virtual file and assigns that to the context of given AST. If the
// file already exists then the file will not be created again as a duplicate.
static void
Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=333166&r1=333165&r2=333166&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Thu May 24 01:41:07 2018
@@ -15,9 +15,11 @@ add_clang_unittest(ASTTests
DeclTest.cpp
EvaluateAsRValueTest.cpp
ExternalASTSourceTest.cpp
+ Language.cpp
NamedDeclPrinterTest.cpp
SourceLocationTest.cpp
StmtPrinterTest.cpp
+ StructuralEquivalenceTest.cpp
)
target_link_libraries(ASTTests
Added: cfe/trunk/unittests/AST/Language.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/Language.cpp?rev=333166&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/Language.cpp (added)
+++ cfe/trunk/unittests/AST/Language.cpp Thu May 24 01:41:07 2018
@@ -0,0 +1,60 @@
+//===------ unittest/AST/Language.cpp - AST unit test support -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines language options for AST unittests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Language.h"
+
+namespace clang {
+namespace ast_matchers {
+
+ArgVector getBasicRunOptionsForLanguage(Language Lang) {
+ ArgVector BasicArgs;
+ // Test with basic arguments.
+ switch (Lang) {
+ case Lang_C:
+ BasicArgs = {"-x", "c", "-std=c99"};
+ break;
+ case Lang_C89:
+ BasicArgs = {"-x", "c", "-std=c89"};
+ break;
+ case Lang_CXX:
+ BasicArgs = {"-std=c++98", "-frtti"};
+ break;
+ case Lang_CXX11:
+ BasicArgs = {"-std=c++11", "-frtti"};
+ break;
+ case Lang_CXX14:
+ BasicArgs = {"-std=c++14", "-frtti"};
+ break;
+ case Lang_OpenCL:
+ case Lang_OBJCXX:
+ llvm_unreachable("Not implemented yet!");
+ }
+ return BasicArgs;
+}
+
+RunOptions getRunOptionsForLanguage(Language Lang) {
+ ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang);
+
+ // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
+ // default behaviour.
+ if (isCXX(Lang)) {
+ ArgVector ArgsForDelayedTemplateParse = BasicArgs;
+ ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
+ return {BasicArgs, ArgsForDelayedTemplateParse};
+ }
+
+ return {BasicArgs};
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
Added: cfe/trunk/unittests/AST/Language.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/Language.h?rev=333166&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/Language.h (added)
+++ cfe/trunk/unittests/AST/Language.h Thu May 24 01:41:07 2018
@@ -0,0 +1,47 @@
+//===------ unittest/AST/Language.h - AST unit test support ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines language options for AST unittests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_AST_LANGUAGE_H
+#define LLVM_CLANG_UNITTESTS_AST_LANGUAGE_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include <vector>
+#include <string>
+
+namespace clang {
+namespace ast_matchers {
+
+typedef std::vector<std::string> ArgVector;
+typedef std::vector<ArgVector> RunOptions;
+
+enum Language {
+ Lang_C,
+ Lang_C89,
+ Lang_CXX,
+ Lang_CXX11,
+ Lang_CXX14,
+ Lang_OpenCL,
+ Lang_OBJCXX
+};
+
+inline bool isCXX(Language Lang) {
+ return Lang == Lang_CXX || Lang == Lang_CXX11 || Lang == Lang_CXX14;
+}
+
+ArgVector getBasicRunOptionsForLanguage(Language Lang);
+RunOptions getRunOptionsForLanguage(Language Lang);
+
+} // end namespace ast_matchers
+} // end namespace clang
+
+#endif
Modified: cfe/trunk/unittests/AST/MatchVerifier.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/MatchVerifier.h?rev=333166&r1=333165&r2=333166&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/MatchVerifier.h (original)
+++ cfe/trunk/unittests/AST/MatchVerifier.h Thu May 24 01:41:07 2018
@@ -23,20 +23,12 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
+#include "Language.h"
#include "gtest/gtest.h"
namespace clang {
namespace ast_matchers {
-enum Language {
- Lang_C,
- Lang_C89,
- Lang_CXX,
- Lang_CXX11,
- Lang_OpenCL,
- Lang_OBJCXX
-};
-
/// \brief Base class for verifying some property of nodes found by a matcher.
template <typename NodeType>
class MatchVerifier : public MatchFinder::MatchCallback {
@@ -113,6 +105,10 @@ testing::AssertionResult MatchVerifier<N
Args.push_back("-std=c++11");
FileName = "input.cc";
break;
+ case Lang_CXX14:
+ Args.push_back("-std=c++14");
+ FileName = "input.cc";
+ break;
case Lang_OpenCL:
FileName = "input.cl";
break;
Added: cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp?rev=333166&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp (added)
+++ cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Thu May 24 01:41:07 2018
@@ -0,0 +1,207 @@
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/AST/ASTStructuralEquivalence.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Tooling/Tooling.h"
+
+#include "Language.h"
+#include "DeclMatcher.h"
+
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using std::get;
+
+struct StructuralEquivalenceTest : ::testing::Test {
+ std::unique_ptr<ASTUnit> AST0, AST1;
+ std::string Code0, Code1; // Buffers for SourceManager
+
+ // Get a pair of Decl pointers to the synthetised declarations from the given
+ // code snipets. By default we search for the unique Decl with name 'foo' in
+ // both snippets.
+ std::tuple<NamedDecl *, NamedDecl *>
+ makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1,
+ Language Lang, const char *const Identifier = "foo") {
+
+ this->Code0 = SrcCode0;
+ this->Code1 = SrcCode1;
+ ArgVector Args = getBasicRunOptionsForLanguage(Lang);
+
+ const char *const InputFileName = "input.cc";
+
+ AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);
+ AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);
+
+ ASTContext &Ctx0 = AST0->getASTContext(), &Ctx1 = AST1->getASTContext();
+
+ auto getDecl = [](ASTContext &Ctx, const std::string &Name) -> NamedDecl * {
+ IdentifierInfo *SearchedII = &Ctx.Idents.get(Name);
+ assert(SearchedII && "Declaration with the identifier "
+ "should be specified in test!");
+ DeclarationName SearchDeclName(SearchedII);
+ SmallVector<NamedDecl *, 4> FoundDecls;
+ Ctx.getTranslationUnitDecl()->localUncachedLookup(SearchDeclName,
+ FoundDecls);
+
+ // We should find one Decl but one only.
+ assert(FoundDecls.size() == 1);
+
+ return FoundDecls[0];
+ };
+
+ NamedDecl *D0 = getDecl(Ctx0, Identifier);
+ NamedDecl *D1 = getDecl(Ctx1, Identifier);
+ assert(D0);
+ assert(D1);
+ return std::make_tuple(D0, D1);
+ }
+
+ bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) {
+ llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
+ StructuralEquivalenceContext Ctx(D0->getASTContext(), D1->getASTContext(),
+ NonEquivalentDecls, false, false);
+ return Ctx.IsStructurallyEquivalent(D0, D1);
+ }
+
+ bool testStructuralMatch(std::tuple<NamedDecl *, NamedDecl *> t) {
+ return testStructuralMatch(get<0>(t), get<1>(t));
+ }
+};
+
+TEST_F(StructuralEquivalenceTest, Int) {
+ auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {
+ auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, Char) {
+ auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+// This test is disabled for now.
+// FIXME Whether this is equivalent is dependendant on the target.
+TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {
+ auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {
+ auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {
+ auto Decls = makeNamedDecls("struct foo { int x; };",
+ "struct foo { signed int x; };", Lang_CXX);
+ EXPECT_TRUE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {
+ auto Decls = makeNamedDecls("struct foo { char x; };",
+ "struct foo { signed char x; };", Lang_CXX);
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
+ auto Decls = makeNamedDecls(
+ "template <class T> struct foo; template<> struct foo<int>{};",
+ "template <class T> struct foo; template<> struct foo<signed int>{};",
+ Lang_CXX);
+ ClassTemplateSpecializationDecl *Spec0 =
+ *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin();
+ ClassTemplateSpecializationDecl *Spec1 =
+ *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin();
+ ASSERT_TRUE(Spec0 != nullptr);
+ ASSERT_TRUE(Spec1 != nullptr);
+ EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
+ auto Decls = makeNamedDecls(
+ "template <class T> struct foo; template<> struct foo<char>{};",
+ "template <class T> struct foo; template<> struct foo<signed char>{};",
+ Lang_CXX);
+ ClassTemplateSpecializationDecl *Spec0 =
+ *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin();
+ ClassTemplateSpecializationDecl *Spec1 =
+ *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin();
+ ASSERT_TRUE(Spec0 != nullptr);
+ ASSERT_TRUE(Spec1 != nullptr);
+ EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
+}
+
+TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
+ auto Decls = makeNamedDecls(
+ R"(
+ struct true_type{};
+ template <class T> struct foo;
+ template<> struct foo<char> : true_type {};
+ )",
+ R"(
+ struct true_type{};
+ template <class T> struct foo;
+ template<> struct foo<signed char> : true_type {};
+ )",
+ Lang_CXX);
+ ClassTemplateSpecializationDecl *Spec0 =
+ *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin();
+ ClassTemplateSpecializationDecl *Spec1 =
+ *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin();
+ ASSERT_TRUE(Spec0 != nullptr);
+ ASSERT_TRUE(Spec1 != nullptr);
+ EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
+}
+
+// This test is disabled for now.
+// FIXME Enable it, once the check is implemented.
+TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
+ auto Code =
+ R"(
+ namespace NS {
+ template <class T> class Base {
+ int a;
+ };
+ class Derived : Base<Derived> {
+ };
+ }
+ void foo(NS::Derived &);
+ )";
+ auto Decls = makeNamedDecls(Code, Code, Lang_CXX);
+
+ NamespaceDecl *NS =
+ LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
+ ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
+ get<1>(Decls), classTemplateDecl(hasName("Base")));
+
+ // Reorder the decls, move the TD to the last place in the DC.
+ NS->removeDecl(TD);
+ NS->addDeclInternal(TD);
+
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {
+ auto Code = "class X { int a; int b; };";
+ auto Decls = makeNamedDecls(Code, Code, Lang_CXX, "X");
+
+ CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(
+ get<1>(Decls), cxxRecordDecl(hasName("X")));
+ FieldDecl *FD =
+ FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));
+
+ // Reorder the FieldDecls
+ RD->removeDecl(FD);
+ RD->addDeclInternal(FD);
+
+ EXPECT_FALSE(testStructuralMatch(Decls));
+}
+
+} // end namespace ast_matchers
+} // end namespace clang
More information about the cfe-commits
mailing list