Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,18 @@
set(LLVM_LINK_COMPONENTS
Support
)
add_clang_unittest(BasicTests
CharInfoTest.cpp
DiagnosticTest.cpp
FileManagerTest.cpp
MemoryBufferCacheTest.cpp
SourceManagerTest.cpp
VirtualFileSystemTest.cpp
)
target_link_libraries(BasicTests
PRIVATE
clangBasic
clangLex
)

View File

@@ -0,0 +1,499 @@
//===- unittests/Basic/CharInfoTest.cpp -- ASCII classification tests -----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/CharInfo.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
// Check that the CharInfo table has been constructed reasonably.
TEST(CharInfoTest, validateInfoTable) {
using namespace charinfo;
EXPECT_EQ((unsigned)CHAR_SPACE, InfoTable[(unsigned)' ']);
EXPECT_EQ((unsigned)CHAR_HORZ_WS, InfoTable[(unsigned)'\t']);
EXPECT_EQ((unsigned)CHAR_HORZ_WS, InfoTable[(unsigned)'\f']); // ??
EXPECT_EQ((unsigned)CHAR_HORZ_WS, InfoTable[(unsigned)'\v']); // ??
EXPECT_EQ((unsigned)CHAR_VERT_WS, InfoTable[(unsigned)'\n']);
EXPECT_EQ((unsigned)CHAR_VERT_WS, InfoTable[(unsigned)'\r']);
EXPECT_EQ((unsigned)CHAR_UNDER, InfoTable[(unsigned)'_']);
EXPECT_EQ((unsigned)CHAR_PERIOD, InfoTable[(unsigned)'.']);
for (unsigned i = 'a'; i <= 'f'; ++i) {
EXPECT_EQ((unsigned)CHAR_XLOWER, InfoTable[i]);
EXPECT_EQ((unsigned)CHAR_XUPPER, InfoTable[i+'A'-'a']);
}
for (unsigned i = 'g'; i <= 'z'; ++i) {
EXPECT_EQ((unsigned)CHAR_LOWER, InfoTable[i]);
EXPECT_EQ((unsigned)CHAR_UPPER, InfoTable[i+'A'-'a']);
}
for (unsigned i = '0'; i <= '9'; ++i)
EXPECT_EQ((unsigned)CHAR_DIGIT, InfoTable[i]);
}
// Check various predicates.
TEST(CharInfoTest, isASCII) {
EXPECT_TRUE(isASCII('\0'));
EXPECT_TRUE(isASCII('\n'));
EXPECT_TRUE(isASCII(' '));
EXPECT_TRUE(isASCII('a'));
EXPECT_TRUE(isASCII('\x7f'));
EXPECT_FALSE(isASCII('\x80'));
EXPECT_FALSE(isASCII('\xc2'));
EXPECT_FALSE(isASCII('\xff'));
}
TEST(CharInfoTest, isIdentifierHead) {
EXPECT_TRUE(isIdentifierHead('a'));
EXPECT_TRUE(isIdentifierHead('A'));
EXPECT_TRUE(isIdentifierHead('z'));
EXPECT_TRUE(isIdentifierHead('Z'));
EXPECT_TRUE(isIdentifierHead('_'));
EXPECT_FALSE(isIdentifierHead('0'));
EXPECT_FALSE(isIdentifierHead('.'));
EXPECT_FALSE(isIdentifierHead('`'));
EXPECT_FALSE(isIdentifierHead('\0'));
EXPECT_FALSE(isIdentifierHead('$'));
EXPECT_TRUE(isIdentifierHead('$', /*AllowDollar=*/true));
EXPECT_FALSE(isIdentifierHead('\x80'));
EXPECT_FALSE(isIdentifierHead('\xc2'));
EXPECT_FALSE(isIdentifierHead('\xff'));
}
TEST(CharInfoTest, isIdentifierBody) {
EXPECT_TRUE(isIdentifierBody('a'));
EXPECT_TRUE(isIdentifierBody('A'));
EXPECT_TRUE(isIdentifierBody('z'));
EXPECT_TRUE(isIdentifierBody('Z'));
EXPECT_TRUE(isIdentifierBody('_'));
EXPECT_TRUE(isIdentifierBody('0'));
EXPECT_FALSE(isIdentifierBody('.'));
EXPECT_FALSE(isIdentifierBody('`'));
EXPECT_FALSE(isIdentifierBody('\0'));
EXPECT_FALSE(isIdentifierBody('$'));
EXPECT_TRUE(isIdentifierBody('$', /*AllowDollar=*/true));
EXPECT_FALSE(isIdentifierBody('\x80'));
EXPECT_FALSE(isIdentifierBody('\xc2'));
EXPECT_FALSE(isIdentifierBody('\xff'));
}
TEST(CharInfoTest, isHorizontalWhitespace) {
EXPECT_FALSE(isHorizontalWhitespace('a'));
EXPECT_FALSE(isHorizontalWhitespace('_'));
EXPECT_FALSE(isHorizontalWhitespace('0'));
EXPECT_FALSE(isHorizontalWhitespace('.'));
EXPECT_FALSE(isHorizontalWhitespace('`'));
EXPECT_FALSE(isHorizontalWhitespace('\0'));
EXPECT_FALSE(isHorizontalWhitespace('\x7f'));
EXPECT_TRUE(isHorizontalWhitespace(' '));
EXPECT_TRUE(isHorizontalWhitespace('\t'));
EXPECT_TRUE(isHorizontalWhitespace('\f')); // ??
EXPECT_TRUE(isHorizontalWhitespace('\v')); // ??
EXPECT_FALSE(isHorizontalWhitespace('\n'));
EXPECT_FALSE(isHorizontalWhitespace('\r'));
EXPECT_FALSE(isHorizontalWhitespace('\x80'));
EXPECT_FALSE(isHorizontalWhitespace('\xc2'));
EXPECT_FALSE(isHorizontalWhitespace('\xff'));
}
TEST(CharInfoTest, isVerticalWhitespace) {
EXPECT_FALSE(isVerticalWhitespace('a'));
EXPECT_FALSE(isVerticalWhitespace('_'));
EXPECT_FALSE(isVerticalWhitespace('0'));
EXPECT_FALSE(isVerticalWhitespace('.'));
EXPECT_FALSE(isVerticalWhitespace('`'));
EXPECT_FALSE(isVerticalWhitespace('\0'));
EXPECT_FALSE(isVerticalWhitespace('\x7f'));
EXPECT_FALSE(isVerticalWhitespace(' '));
EXPECT_FALSE(isVerticalWhitespace('\t'));
EXPECT_FALSE(isVerticalWhitespace('\f')); // ??
EXPECT_FALSE(isVerticalWhitespace('\v')); // ??
EXPECT_TRUE(isVerticalWhitespace('\n'));
EXPECT_TRUE(isVerticalWhitespace('\r'));
EXPECT_FALSE(isVerticalWhitespace('\x80'));
EXPECT_FALSE(isVerticalWhitespace('\xc2'));
EXPECT_FALSE(isVerticalWhitespace('\xff'));
}
TEST(CharInfoTest, isWhitespace) {
EXPECT_FALSE(isWhitespace('a'));
EXPECT_FALSE(isWhitespace('_'));
EXPECT_FALSE(isWhitespace('0'));
EXPECT_FALSE(isWhitespace('.'));
EXPECT_FALSE(isWhitespace('`'));
EXPECT_FALSE(isWhitespace('\0'));
EXPECT_FALSE(isWhitespace('\x7f'));
EXPECT_TRUE(isWhitespace(' '));
EXPECT_TRUE(isWhitespace('\t'));
EXPECT_TRUE(isWhitespace('\f'));
EXPECT_TRUE(isWhitespace('\v'));
EXPECT_TRUE(isWhitespace('\n'));
EXPECT_TRUE(isWhitespace('\r'));
EXPECT_FALSE(isWhitespace('\x80'));
EXPECT_FALSE(isWhitespace('\xc2'));
EXPECT_FALSE(isWhitespace('\xff'));
}
TEST(CharInfoTest, isDigit) {
EXPECT_TRUE(isDigit('0'));
EXPECT_TRUE(isDigit('9'));
EXPECT_FALSE(isDigit('a'));
EXPECT_FALSE(isDigit('A'));
EXPECT_FALSE(isDigit('z'));
EXPECT_FALSE(isDigit('Z'));
EXPECT_FALSE(isDigit('.'));
EXPECT_FALSE(isDigit('_'));
EXPECT_FALSE(isDigit('/'));
EXPECT_FALSE(isDigit('\0'));
EXPECT_FALSE(isDigit('\x80'));
EXPECT_FALSE(isDigit('\xc2'));
EXPECT_FALSE(isDigit('\xff'));
}
TEST(CharInfoTest, isHexDigit) {
EXPECT_TRUE(isHexDigit('0'));
EXPECT_TRUE(isHexDigit('9'));
EXPECT_TRUE(isHexDigit('a'));
EXPECT_TRUE(isHexDigit('A'));
EXPECT_FALSE(isHexDigit('z'));
EXPECT_FALSE(isHexDigit('Z'));
EXPECT_FALSE(isHexDigit('.'));
EXPECT_FALSE(isHexDigit('_'));
EXPECT_FALSE(isHexDigit('/'));
EXPECT_FALSE(isHexDigit('\0'));
EXPECT_FALSE(isHexDigit('\x80'));
EXPECT_FALSE(isHexDigit('\xc2'));
EXPECT_FALSE(isHexDigit('\xff'));
}
TEST(CharInfoTest, isLetter) {
EXPECT_FALSE(isLetter('0'));
EXPECT_FALSE(isLetter('9'));
EXPECT_TRUE(isLetter('a'));
EXPECT_TRUE(isLetter('A'));
EXPECT_TRUE(isLetter('z'));
EXPECT_TRUE(isLetter('Z'));
EXPECT_FALSE(isLetter('.'));
EXPECT_FALSE(isLetter('_'));
EXPECT_FALSE(isLetter('/'));
EXPECT_FALSE(isLetter('('));
EXPECT_FALSE(isLetter('\0'));
EXPECT_FALSE(isLetter('\x80'));
EXPECT_FALSE(isLetter('\xc2'));
EXPECT_FALSE(isLetter('\xff'));
}
TEST(CharInfoTest, isLowercase) {
EXPECT_FALSE(isLowercase('0'));
EXPECT_FALSE(isLowercase('9'));
EXPECT_TRUE(isLowercase('a'));
EXPECT_FALSE(isLowercase('A'));
EXPECT_TRUE(isLowercase('z'));
EXPECT_FALSE(isLowercase('Z'));
EXPECT_FALSE(isLowercase('.'));
EXPECT_FALSE(isLowercase('_'));
EXPECT_FALSE(isLowercase('/'));
EXPECT_FALSE(isLowercase('('));
EXPECT_FALSE(isLowercase('\0'));
EXPECT_FALSE(isLowercase('\x80'));
EXPECT_FALSE(isLowercase('\xc2'));
EXPECT_FALSE(isLowercase('\xff'));
}
TEST(CharInfoTest, isUppercase) {
EXPECT_FALSE(isUppercase('0'));
EXPECT_FALSE(isUppercase('9'));
EXPECT_FALSE(isUppercase('a'));
EXPECT_TRUE(isUppercase('A'));
EXPECT_FALSE(isUppercase('z'));
EXPECT_TRUE(isUppercase('Z'));
EXPECT_FALSE(isUppercase('.'));
EXPECT_FALSE(isUppercase('_'));
EXPECT_FALSE(isUppercase('/'));
EXPECT_FALSE(isUppercase('('));
EXPECT_FALSE(isUppercase('\0'));
EXPECT_FALSE(isUppercase('\x80'));
EXPECT_FALSE(isUppercase('\xc2'));
EXPECT_FALSE(isUppercase('\xff'));
}
TEST(CharInfoTest, isAlphanumeric) {
EXPECT_TRUE(isAlphanumeric('0'));
EXPECT_TRUE(isAlphanumeric('9'));
EXPECT_TRUE(isAlphanumeric('a'));
EXPECT_TRUE(isAlphanumeric('A'));
EXPECT_TRUE(isAlphanumeric('z'));
EXPECT_TRUE(isAlphanumeric('Z'));
EXPECT_FALSE(isAlphanumeric('.'));
EXPECT_FALSE(isAlphanumeric('_'));
EXPECT_FALSE(isAlphanumeric('/'));
EXPECT_FALSE(isAlphanumeric('('));
EXPECT_FALSE(isAlphanumeric('\0'));
EXPECT_FALSE(isAlphanumeric('\x80'));
EXPECT_FALSE(isAlphanumeric('\xc2'));
EXPECT_FALSE(isAlphanumeric('\xff'));
}
TEST(CharInfoTest, isPunctuation) {
EXPECT_FALSE(isPunctuation('0'));
EXPECT_FALSE(isPunctuation('9'));
EXPECT_FALSE(isPunctuation('a'));
EXPECT_FALSE(isPunctuation('A'));
EXPECT_FALSE(isPunctuation('z'));
EXPECT_FALSE(isPunctuation('Z'));
EXPECT_TRUE(isPunctuation('.'));
EXPECT_TRUE(isPunctuation('_'));
EXPECT_TRUE(isPunctuation('/'));
EXPECT_TRUE(isPunctuation('('));
EXPECT_FALSE(isPunctuation(' '));
EXPECT_FALSE(isPunctuation('\n'));
EXPECT_FALSE(isPunctuation('\0'));
EXPECT_FALSE(isPunctuation('\x80'));
EXPECT_FALSE(isPunctuation('\xc2'));
EXPECT_FALSE(isPunctuation('\xff'));
}
TEST(CharInfoTest, isPrintable) {
EXPECT_TRUE(isPrintable('0'));
EXPECT_TRUE(isPrintable('9'));
EXPECT_TRUE(isPrintable('a'));
EXPECT_TRUE(isPrintable('A'));
EXPECT_TRUE(isPrintable('z'));
EXPECT_TRUE(isPrintable('Z'));
EXPECT_TRUE(isPrintable('.'));
EXPECT_TRUE(isPrintable('_'));
EXPECT_TRUE(isPrintable('/'));
EXPECT_TRUE(isPrintable('('));
EXPECT_TRUE(isPrintable(' '));
EXPECT_FALSE(isPrintable('\t'));
EXPECT_FALSE(isPrintable('\n'));
EXPECT_FALSE(isPrintable('\0'));
EXPECT_FALSE(isPrintable('\x80'));
EXPECT_FALSE(isPrintable('\xc2'));
EXPECT_FALSE(isPrintable('\xff'));
}
TEST(CharInfoTest, isPreprocessingNumberBody) {
EXPECT_TRUE(isPreprocessingNumberBody('0'));
EXPECT_TRUE(isPreprocessingNumberBody('9'));
EXPECT_TRUE(isPreprocessingNumberBody('a'));
EXPECT_TRUE(isPreprocessingNumberBody('A'));
EXPECT_TRUE(isPreprocessingNumberBody('z'));
EXPECT_TRUE(isPreprocessingNumberBody('Z'));
EXPECT_TRUE(isPreprocessingNumberBody('.'));
EXPECT_TRUE(isPreprocessingNumberBody('_'));
EXPECT_FALSE(isPreprocessingNumberBody('/'));
EXPECT_FALSE(isPreprocessingNumberBody('('));
EXPECT_FALSE(isPreprocessingNumberBody('\0'));
EXPECT_FALSE(isPreprocessingNumberBody('\x80'));
EXPECT_FALSE(isPreprocessingNumberBody('\xc2'));
EXPECT_FALSE(isPreprocessingNumberBody('\xff'));
}
TEST(CharInfoTest, isRawStringDelimBody) {
EXPECT_TRUE(isRawStringDelimBody('0'));
EXPECT_TRUE(isRawStringDelimBody('9'));
EXPECT_TRUE(isRawStringDelimBody('a'));
EXPECT_TRUE(isRawStringDelimBody('A'));
EXPECT_TRUE(isRawStringDelimBody('z'));
EXPECT_TRUE(isRawStringDelimBody('Z'));
EXPECT_TRUE(isRawStringDelimBody('.'));
EXPECT_TRUE(isRawStringDelimBody('_'));
EXPECT_TRUE(isRawStringDelimBody('/'));
EXPECT_FALSE(isRawStringDelimBody('('));
EXPECT_FALSE(isRawStringDelimBody('\0'));
EXPECT_FALSE(isRawStringDelimBody('\x80'));
EXPECT_FALSE(isRawStringDelimBody('\xc2'));
EXPECT_FALSE(isRawStringDelimBody('\xff'));
}
TEST(CharInfoTest, toLowercase) {
EXPECT_EQ('0', toLowercase('0'));
EXPECT_EQ('9', toLowercase('9'));
EXPECT_EQ('a', toLowercase('a'));
EXPECT_EQ('a', toLowercase('A'));
EXPECT_EQ('z', toLowercase('z'));
EXPECT_EQ('z', toLowercase('Z'));
EXPECT_EQ('.', toLowercase('.'));
EXPECT_EQ('_', toLowercase('_'));
EXPECT_EQ('/', toLowercase('/'));
EXPECT_EQ('\0', toLowercase('\0'));
}
TEST(CharInfoTest, toUppercase) {
EXPECT_EQ('0', toUppercase('0'));
EXPECT_EQ('9', toUppercase('9'));
EXPECT_EQ('A', toUppercase('a'));
EXPECT_EQ('A', toUppercase('A'));
EXPECT_EQ('Z', toUppercase('z'));
EXPECT_EQ('Z', toUppercase('Z'));
EXPECT_EQ('.', toUppercase('.'));
EXPECT_EQ('_', toUppercase('_'));
EXPECT_EQ('/', toUppercase('/'));
EXPECT_EQ('\0', toUppercase('\0'));
}
TEST(CharInfoTest, isValidIdentifier) {
EXPECT_FALSE(isValidIdentifier(""));
// 1 character
EXPECT_FALSE(isValidIdentifier("."));
EXPECT_FALSE(isValidIdentifier("\n"));
EXPECT_FALSE(isValidIdentifier(" "));
EXPECT_FALSE(isValidIdentifier("\x80"));
EXPECT_FALSE(isValidIdentifier("\xc2"));
EXPECT_FALSE(isValidIdentifier("\xff"));
EXPECT_FALSE(isValidIdentifier("$"));
EXPECT_FALSE(isValidIdentifier("1"));
EXPECT_TRUE(isValidIdentifier("_"));
EXPECT_TRUE(isValidIdentifier("a"));
EXPECT_TRUE(isValidIdentifier("z"));
EXPECT_TRUE(isValidIdentifier("A"));
EXPECT_TRUE(isValidIdentifier("Z"));
// 2 characters, '_' suffix
EXPECT_FALSE(isValidIdentifier("._"));
EXPECT_FALSE(isValidIdentifier("\n_"));
EXPECT_FALSE(isValidIdentifier(" _"));
EXPECT_FALSE(isValidIdentifier("\x80_"));
EXPECT_FALSE(isValidIdentifier("\xc2_"));
EXPECT_FALSE(isValidIdentifier("\xff_"));
EXPECT_FALSE(isValidIdentifier("$_"));
EXPECT_FALSE(isValidIdentifier("1_"));
EXPECT_TRUE(isValidIdentifier("__"));
EXPECT_TRUE(isValidIdentifier("a_"));
EXPECT_TRUE(isValidIdentifier("z_"));
EXPECT_TRUE(isValidIdentifier("A_"));
EXPECT_TRUE(isValidIdentifier("Z_"));
// 2 characters, '_' prefix
EXPECT_FALSE(isValidIdentifier("_."));
EXPECT_FALSE(isValidIdentifier("_\n"));
EXPECT_FALSE(isValidIdentifier("_ "));
EXPECT_FALSE(isValidIdentifier("_\x80"));
EXPECT_FALSE(isValidIdentifier("_\xc2"));
EXPECT_FALSE(isValidIdentifier("_\xff"));
EXPECT_FALSE(isValidIdentifier("_$"));
EXPECT_TRUE(isValidIdentifier("_1"));
EXPECT_TRUE(isValidIdentifier("__"));
EXPECT_TRUE(isValidIdentifier("_a"));
EXPECT_TRUE(isValidIdentifier("_z"));
EXPECT_TRUE(isValidIdentifier("_A"));
EXPECT_TRUE(isValidIdentifier("_Z"));
// 3 characters, '__' prefix
EXPECT_FALSE(isValidIdentifier("__."));
EXPECT_FALSE(isValidIdentifier("__\n"));
EXPECT_FALSE(isValidIdentifier("__ "));
EXPECT_FALSE(isValidIdentifier("__\x80"));
EXPECT_FALSE(isValidIdentifier("__\xc2"));
EXPECT_FALSE(isValidIdentifier("__\xff"));
EXPECT_FALSE(isValidIdentifier("__$"));
EXPECT_TRUE(isValidIdentifier("__1"));
EXPECT_TRUE(isValidIdentifier("___"));
EXPECT_TRUE(isValidIdentifier("__a"));
EXPECT_TRUE(isValidIdentifier("__z"));
EXPECT_TRUE(isValidIdentifier("__A"));
EXPECT_TRUE(isValidIdentifier("__Z"));
// 3 characters, '_' prefix and suffix
EXPECT_FALSE(isValidIdentifier("_._"));
EXPECT_FALSE(isValidIdentifier("_\n_"));
EXPECT_FALSE(isValidIdentifier("_ _"));
EXPECT_FALSE(isValidIdentifier("_\x80_"));
EXPECT_FALSE(isValidIdentifier("_\xc2_"));
EXPECT_FALSE(isValidIdentifier("_\xff_"));
EXPECT_FALSE(isValidIdentifier("_$_"));
EXPECT_TRUE(isValidIdentifier("_1_"));
EXPECT_TRUE(isValidIdentifier("___"));
EXPECT_TRUE(isValidIdentifier("_a_"));
EXPECT_TRUE(isValidIdentifier("_z_"));
EXPECT_TRUE(isValidIdentifier("_A_"));
EXPECT_TRUE(isValidIdentifier("_Z_"));
}

