Fixed path differences when using include/exclude headers

Added function for removing relative operators from input paths.

llvm-svn: 187481
This commit is contained in:
Ariel J. Bernal 2013-07-31 04:00:28 +00:00
parent 3e0afb87b2
commit dec84e1139
2 changed files with 51 additions and 6 deletions

View File

@ -26,6 +26,9 @@ namespace {
/// \brief Helper function to determine whether a file has the same path /// \brief Helper function to determine whether a file has the same path
/// prefix as \a Path. /// prefix as \a Path.
/// ///
/// \a File shouldn't contain relative operators i.e. ".." or "." since Path
/// comes from the include/exclude list of paths in which relative operators
/// were removed.
/// \a Path must be an absolute path. /// \a Path must be an absolute path.
bool fileHasPathPrefix(StringRef File, StringRef Path) { bool fileHasPathPrefix(StringRef File, StringRef Path) {
// Converts File to its absolute path. // Converts File to its absolute path.
@ -48,6 +51,31 @@ bool fileHasPathPrefix(StringRef File, StringRef Path) {
return true; return true;
} }
/// \brief Helper function for removing relative operators from a given
/// path i.e. "..", ".".
std::string removeRelativeOperators(StringRef Path) {
sys::path::const_iterator PathI = sys::path::begin(Path);
sys::path::const_iterator PathE = sys::path::end(Path);
SmallVector<StringRef, 16> PathT;
while (PathI != PathE) {
if (PathI->equals("..")) {
// Test if we have reached the root then Path is invalid.
if (PathT.empty())
return "";
PathT.pop_back();
} else if (!PathI->equals("."))
PathT.push_back(*PathI);
++PathI;
}
// Rebuild the new path.
SmallString<64> NewPath;
for (SmallVectorImpl<StringRef>::iterator I = PathT.begin(), E = PathT.end();
I != E; ++I) {
llvm::sys::path::append(NewPath, *I);
}
return NewPath.str();
}
/// \brief Helper function to tokenize a string of paths and populate /// \brief Helper function to tokenize a string of paths and populate
/// the vector. /// the vector.
error_code parseCLInput(StringRef Line, std::vector<std::string> &List, error_code parseCLInput(StringRef Line, std::vector<std::string> &List,
@ -61,13 +89,13 @@ error_code parseCLInput(StringRef Line, std::vector<std::string> &List,
SmallString<64> Path = I->rtrim(); SmallString<64> Path = I->rtrim();
if (error_code Err = sys::fs::make_absolute(Path)) if (error_code Err = sys::fs::make_absolute(Path))
return Err; return Err;
// Remove relative operators from the path.
// sys::fs::make_absolute will turn "." into "<pwd>/.". Need to strip "/." std::string AbsPath = removeRelativeOperators(Path);
// off or it interferes with prefix checking. // Add only non-empty paths to the list.
if (Path.endswith("/.")) if (!AbsPath.empty())
List.push_back(Path.slice(0, Path.size() - 2).str()); List.push_back(AbsPath);
else else
List.push_back(Path.str()); llvm::errs() << "Unable to parse input path: " << *I << "\n";
llvm::errs() << "Parse: " <<List.back() << "\n"; llvm::errs() << "Parse: " <<List.back() << "\n";
} }

View File

@ -52,6 +52,23 @@ TEST(IncludeExcludeTest, ParseString) {
EXPECT_FALSE(IEManager.isFileIncluded("c/c2/c3/f.cpp")); EXPECT_FALSE(IEManager.isFileIncluded("c/c2/c3/f.cpp"));
} }
TEST(IncludeExcludeTest, ParseStringCases) {
IncludeExcludeInfo IEManager;
llvm::error_code Err = IEManager.readListFromString(
/*include=*/ "a/.,b/b2/,c/c2/c3/../../c4/,d/d2/./d3/,/e/e2/.",
/*exclude=*/ "");
ASSERT_EQ(Err, llvm::error_code::success());
EXPECT_TRUE(IEManager.isFileIncluded("a/f.cpp"));
EXPECT_TRUE(IEManager.isFileIncluded("b/b2/f.cpp"));
EXPECT_TRUE(IEManager.isFileIncluded("c/c4/f.cpp"));
EXPECT_TRUE(IEManager.isFileIncluded("d/d2/d3/f.cpp"));
EXPECT_TRUE(IEManager.isFileIncluded("/e/e2/f.cpp"));
EXPECT_FALSE(IEManager.isFileIncluded("c/c2/c3/f.cpp"));
}
// Utility for creating and filling files with data for IncludeExcludeFileTest // Utility for creating and filling files with data for IncludeExcludeFileTest
// tests. // tests.
struct InputFiles { struct InputFiles {