aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/Analysis/CFGTest.cpp153
-rw-r--r--clang/unittests/CodeGen/TestCompiler.h2
-rw-r--r--clang/unittests/Frontend/CompilerInstanceTest.cpp2
-rw-r--r--clang/unittests/Lex/LexHLSLRootSignatureTest.cpp3
-rw-r--r--clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp34
-rw-r--r--clang/unittests/Serialization/ForceCheckFileInputTest.cpp4
-rw-r--r--clang/unittests/StaticAnalyzer/CallEventTest.cpp41
-rw-r--r--clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp2
8 files changed, 235 insertions, 6 deletions
diff --git a/clang/unittests/Analysis/CFGTest.cpp b/clang/unittests/Analysis/CFGTest.cpp
index 46a6751..6aa09a8 100644
--- a/clang/unittests/Analysis/CFGTest.cpp
+++ b/clang/unittests/Analysis/CFGTest.cpp
@@ -93,6 +93,159 @@ TEST(CFG, DependantBaseAddImplicitDtors) {
.getStatus());
}
+TEST(CFG, SwitchCoveredEnumNoDefault) {
+ const char *Code = R"(
+ enum class E {E1, E2};
+ int f(E e) {
+ switch(e) {
+ case E::E1:
+ return 1;
+ case E::E2:
+ return 2;
+ }
+ return 0;
+ }
+ )";
+ CFG::BuildOptions Options;
+ Options.AssumeReachableDefaultInSwitchStatements = true;
+ BuildResult B = BuildCFG(Code, Options);
+ ASSERT_EQ(BuildResult::BuiltCFG, B.getStatus());
+
+ // [B5 (ENTRY)]
+ // Succs (1): B2
+ //
+ // [B1]
+ // 1: 0
+ // 2: return [B1.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B2]
+ // 1: e (ImplicitCastExpr, LValueToRValue, E)
+ // T: switch [B2.1]
+ // Preds (1): B5
+ // Succs (3): B3 B4 B1
+ //
+ // [B3]
+ // case E::E2:
+ // 1: 2
+ // 2: return [B3.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B4]
+ // case E::E1:
+ // 1: 1
+ // 2: return [B4.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B0 (EXIT)]
+ // Preds (3): B1 B3 B4
+
+ auto *CFG = B.getCFG();
+ const auto &Entry = CFG->getEntry();
+ ASSERT_EQ(1u, Entry.succ_size());
+ // First successor of Entry is the switch
+ CFGBlock *SwitchBlock = *Entry.succ_begin();
+ ASSERT_EQ(3u, SwitchBlock->succ_size());
+ // Last successor of the switch is after the switch
+ auto NoCaseSucc = SwitchBlock->succ_rbegin();
+ EXPECT_TRUE(NoCaseSucc->isReachable());
+
+ // Checking that the same node is Unreachable without this setting
+ Options.AssumeReachableDefaultInSwitchStatements = false;
+ B = BuildCFG(Code, Options);
+ ASSERT_EQ(BuildResult::BuiltCFG, B.getStatus());
+
+ const auto &Entry2 = B.getCFG()->getEntry();
+ ASSERT_EQ(1u, Entry2.succ_size());
+ CFGBlock *SwitchBlock2 = *Entry2.succ_begin();
+ ASSERT_EQ(3u, SwitchBlock2->succ_size());
+ auto NoCaseSucc2 = SwitchBlock2->succ_rbegin();
+ EXPECT_FALSE(NoCaseSucc2->isReachable());
+}
+
+TEST(CFG, SwitchCoveredEnumWithDefault) {
+ const char *Code = R"(
+ enum class E {E1, E2};
+ int f(E e) {
+ switch(e) {
+ case E::E1:
+ return 1;
+ case E::E2:
+ return 2;
+ default:
+ return 0;
+ }
+ return -1;
+ }
+ )";
+ CFG::BuildOptions Options;
+ Options.AssumeReachableDefaultInSwitchStatements = true;
+ BuildResult B = BuildCFG(Code, Options);
+ ASSERT_EQ(BuildResult::BuiltCFG, B.getStatus());
+
+ // [B6 (ENTRY)]
+ // Succs (1): B2
+ //
+ // [B1]
+ // 1: -1
+ // 2: return [B1.1];
+ // Succs (1): B0
+ //
+ // [B2]
+ // 1: e (ImplicitCastExpr, LValueToRValue, E)
+ // T: switch [B2.1]
+ // Preds (1): B6
+ // Succs (3): B4 B5 B3
+ //
+ // [B3]
+ // default:
+ // 1: 0
+ // 2: return [B3.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B4]
+ // case E::E2:
+ // 1: 2
+ // 2: return [B4.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B5]
+ // case E::E1:
+ // 1: 1
+ // 2: return [B5.1];
+ // Preds (1): B2
+ // Succs (1): B0
+ //
+ // [B0 (EXIT)]
+ // Preds (4): B1 B3 B4 B5
+
+ const auto &Entry = B.getCFG()->getEntry();
+ ASSERT_EQ(1u, Entry.succ_size());
+ // First successor of Entry is the switch
+ CFGBlock *SwitchBlock = *Entry.succ_begin();
+ ASSERT_EQ(3u, SwitchBlock->succ_size());
+ // Last successor of the switch is the default branch
+ auto defaultBlock = SwitchBlock->succ_rbegin();
+ EXPECT_TRUE(defaultBlock->isReachable());
+
+ // Checking that the same node is Unreachable without this setting
+ Options.AssumeReachableDefaultInSwitchStatements = false;
+ B = BuildCFG(Code, Options);
+ ASSERT_EQ(BuildResult::BuiltCFG, B.getStatus());
+
+ const auto &Entry2 = B.getCFG()->getEntry();
+ ASSERT_EQ(1u, Entry2.succ_size());
+ CFGBlock *SwitchBlock2 = *Entry2.succ_begin();
+ ASSERT_EQ(3u, SwitchBlock2->succ_size());
+ auto defaultBlock2 = SwitchBlock2->succ_rbegin();
+ EXPECT_FALSE(defaultBlock2->isReachable());
+}
+
TEST(CFG, IsLinear) {
auto expectLinear = [](bool IsLinear, const char *Code) {
BuildResult B = BuildCFG(Code);
diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h
index 57b5b07..9bd9060 100644
--- a/clang/unittests/CodeGen/TestCompiler.h
+++ b/clang/unittests/CodeGen/TestCompiler.h
@@ -52,7 +52,7 @@ struct TestCompiler {
PtrSize = TInfo.getPointerWidth(clang::LangAS::Default) / 8;
compiler.createFileManager();
- compiler.createSourceManager(compiler.getFileManager());
+ compiler.createSourceManager();
compiler.createPreprocessor(clang::TU_Prefix);
compiler.createASTContext();
diff --git a/clang/unittests/Frontend/CompilerInstanceTest.cpp b/clang/unittests/Frontend/CompilerInstanceTest.cpp
index 36cac5a..cd3fefa 100644
--- a/clang/unittests/Frontend/CompilerInstanceTest.cpp
+++ b/clang/unittests/Frontend/CompilerInstanceTest.cpp
@@ -33,7 +33,7 @@ TEST(CompilerInstance, DefaultVFSOverlayFromInvocation) {
SmallString<256> CurrentPath;
sys::fs::current_path(CurrentPath);
- sys::fs::make_absolute(CurrentPath, FileName);
+ sys::path::make_absolute(CurrentPath, FileName);
// Mount the VFS file itself on the path 'virtual.file'. Makes this test
// a bit shorter than creating a new dummy file just for this purpose.
diff --git a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
index 01f8d4f..82f1968 100644
--- a/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Lex/LexHLSLRootSignatureTest.cpp
@@ -226,6 +226,9 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
STATIC_BORDER_COLOR_OPAQUE_WHITE
STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT
+
+ UINT_BORDER_COLOR
+ NON_NORMALIZED_COORDINATES
)cc";
hlsl::RootSignatureLexer Lexer(Source);
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 9b9f5dd..f7e9d2d 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -263,7 +263,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
filter = FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT,
maxLOD = 9000, addressU = TEXTURE_ADDRESS_MIRROR,
comparisonFunc = COMPARISON_NOT_EQUAL,
- borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT
+ borderColor = STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT,
+ flags = 0
)
)cc";
@@ -336,6 +337,37 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
ASSERT_TRUE(Consumer->isSatisfied());
}
+TEST_F(ParseHLSLRootSignatureTest, ValidStaticSamplerFlagsTest) {
+ const llvm::StringLiteral Source = R"cc(
+ StaticSampler(s0, flags = UINT_BORDER_COLOR | NON_NORMALIZED_COORDINATES)
+ )cc";
+
+ auto Ctx = createMinimalASTContext();
+ StringLiteral *Signature = wrapSource(Ctx, Source);
+
+ TrivialModuleLoader ModLoader;
+ auto PP = createPP(Source, ModLoader);
+
+ hlsl::RootSignatureParser Parser(RootSignatureVersion::V1_1, Signature, *PP);
+
+ // Test no diagnostics produced
+ Consumer->setNoDiag();
+
+ ASSERT_FALSE(Parser.parse());
+
+ auto Elements = Parser.getElements();
+ ASSERT_EQ(Elements.size(), 1u);
+
+ RootElement Elem = Elements[0].getElement();
+ ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
+ auto ValidStaticSamplerFlags =
+ llvm::dxbc::StaticSamplerFlags::NonNormalizedCoordinates |
+ llvm::dxbc::StaticSamplerFlags::UintBorderColor;
+ ASSERT_EQ(std::get<StaticSampler>(Elem).Flags, ValidStaticSamplerFlags);
+
+ ASSERT_TRUE(Consumer->isSatisfied());
+}
+
TEST_F(ParseHLSLRootSignatureTest, ValidParseFloatsTest) {
const llvm::StringLiteral Source = R"cc(
StaticSampler(s0, mipLODBias = 0),
diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
index 24e2fd6..edf33ae 100644
--- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -122,8 +122,8 @@ export int aa = 43;
Clang.setDiagnostics(Diags);
Clang.createVirtualFileSystem(CIOpts.VFS);
- FileManager *FM = Clang.createFileManager();
- Clang.createSourceManager(*FM);
+ Clang.createFileManager();
+ Clang.createSourceManager();
EXPECT_TRUE(Clang.createTarget());
Clang.createPreprocessor(TU_Complete);
diff --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
index 8b5289e..f426892 100644
--- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp
+++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp
@@ -84,6 +84,47 @@ TEST(CXXDeallocatorCall, SimpleDestructor) {
#endif
}
+TEST(PrivateMethodCache, NeverReturnDanglingPointersWithMultipleASTs) {
+ // Each iteration will load and unload an AST multiple times. Since the code
+ // is always the same, we increase the chance of hitting a bug in the private
+ // method cache, returning a dangling pointer and crashing the process. If the
+ // cache is properly cleared between runs, the test should pass.
+ for (int I = 0; I < 100; ++I) {
+ auto const *Code = R"(
+ typedef __typeof(sizeof(int)) size_t;
+
+ extern void *malloc(size_t size);
+ extern void *memcpy(void *dest, const void *src, size_t n);
+
+ @interface SomeMoreData {
+ char const* _buffer;
+ int _size;
+ }
+ @property(nonatomic, readonly) const char* buffer;
+ @property(nonatomic) int size;
+
+ - (void)appendData:(SomeMoreData*)other;
+
+ @end
+
+ @implementation SomeMoreData
+ @synthesize size = _size;
+ @synthesize buffer = _buffer;
+
+ - (void)appendData:(SomeMoreData*)other {
+ int const len = (_size + other.size); // implicit self._length
+ char* d = malloc(sizeof(char) * len);
+ memcpy(d + 20, other.buffer, len);
+ }
+
+ @end
+ )";
+ std::string Diags;
+ EXPECT_TRUE(runCheckerOnCodeWithArgs<addCXXDeallocatorChecker>(
+ Code, {"-x", "objective-c", "-Wno-objc-root-class"}, Diags));
+ }
+}
+
} // namespace
} // namespace ento
} // namespace clang
diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp
index 80289ef..aa32bb3 100644
--- a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp
+++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp
@@ -65,7 +65,7 @@ public:
if (!Compiler.hasDiagnostics())
return false;
- Compiler.createSourceManager(*FileMgr);
+ Compiler.createSourceManager();
Compiler.addDependencyCollector(std::make_shared<TestFileCollector>(
Compiler.getInvocation().getDependencyOutputOpts(), Deps));