View File

@@ -0,0 +1,97 @@
//===- unittests/Basic/DiagnosticTest.cpp -- Diagnostic engine tests ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticError.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
namespace {
// Check that DiagnosticErrorTrap works with SuppressAllDiagnostics.
TEST(DiagnosticTest, suppressAndTrap) {
DiagnosticsEngine Diags(new DiagnosticIDs(),
new DiagnosticOptions,
new IgnoringDiagConsumer());
Diags.setSuppressAllDiagnostics(true);
{
DiagnosticErrorTrap trap(Diags);
// Diag that would set UncompilableErrorOccurred and ErrorOccurred.
Diags.Report(diag::err_target_unknown_triple) << "unknown";
// Diag that would set UnrecoverableErrorOccurred and ErrorOccurred.
Diags.Report(diag::err_cannot_open_file) << "file" << "error";
// Diag that would set FatalErrorOccurred
// (via non-note following a fatal error).
Diags.Report(diag::warn_mt_message) << "warning";
EXPECT_TRUE(trap.hasErrorOccurred());
EXPECT_TRUE(trap.hasUnrecoverableErrorOccurred());
}
EXPECT_FALSE(Diags.hasErrorOccurred());
EXPECT_FALSE(Diags.hasFatalErrorOccurred());
EXPECT_FALSE(Diags.hasUncompilableErrorOccurred());
EXPECT_FALSE(Diags.hasUnrecoverableErrorOccurred());
}
// Check that SuppressAfterFatalError works as intended
TEST(DiagnosticTest, suppressAfterFatalError) {
for (unsigned Suppress = 0; Suppress != 2; ++Suppress) {
DiagnosticsEngine Diags(new DiagnosticIDs(),
new DiagnosticOptions,
new IgnoringDiagConsumer());
Diags.setSuppressAfterFatalError(Suppress);
// Diag that would set UnrecoverableErrorOccurred and ErrorOccurred.
Diags.Report(diag::err_cannot_open_file) << "file" << "error";
// Diag that would set FatalErrorOccurred
// (via non-note following a fatal error).
Diags.Report(diag::warn_mt_message) << "warning";
EXPECT_TRUE(Diags.hasErrorOccurred());
EXPECT_TRUE(Diags.hasFatalErrorOccurred());
EXPECT_TRUE(Diags.hasUncompilableErrorOccurred());
EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred());
// The warning should be emitted and counted only if we're not suppressing
// after fatal errors.
EXPECT_EQ(Diags.getNumWarnings(), Suppress ? 0u : 1u);
}
}
TEST(DiagnosticTest, diagnosticError) {
DiagnosticsEngine Diags(new DiagnosticIDs(), new DiagnosticOptions,
new IgnoringDiagConsumer());
PartialDiagnostic::StorageAllocator Alloc;
llvm::Expected<std::pair<int, int>> Value = DiagnosticError::create(
SourceLocation(), PartialDiagnostic(diag::err_cannot_open_file, Alloc)
<< "file"
<< "error");
ASSERT_TRUE(!Value);
llvm::Error Err = Value.takeError();
Optional<PartialDiagnosticAt> ErrDiag = DiagnosticError::take(Err);
llvm::cantFail(std::move(Err));
ASSERT_FALSE(!ErrDiag);
EXPECT_EQ(ErrDiag->first, SourceLocation());
EXPECT_EQ(ErrDiag->second.getDiagID(), diag::err_cannot_open_file);
Value = std::make_pair(20, 1);
ASSERT_FALSE(!Value);
EXPECT_EQ(*Value, std::make_pair(20, 1));
EXPECT_EQ(Value->first, 20);
}
}

