aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/AST/DeclPrinterTest.cpp104
-rw-r--r--clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp11
-rw-r--r--clang/unittests/Analysis/FlowSensitive/TransferTest.cpp79
-rw-r--r--clang/unittests/Basic/DiagnosticTest.cpp36
-rw-r--r--clang/unittests/Driver/ToolChainTest.cpp2
5 files changed, 174 insertions, 58 deletions
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index 28750c4..1a1b707 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -1022,91 +1022,91 @@ TEST(DeclPrinter, TestFieldDecl2) {
}
TEST(DeclPrinter, TestClassTemplateDecl1) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<typename T>"
- "struct A { T a; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<typename T>"
+ "struct A { T a; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <typename T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl2) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<typename T = int>"
- "struct A { T a; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T = int> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<typename T = int>"
+ "struct A { T a; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <typename T = int> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl3) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<class T>"
- "struct A { T a; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <class T> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<class T>"
+ "struct A { T a; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl4) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<typename T, typename U>"
- "struct A { T a; U b; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <typename T, typename U> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<typename T, typename U>"
+ "struct A { T a; U b; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <typename T, typename U> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl5) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<int N>"
- "struct A { int a[N]; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <int N> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<int N>"
+ "struct A { int a[N]; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <int N> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl6) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<int N = 42>"
- "struct A { int a[N]; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <int N = 42> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("template<int N = 42>"
+ "struct A { int a[N]; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <int N = 42> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl7) {
- ASSERT_TRUE(PrintedDeclCXX98Matches(
- "typedef int MyInt;"
- "template<MyInt N>"
- "struct A { int a[N]; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <MyInt N> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX98Matches("typedef int MyInt;"
+ "template<MyInt N>"
+ "struct A { int a[N]; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <MyInt N> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl8) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<template<typename U> class T> struct A { };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <template <typename U> class T> struct A {}"));
+ "template<template<typename U> class T> struct A { };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <template <typename U> class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl9) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
- "template<typename T> struct Z { };"
- "template<template<typename U> class T = Z> struct A { };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <template <typename U> class T> struct A {}"));
+ "template<typename T> struct Z { };"
+ "template<template<typename U> class T = Z> struct A { };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <template <typename U> class T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl10) {
- ASSERT_TRUE(PrintedDeclCXX11Matches(
- "template<typename... T>"
- "struct A { int a; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <typename ...T> struct A {}"));
+ ASSERT_TRUE(
+ PrintedDeclCXX11Matches("template<typename... T>"
+ "struct A { int a; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <typename ...T> struct A {}"));
}
TEST(DeclPrinter, TestClassTemplateDecl11) {
ASSERT_TRUE(PrintedDeclCXX11Matches(
- "template<typename... T>"
- "struct A : public T... { int a; };",
- classTemplateDecl(hasName("A")).bind("id"),
- "template <typename ...T> struct A : public T... {}"));
+ "template<typename... T>"
+ "struct A : public T... { int a; };",
+ classTemplateDecl(hasName("A")).bind("id"),
+ "template <typename ...T> struct A : public T... {}"));
}
TEST(DeclPrinter, TestClassTemplatePartialSpecializationDecl1) {
diff --git a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
index 57162cd..73390a8 100644
--- a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp
@@ -64,7 +64,8 @@ TEST(RecordOpsTest, CopyRecord) {
runDataflow(
Code,
[](QualType Ty) -> llvm::StringMap<QualType> {
- if (Ty.getAsString() != "S")
+ std::string TypeAsString = Ty.getAsString();
+ if (TypeAsString != "S" && TypeAsString != "struct S")
return {};
QualType IntTy =
getFieldNamed(Ty->getAsRecordDecl(), "outer_int")->getType();
@@ -123,7 +124,8 @@ TEST(RecordOpsTest, RecordsEqual) {
runDataflow(
Code,
[](QualType Ty) -> llvm::StringMap<QualType> {
- if (Ty.getAsString() != "S")
+ std::string TypeAsString = Ty.getAsString();
+ if (TypeAsString != "S" && TypeAsString != "struct S")
return {};
QualType IntTy =
getFieldNamed(Ty->getAsRecordDecl(), "outer_int")->getType();
@@ -213,9 +215,10 @@ TEST(RecordOpsTest, CopyRecordBetweenDerivedAndBase) {
)";
auto SyntheticFieldCallback = [](QualType Ty) -> llvm::StringMap<QualType> {
CXXRecordDecl *ADecl = nullptr;
- if (Ty.getAsString() == "A")
+ std::string TypeAsString = Ty.getAsString();
+ if (TypeAsString == "A" || TypeAsString == "struct A")
ADecl = Ty->getAsCXXRecordDecl();
- else if (Ty.getAsString() == "B")
+ else if (TypeAsString == "B" || TypeAsString == "struct B")
ADecl = Ty->getAsCXXRecordDecl()
->bases_begin()
->getType()
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index cbd5596..66b3bba 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -3709,6 +3709,83 @@ TEST(TransferTest, StaticCastBaseToDerived) {
});
}
+TEST(TransferTest, MultipleConstructionsFromStaticCastsBaseToDerived) {
+ std::string Code = R"cc(
+ struct Base {};
+
+struct DerivedOne : public Base {
+ // Need a field in one of the derived siblings that the other doesn't have.
+ int I;
+};
+
+struct DerivedTwo : public Base {};
+
+int getInt();
+
+void target(Base* B) {
+ // Need something to cause modeling of I.
+ DerivedOne D1;
+ (void)D1.I;
+
+ // Switch cases are a reasonable pattern where the same variable might be
+ // safely cast to two different derived types within the same function
+ // without resetting the value of the variable. getInt is a stand-in for what
+ // is usually a function indicating the dynamic derived type.
+ switch (getInt()) {
+ case 1:
+ // Need a CXXConstructExpr or copy/move CXXOperatorCallExpr from each of
+ // the casts to derived types, cast from the same base variable, to
+ // trigger the copyRecord behavior.
+ (void)new DerivedOne(*static_cast<DerivedOne*>(B));
+ break;
+ case 2:
+ (void)new DerivedTwo(*static_cast<DerivedTwo*>(B));
+ break;
+ };
+}
+)cc";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ // This is a crash repro. We used to crash when transferring the
+ // construction of DerivedTwo because B's StorageLocation had a child
+ // for the field I, but DerivedTwo doesn't. Now, we should only copy the
+ // fields from B that are present in DerivedTwo.
+ });
+}
+
+TEST(TransferTest, CopyConstructionOfBaseAfterStaticCastsBaseToDerived) {
+ std::string Code = R"cc(
+ struct Base {};
+
+struct Derived : public Base {
+// Need a field in Derived that is not in Base.
+ char C;
+};
+
+void target(Base* B, Base* OtherB) {
+ Derived* D = static_cast<Derived*>(B);
+ *B = *OtherB;
+ // Need something to cause modeling of C.
+ (void)D->C;
+}
+
+)cc";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ // This is a crash repro. We used to crash when transferring the
+ // copy construction of B from OtherB because B's StorageLocation had a
+ // child for the field C, but Base doesn't (so OtherB doesn't, since
+ // it's never been cast to any other type), and we tried to copy from
+ // the source (OtherB) all the fields present in the destination (B).
+ // Now, we should only try to copy the fields from OtherB that are
+ // present in Base.
+ });
+}
+
TEST(TransferTest, ExplicitDerivedToBaseCast) {
std::string Code = R"cc(
struct Base {};
@@ -5320,7 +5397,7 @@ TEST(TransferTest, UnsupportedValueEquality) {
A,
B
};
-
+
void target() {
EC ec = EC::A;
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp
index 4b3af00..de09086 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -314,6 +314,42 @@ TEST_F(SuppressionMappingTest, LongestMatchWins) {
locForFile("clang/lib/Sema/foo.h")));
}
+TEST_F(SuppressionMappingTest, LongShortMatch) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*test/*
+ src:*lld/*=emit)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), IsEmpty());
+
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ locForFile("test/t1.cpp")));
+
+ // FIXME: This is confusing.
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ locForFile("lld/test/t2.cpp")));
+}
+
+TEST_F(SuppressionMappingTest, ShortLongMatch) {
+ llvm::StringLiteral SuppressionMappingFile = R"(
+ [unused]
+ src:*lld/*=emit
+ src:*test/*)";
+ Diags.getDiagnosticOptions().DiagnosticSuppressionMappingsFile = "foo.txt";
+ FS->addFile("foo.txt", /*ModificationTime=*/{},
+ llvm::MemoryBuffer::getMemBuffer(SuppressionMappingFile));
+ clang::ProcessWarningOptions(Diags, Diags.getDiagnosticOptions(), *FS);
+ EXPECT_THAT(diags(), IsEmpty());
+
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ locForFile("test/t1.cpp")));
+ EXPECT_TRUE(Diags.isSuppressedViaMapping(diag::warn_unused_function,
+ locForFile("lld/test/t2.cpp")));
+}
+
TEST_F(SuppressionMappingTest, IsIgnored) {
llvm::StringLiteral SuppressionMappingFile = R"(
[unused]
diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp
index c1c5c96..afa17ff 100644
--- a/clang/unittests/Driver/ToolChainTest.cpp
+++ b/clang/unittests/Driver/ToolChainTest.cpp
@@ -442,7 +442,7 @@ TEST(ToolChainTest, ParsedClangName) {
TEST(ToolChainTest, GetTargetAndMode) {
llvm::InitializeAllTargets();
std::string IgnoredError;
- if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError))
+ if (!llvm::TargetRegistry::lookupTarget(llvm::Triple("x86_64"), IgnoredError))
GTEST_SKIP();
ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang");