diff options
Diffstat (limited to 'clang/unittests')
-rw-r--r-- | clang/unittests/AST/DeclPrinterTest.cpp | 104 | ||||
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp | 11 | ||||
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 79 | ||||
-rw-r--r-- | clang/unittests/Basic/DiagnosticTest.cpp | 36 | ||||
-rw-r--r-- | clang/unittests/Driver/ToolChainTest.cpp | 2 |
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"); |