View File

@@ -0,0 +1,326 @@
//===- unittests/Basic/FileMangerTest.cpp ------------ FileManger tests ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "clang/Basic/VirtualFileSystem.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Path.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
namespace {
// Used to create a fake file system for running the tests with such
// that the tests are not affected by the structure/contents of the
// file system on the machine running the tests.
class FakeStatCache : public FileSystemStatCache {
private:
// Maps a file/directory path to its desired stat result. Anything
// not in this map is considered to not exist in the file system.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
#ifndef LLVM_ON_WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
#endif
FileData Data;
Data.Name = Path;
Data.Size = 0;
Data.ModTime = 0;
Data.UniqueID = llvm::sys::fs::UniqueID(1, INode);
Data.IsDirectory = !IsFile;
Data.IsNamedPipe = false;
Data.InPCH = false;
StatCalls[Path] = Data;
}
public:
// Inject a file with the given inode value to the fake file system.
void InjectFile(const char *Path, ino_t INode) {
InjectFileOrDirectory(Path, INode, /*IsFile=*/true);
}
// Inject a directory with the given inode value to the fake file system.
void InjectDirectory(const char *Path, ino_t INode) {
InjectFileOrDirectory(Path, INode, /*IsFile=*/false);
}
// Implement FileSystemStatCache::getStat().
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<vfs::File> *F,
vfs::FileSystem &FS) override {
#ifndef LLVM_ON_WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
#endif
if (StatCalls.count(Path) != 0) {
Data = StatCalls[Path];
return CacheExists;
}
return CacheMissing; // This means the file/directory doesn't exist.
}
};
// The test fixture.
class FileManagerTest : public ::testing::Test {
protected:
FileManagerTest() : manager(options) {
}
FileSystemOptions options;
FileManager manager;
};
// When a virtual file is added, its getDir() field is set correctly
// (not NULL, correct name).
TEST_F(FileManagerTest, getVirtualFileSetsTheDirFieldCorrectly) {
const FileEntry *file = manager.getVirtualFile("foo.cpp", 42, 0);
ASSERT_TRUE(file != nullptr);
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ(".", dir->getName());
file = manager.getVirtualFile("x/y/z.cpp", 42, 0);
ASSERT_TRUE(file != nullptr);
dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("x/y", dir->getName());
}
// Before any virtual file is added, no virtual directory exists.
TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
// An empty FakeStatCache causes all stat calls made by the
// FileManager to report "file/directory doesn't exist". This
// avoids the possibility of the result of this test being affected
// by what's in the real file system.
manager.addStatCache(llvm::make_unique<FakeStatCache>());
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir"));
EXPECT_EQ(nullptr, manager.getDirectory("virtual"));
}
// When a virtual file is added, all of its ancestors should be created.
TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
// Fake an empty real file system.
manager.addStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
const DirectoryEntry *dir = manager.getDirectory("virtual/dir");
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual/dir", dir->getName());
dir = manager.getDirectory("virtual");
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual", dir->getName());
}
// getFile() returns non-NULL if a real file exists at the given path.
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("/tmp", 42);
statCache->InjectFile("/tmp/test", 43);
#ifdef LLVM_ON_WIN32
const char *DirName = "C:.";
const char *FileName = "C:test";
statCache->InjectDirectory(DirName, 44);
statCache->InjectFile(FileName, 45);
#endif
manager.addStatCache(std::move(statCache));
const FileEntry *file = manager.getFile("/tmp/test");
ASSERT_TRUE(file != nullptr);
ASSERT_TRUE(file->isValid());
EXPECT_EQ("/tmp/test", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("/tmp", dir->getName());
#ifdef LLVM_ON_WIN32
file = manager.getFile(FileName);
ASSERT_TRUE(file != NULL);
dir = file->getDir();
ASSERT_TRUE(dir != NULL);
EXPECT_EQ(DirName, dir->getName());
#endif
}
// getFile() returns non-NULL if a virtual file exists at the given path.
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
// Fake an empty real file system.
manager.addStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
const FileEntry *file = manager.getFile("virtual/dir/bar.h");
ASSERT_TRUE(file != nullptr);
ASSERT_TRUE(file->isValid());
EXPECT_EQ("virtual/dir/bar.h", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual/dir", dir->getName());
}
// getFile() returns different FileEntries for different paths when
// there's no aliasing.
TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) {
// Inject two fake files into the file system. Different inodes
// mean the files are not symlinked together.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
statCache->InjectFile("bar.cpp", 43);
manager.addStatCache(std::move(statCache));
const FileEntry *fileFoo = manager.getFile("foo.cpp");
const FileEntry *fileBar = manager.getFile("bar.cpp");
ASSERT_TRUE(fileFoo != nullptr);
ASSERT_TRUE(fileFoo->isValid());
ASSERT_TRUE(fileBar != nullptr);
ASSERT_TRUE(fileBar->isValid());
EXPECT_NE(fileFoo, fileBar);
}
// getFile() returns NULL if neither a real file nor a virtual file
// exists at the given path.
TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
// Inject a fake foo.cpp into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
manager.addStatCache(std::move(statCache));
// Create a virtual bar.cpp file.
manager.getVirtualFile("bar.cpp", 200, 0);
const FileEntry *file = manager.getFile("xyz.txt");
EXPECT_EQ(nullptr, file);
}
// The following tests apply to Unix-like system only.
#ifndef LLVM_ON_WIN32
// getFile() returns the same FileEntry for real files that are aliases.
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
// Inject two real files with the same inode.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
manager.addStatCache(std::move(statCache));
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
// getFile() returns the same FileEntry for virtual files that have
// corresponding real files that are aliases.
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
// Inject two real files with the same inode.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
manager.addStatCache(std::move(statCache));
ASSERT_TRUE(manager.getVirtualFile("abc/foo.cpp", 100, 0)->isValid());
ASSERT_TRUE(manager.getVirtualFile("abc/bar.cpp", 200, 0)->isValid());
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
TEST_F(FileManagerTest, addRemoveStatCache) {
manager.addStatCache(llvm::make_unique<FakeStatCache>());
auto statCacheOwner = llvm::make_unique<FakeStatCache>();
auto *statCache = statCacheOwner.get();
manager.addStatCache(std::move(statCacheOwner));
manager.addStatCache(llvm::make_unique<FakeStatCache>());
manager.removeStatCache(statCache);
}
// getFile() Should return the same entry as getVirtualFile if the file actually
// is a virtual file, even if the name is not exactly the same (but is after
// normalisation done by the file system, like on Windows). This can be checked
// here by checkng the size.
TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("c:\\tmp", 42);
statCache->InjectFile("c:\\tmp\\test", 43);
manager.addStatCache(std::move(statCache));
// Inject the virtual file:
const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1);
ASSERT_TRUE(file1 != nullptr);
ASSERT_TRUE(file1->isValid());
EXPECT_EQ(43U, file1->getUniqueID().getFile());
EXPECT_EQ(123, file1->getSize());
// Lookup the virtual file with a different name:
const FileEntry *file2 = manager.getFile("c:/tmp/test", 100, 1);
ASSERT_TRUE(file2 != nullptr);
ASSERT_TRUE(file2->isValid());
// Check that it's the same UFE:
EXPECT_EQ(file1, file2);
EXPECT_EQ(43U, file2->getUniqueID().getFile());
// Check that the contents of the UFE are not overwritten by the entry in the
// filesystem:
EXPECT_EQ(123, file2->getSize());
}
#endif // !LLVM_ON_WIN32
TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
SmallString<64> CustomWorkingDir;
#ifdef LLVM_ON_WIN32
CustomWorkingDir = "C:";
#else
CustomWorkingDir = "/";
#endif
llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
auto FS =
IntrusiveRefCntPtr<vfs::InMemoryFileSystem>(new vfs::InMemoryFileSystem);
// setCurrentworkingdirectory must finish without error.
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
FileSystemOptions Opts;
FileManager Manager(Opts, FS);
SmallString<64> Path("a/foo.cpp");
SmallString<64> ExpectedResult(CustomWorkingDir);
llvm::sys::path::append(ExpectedResult, Path);
ASSERT_TRUE(Manager.makeAbsolutePath(Path));
EXPECT_EQ(Path, ExpectedResult);
}
} // anonymous namespace

View File

@@ -0,0 +1,94 @@
//===- MemoryBufferCacheTest.cpp - MemoryBufferCache tests ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/MemoryBufferCache.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
namespace {
std::unique_ptr<MemoryBuffer> getBuffer(int I) {
SmallVector<char, 8> Bytes;
raw_svector_ostream(Bytes) << "data:" << I;
return MemoryBuffer::getMemBuffer(StringRef(Bytes.data(), Bytes.size()), "",
/* RequiresNullTerminator = */ false);
}
TEST(MemoryBufferCacheTest, addBuffer) {
auto B1 = getBuffer(1);
auto B2 = getBuffer(2);
auto B3 = getBuffer(3);
auto *RawB1 = B1.get();
auto *RawB2 = B2.get();
auto *RawB3 = B3.get();
// Add a few buffers.
MemoryBufferCache Cache;
EXPECT_EQ(RawB1, &Cache.addBuffer("1", std::move(B1)));
EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
EXPECT_EQ(RawB3, &Cache.addBuffer("3", std::move(B3)));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
EXPECT_EQ(RawB3, Cache.lookupBuffer("3"));
EXPECT_FALSE(Cache.isBufferFinal("1"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
EXPECT_FALSE(Cache.isBufferFinal("3"));
// Remove the middle buffer.
EXPECT_FALSE(Cache.tryToRemoveBuffer("2"));
EXPECT_EQ(nullptr, Cache.lookupBuffer("2"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
// Replace the middle buffer.
B2 = getBuffer(2);
RawB2 = B2.get();
EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
// Check that nothing is final.
EXPECT_FALSE(Cache.isBufferFinal("1"));
EXPECT_FALSE(Cache.isBufferFinal("2"));
EXPECT_FALSE(Cache.isBufferFinal("3"));
}
TEST(MemoryBufferCacheTest, finalizeCurrentBuffers) {
// Add a buffer.
MemoryBufferCache Cache;
auto B1 = getBuffer(1);
auto *RawB1 = B1.get();
Cache.addBuffer("1", std::move(B1));
ASSERT_FALSE(Cache.isBufferFinal("1"));
// Finalize it.
Cache.finalizeCurrentBuffers();
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_TRUE(Cache.isBufferFinal("1"));
// Repeat.
auto B2 = getBuffer(2);
auto *RawB2 = B2.get();
Cache.addBuffer("2", std::move(B2));
EXPECT_FALSE(Cache.isBufferFinal("2"));
Cache.finalizeCurrentBuffers();
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.isBufferFinal("2"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
EXPECT_TRUE(Cache.tryToRemoveBuffer("2"));
EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
EXPECT_TRUE(Cache.isBufferFinal("1"));
EXPECT_TRUE(Cache.isBufferFinal("2"));
}
} // namespace

View File

@@ -0,0 +1,382 @@
//===- unittests/Basic/SourceManagerTest.cpp ------ SourceManager tests ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/MemoryBufferCache.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
#include "gtest/gtest.h"
using namespace clang;
namespace {
// The test fixture.
class SourceManagerTest : public ::testing::Test {
protected:
SourceManagerTest()
: FileMgr(FileMgrOpts),
DiagID(new DiagnosticIDs()),
Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr),
TargetOpts(new TargetOptions) {
TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
}
FileSystemOptions FileMgrOpts;
FileManager FileMgr;
IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
DiagnosticsEngine Diags;
SourceManager SourceMgr;
LangOptions LangOpts;
std::shared_ptr<TargetOptions> TargetOpts;
IntrusiveRefCntPtr<TargetInfo> Target;
};
TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
const char *source =
"#define M(x) [x]\n"
"M(foo)";
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(source);
FileID mainFileID = SourceMgr.createFileID(std::move(Buf));
SourceMgr.setMainFileID(mainFileID);
TrivialModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
PP.Initialize(*Target);
PP.EnterMainSourceFile();
std::vector<Token> toks;
while (1) {
Token tok;
PP.Lex(tok);
if (tok.is(tok::eof))
break;
toks.push_back(tok);
}
// Make sure we got the tokens that we expected.
ASSERT_EQ(3U, toks.size());
ASSERT_EQ(tok::l_square, toks[0].getKind());
ASSERT_EQ(tok::identifier, toks[1].getKind());
ASSERT_EQ(tok::r_square, toks[2].getKind());
SourceLocation lsqrLoc = toks[0].getLocation();
SourceLocation idLoc = toks[1].getLocation();
SourceLocation rsqrLoc = toks[2].getLocation();
SourceLocation macroExpStartLoc = SourceMgr.translateLineCol(mainFileID, 2, 1);
SourceLocation macroExpEndLoc = SourceMgr.translateLineCol(mainFileID, 2, 6);
ASSERT_TRUE(macroExpStartLoc.isFileID());
ASSERT_TRUE(macroExpEndLoc.isFileID());
SmallString<32> str;
ASSERT_EQ("M", PP.getSpelling(macroExpStartLoc, str));
ASSERT_EQ(")", PP.getSpelling(macroExpEndLoc, str));
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(lsqrLoc, idLoc));
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, rsqrLoc));
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(macroExpStartLoc, idLoc));
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, macroExpEndLoc));
}
TEST_F(SourceManagerTest, getColumnNumber) {
const char *Source =
"int x;\n"
"int y;";
std::unique_ptr<llvm::MemoryBuffer> Buf =
llvm::MemoryBuffer::getMemBuffer(Source);
FileID MainFileID = SourceMgr.createFileID(std::move(Buf));
SourceMgr.setMainFileID(MainFileID);
bool Invalid;
Invalid = false;
EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, &Invalid));
EXPECT_TRUE(!Invalid);
Invalid = false;
EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 4, &Invalid));
EXPECT_TRUE(!Invalid);
Invalid = false;
EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 7, &Invalid));
EXPECT_TRUE(!Invalid);
Invalid = false;
EXPECT_EQ(5U, SourceMgr.getColumnNumber(MainFileID, 11, &Invalid));
EXPECT_TRUE(!Invalid);
Invalid = false;
EXPECT_EQ(7U, SourceMgr.getColumnNumber(MainFileID, strlen(Source),
&Invalid));
EXPECT_TRUE(!Invalid);
Invalid = false;
SourceMgr.getColumnNumber(MainFileID, strlen(Source)+1, &Invalid);
EXPECT_TRUE(Invalid);
// Test invalid files
Invalid = false;
SourceMgr.getColumnNumber(FileID(), 0, &Invalid);
EXPECT_TRUE(Invalid);
Invalid = false;
SourceMgr.getColumnNumber(FileID(), 1, &Invalid);
EXPECT_TRUE(Invalid);
// Test with no invalid flag.
EXPECT_EQ(1U, SourceMgr.getColumnNumber(MainFileID, 0, nullptr));
}
#if defined(LLVM_ON_UNIX)
TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
const char *header =
"#define FM(x,y) x\n";
const char *main =
"#include \"/test-header.h\"\n"
"#define VAL 0\n"
"FM(VAL,0)\n"
"FM(0,VAL)\n"
"FM(FM(0,VAL),0)\n"
"#define CONCAT(X, Y) X##Y\n"
"CONCAT(1,1)\n";
std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
llvm::MemoryBuffer::getMemBuffer(header);
std::unique_ptr<llvm::MemoryBuffer> MainBuf =
llvm::MemoryBuffer::getMemBuffer(main);
FileID mainFileID = SourceMgr.createFileID(std::move(MainBuf));
SourceMgr.setMainFileID(mainFileID);
const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
HeaderBuf->getBufferSize(), 0);
SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
TrivialModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
PP.Initialize(*Target);
PP.EnterMainSourceFile();
std::vector<Token> toks;
while (1) {
Token tok;
PP.Lex(tok);
if (tok.is(tok::eof))
break;
toks.push_back(tok);
}
// Make sure we got the tokens that we expected.
ASSERT_EQ(4U, toks.size());
ASSERT_EQ(tok::numeric_constant, toks[0].getKind());
ASSERT_EQ(tok::numeric_constant, toks[1].getKind());
ASSERT_EQ(tok::numeric_constant, toks[2].getKind());
ASSERT_EQ(tok::numeric_constant, toks[3].getKind());
SourceLocation defLoc = SourceMgr.translateLineCol(mainFileID, 2, 13);
SourceLocation loc1 = SourceMgr.translateLineCol(mainFileID, 3, 8);
SourceLocation loc2 = SourceMgr.translateLineCol(mainFileID, 4, 4);
SourceLocation loc3 = SourceMgr.translateLineCol(mainFileID, 5, 7);
SourceLocation defLoc2 = SourceMgr.translateLineCol(mainFileID, 6, 22);
defLoc = SourceMgr.getMacroArgExpandedLocation(defLoc);
loc1 = SourceMgr.getMacroArgExpandedLocation(loc1);
loc2 = SourceMgr.getMacroArgExpandedLocation(loc2);
loc3 = SourceMgr.getMacroArgExpandedLocation(loc3);
defLoc2 = SourceMgr.getMacroArgExpandedLocation(defLoc2);
EXPECT_TRUE(defLoc.isFileID());
EXPECT_TRUE(loc1.isFileID());
EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc2));
EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc3));
EXPECT_EQ(loc2, toks[1].getLocation());
EXPECT_EQ(loc3, toks[2].getLocation());
EXPECT_TRUE(defLoc2.isFileID());
}
namespace {
struct MacroAction {
enum Kind { kExpansion, kDefinition, kUnDefinition};
SourceLocation Loc;
std::string Name;
unsigned MAKind : 3;
MacroAction(SourceLocation Loc, StringRef Name, unsigned K)
: Loc(Loc), Name(Name), MAKind(K) { }
bool isExpansion() const { return MAKind == kExpansion; }
bool isDefinition() const { return MAKind & kDefinition; }
bool isUnDefinition() const { return MAKind & kUnDefinition; }
};
class MacroTracker : public PPCallbacks {
std::vector<MacroAction> &Macros;
public:
explicit MacroTracker(std::vector<MacroAction> &Macros) : Macros(Macros) { }
void MacroDefined(const Token &MacroNameTok,
const MacroDirective *MD) override {
Macros.push_back(MacroAction(MD->getLocation(),
MacroNameTok.getIdentifierInfo()->getName(),
MacroAction::kDefinition));
}
void MacroUndefined(const Token &MacroNameTok,
const MacroDefinition &MD,
const MacroDirective *UD) override {
Macros.push_back(
MacroAction(UD ? UD->getLocation() : SourceLocation(),
MacroNameTok.getIdentifierInfo()->getName(),
UD ? MacroAction::kDefinition | MacroAction::kUnDefinition
: MacroAction::kUnDefinition));
}
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range, const MacroArgs *Args) override {
Macros.push_back(MacroAction(MacroNameTok.getLocation(),
MacroNameTok.getIdentifierInfo()->getName(),
MacroAction::kExpansion));
}
};
}
TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
const char *header =
"#define MACRO_IN_INCLUDE 0\n"
"#define MACRO_DEFINED\n"
"#undef MACRO_DEFINED\n"
"#undef MACRO_UNDEFINED\n";
const char *main =
"#define M(x) x\n"
"#define INC \"/test-header.h\"\n"
"#include M(INC)\n"
"#define INC2 </test-header.h>\n"
"#include M(INC2)\n";
std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
llvm::MemoryBuffer::getMemBuffer(header);
std::unique_ptr<llvm::MemoryBuffer> MainBuf =
llvm::MemoryBuffer::getMemBuffer(main);
SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
HeaderBuf->getBufferSize(), 0);
SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
TrivialModuleLoader ModLoader;
MemoryBufferCache PCMCache;
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
Diags, LangOpts, &*Target);
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
SourceMgr, PCMCache, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
PP.Initialize(*Target);
std::vector<MacroAction> Macros;
PP.addPPCallbacks(llvm::make_unique<MacroTracker>(Macros));
PP.EnterMainSourceFile();
std::vector<Token> toks;
while (1) {
Token tok;
PP.Lex(tok);
if (tok.is(tok::eof))
break;
toks.push_back(tok);
}
// Make sure we got the tokens that we expected.
ASSERT_EQ(0U, toks.size());
ASSERT_EQ(15U, Macros.size());
// #define M(x) x
ASSERT_TRUE(Macros[0].isDefinition());
ASSERT_EQ("M", Macros[0].Name);
// #define INC "/test-header.h"
ASSERT_TRUE(Macros[1].isDefinition());
ASSERT_EQ("INC", Macros[1].Name);
// M expansion in #include M(INC)
ASSERT_FALSE(Macros[2].isDefinition());
ASSERT_EQ("M", Macros[2].Name);
// INC expansion in #include M(INC)
ASSERT_TRUE(Macros[3].isExpansion());
ASSERT_EQ("INC", Macros[3].Name);
// #define MACRO_IN_INCLUDE 0
ASSERT_TRUE(Macros[4].isDefinition());
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
// #define MACRO_DEFINED
ASSERT_TRUE(Macros[5].isDefinition());
ASSERT_FALSE(Macros[5].isUnDefinition());
ASSERT_EQ("MACRO_DEFINED", Macros[5].Name);
// #undef MACRO_DEFINED
ASSERT_TRUE(Macros[6].isDefinition());
ASSERT_TRUE(Macros[6].isUnDefinition());
ASSERT_EQ("MACRO_DEFINED", Macros[6].Name);
// #undef MACRO_UNDEFINED
ASSERT_FALSE(Macros[7].isDefinition());
ASSERT_TRUE(Macros[7].isUnDefinition());
ASSERT_EQ("MACRO_UNDEFINED", Macros[7].Name);
// #define INC2 </test-header.h>
ASSERT_TRUE(Macros[8].isDefinition());
ASSERT_EQ("INC2", Macros[8].Name);
// M expansion in #include M(INC2)
ASSERT_FALSE(Macros[9].isDefinition());
ASSERT_EQ("M", Macros[9].Name);
// INC2 expansion in #include M(INC2)
ASSERT_TRUE(Macros[10].isExpansion());
ASSERT_EQ("INC2", Macros[10].Name);
// #define MACRO_IN_INCLUDE 0
ASSERT_TRUE(Macros[11].isDefinition());
ASSERT_EQ("MACRO_IN_INCLUDE", Macros[11].Name);
// The INC expansion in #include M(INC) comes before the first
// MACRO_IN_INCLUDE definition of the included file.
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[3].Loc, Macros[4].Loc));
// The INC2 expansion in #include M(INC2) comes before the second
// MACRO_IN_INCLUDE definition of the included file.
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
}
#endif
} // anonymous namespace

File diff suppressed because it is too large Load Diff